Looping/printing over a list in R - r

Let's suppose I have a simple list
v <- list(vec1=c(1,2,3), vec2=c(3,4,5, 6))
I would like to loop over this list and perform some function on its element, so that as an output I get both: name of that particular element and output of the function. For example:
for (i in v)
{print(sd(i))
}
In this case, the output is:
[1] 1
[1] 1.290994
But I would like to see something like this:
$vec1
[1] 1
$vec2
[1] 1.290994
So that I can easily spot to which element each output refers, if I have many elements within my list. I know it has sth with the function names() to do, but I can't make it work.

Using the function names() and outputting a list:
result<-list()
for (i in 1:length(v))
{result[[i]]=sd(v[[i]])
}
names(result)<-names(v)
The downside of this method is that it will assign the wrong names if the resulting list is smaller or greater than the original list (for example, if you add a next statement on the loop or otherwise skip an element).
If possible, a much easier solution is to follow d.b's comment.

Related

Convert R list to Pythonic list and output as a txt file

I'm trying to convert these lists like Python's list. I've used these codes
library(GenomicRanges)
library(data.table)
library(Repitools)
pcs_by_tile<-lapply(as.list(1:length(tiled_chr)) , function(x){
obj<-tileSplit[[as.character(x)]]
if(is.null(obj)){
return(0)
} else {
runs<-filtered_identical_seqs.gr[obj]
df <- annoGR2DF(runs)
score = split(df[,c("start","end")], 1:nrow(df[,c("start","end")]))
#print(score)
return(score)
}
})
dt_text <- unlist(lapply(tiled_chr$score, paste, collapse=","))
writeLines(tiled_chr, paste0("x.txt"))
The following line of code iterates through each row of the DataFrame (only 2 columns) and splits them into the list. However, its output is different from what I desired.
score = split(df[,c("start","end")], 1:nrow(df[,c("start","end")]))
But I wanted the following kinda output:
[20350, 20355], [20357, 20359], [20361, 20362], ........
If I understand your question correctly, using as.tuple from the package 'sets' might help. Here's what the code might look like
library(sets)
score = split(df[,c("start","end")], 1:nrow(df[,c("start","end")]))
....
df_text = unlist(lapply(score, as.tuple),recursive = F)
This will return a list of tuples (and zeroes) that look more like what you are looking for. You can filter out the zeroes by checking the type of each element in the resulting list and removing the ones that match the type. For example, you could do something like this
df_text_trimmed <- df_text[!lapply(df_text, is.double)]
to get rid of all your zeroes
Edit: Now that I think about it, you probably don't even need to convert your dataframes to tuples if you don't want to. You just need to make sure to include the 'recursive = F' option when you unlist things to get a list of 0s and dataframes containing the numbers you want.

How to name the elements of an unnamed list

I have a list that look like this:
setlist2 <- list(wsb_b6, wsb_id8)
[[1]]
[1] "Gm10116" "Tpm3-rs7" "Wdfy1" "Rps3a2" "AK157302" "Gm6563"
"Gm9825" "Gm10259" "Gm6768"
[[2]]
[1] "Gm6401" "Ecel1" "Hpca" "Tmem176a" "Lepr"
"Baiap3" "Fam183b" "Vsx2" "Vtn"
I need it to look like this:
$wsb_b6
[1] "Gm10116" "Tpm3-rs7" "Wdfy1" "Rps3a2" "AK157302" "Gm6563"
"Gm9825" "Gm10259" "Gm6768"
$wsb_id8
[1] "Gm6401" "Ecel1" "Hpca" "Tmem176a" "Lepr"
"Baiap3" "Fam183b" "Vsx2" "Vtn"
I know that by doing it manually I can achieve it but it is more that 100 each, there's got to be a better way
#I found that I had to unlist my two previous lists
wsb_b6 <-wsb_b6[,1]
wsb_b6 <-unlist(wsb_b6)
wsb_id8 <-wsb_id8[,1]
wsb_id8 <- unlist(wsb_id8)
#And then list them again, but like this
setlist2 <-list(wsb_b6=wsb_b6, wsb_id8= wsb_id8)
Use dplyr::lst
setlist2 <- dplyr::lst(wsb_b6, wsb_id8)
It sounds like you want to create a named list. Specifically, you want to create a named list where the names are taken from the names of the variables in the environment.
This is similar to this question: Can lists be created that name themselves based on input object names?
I don't believe there is a simple function to do this in base R, but you can using the function llist from the package Hmisc:
library(Hmisc)
setlist2 <- llist(wsb_b6, wsb_id8)

Writing a loop in R

I have written a loop in R. The code is expected to go through a list of variables defined in a list and then for each of the variables perform a function.
Problem 1 - I cannot loop through the list of variables
Problem 2 - I need to insert each output from the values into Mongo DB
Here is an example of the list:
121715771201463_626656620831011
121715771201463_1149346125105084
Based on this value - I am running a code and i want this output to be inserted into MongoDB. Right now only the first value and its corresponding output is inserted
test_list <-
C("121715771201463_626656620831011","121715771201463_1149346125105084","121715771201463_1149346125105999")
for (i in test_list)
{ //myfunction//
mongo.insert(mongo, DBNS, i)
}
I am able to only pick the values for the first value and not all from the list
Any help is appreciated.
Try this example, which prints the final characters
myfunction <- function(x){ print( substr(x, 27, nchar(x)) ) }
test_list <- c("121715771201463_626656620831011",
"121715771201463_1149346125105084",
"121715771201463_1149346125105999")
for (i in test_list){ myfunction(i) }
for (j in 1:length(test_list)){ myfunction(test_list[j]) }
The final two lines should each produce
[1] "31011"
[1] "105084"
[1] "105999"
It is not clear whether "variable" is the same as "value" here.
If what you mean by variable is actually an element in the list you construct, then I think Ilyas comment above may solve the issue.
If "variable" is instead an object in the workspace, and elements in the list are the names of the objects you want to process, then you need to make sure that you use get. Like this:
for(i in ls()){
cat(paste(mode(get(i)),"\n") )
}
ls() returns a list of names of objects. The loop above goes through them all, uses get on them to get the proper object. From there, you can do the processing you want to do (in the example above, I just printed the mode of the object).
Hope this helps somehow.

Create a list of integer vectors

let us say I want to create a list where each element is an integer vector.
Let us say I have,
a = c(1,2,3,4)
b = c(7,9,10,3)
d = c(90.2,43.1,54.2,12.3)
And I'd like a list where element 1 of the list is:
c(1,7,90.2)
Second element is,
c(2,9,43.1),
The third element is,
c(3,10,54.2),
and the 4th element is,
c(4,3,12.3).
If I do,
my.list = list(a=a,b=b,d=d)
gives me the transpose of what I want. Is there any direct way to achieve such goal?
I need to have a list because I want to use the mclapply function and that function only takes lists as input, or (if given dataframes) will coerce them to the non desired list structure.
Note that in my program this vectors are quite huge, 400 million entries or so. I am looking for a very fast and efficient way to do this. Thanks!
kk<-Map(function(x,y,w) c(x,y,w),a,b,d)
> kk[1]
[[1]]
[1] 1.0 7.0 90.2
Or just :
kk<-Map(`c`,a,b,d)
> kk[1]
[[1]]
[1] 1.0 7.0 90.2
Turn your vectors into one data.frame:
adf<-data.frame(a=a, b=b, d=d)
Then use apply to turn each row into a list element:
apply(adf, 1, function(x) list(x))

how do I get the difference between two R named lists?

OK, I've got two named lists, one is "expected" and one is "observed". They may be complex in structure, with arbitrary data types. I want to get a new list containing just those elements of the observed list that are different from what's in the expected list. Here's an example:
Lexp <- list(a=1, b="two", c=list(3, "four"))
Lobs <- list(a=1, c=list(3, "four"), b="ni")
Lwant <- list(b="ni")
Lwant is what I want the result to be. I tried this:
> setdiff(Lobs, Lexp)
[[1]]
[1] "ni"
Nope, that loses the name, and I don't think setdiff pays attention to the names. Order clearly doesn't matter here, and I don't want a=1 to match with b=1.
Not sure what a good approach is... Something that loops over a list of names(Lobs)? Sounds clumsy and non-R-like, although workable... Got any elegant ideas?
At least in this case
Lobs[!(Lobs %in% Lexp)]
gives you what you want.
OK, I found one slightly obtuse answer, using the plyr package:
> Lobs[laply(names(Lobs), function(x) !identical(Lobs[[x]], Lexp[[x]]))]
$b
[1] "ni"
So, it takes the names of the array from the observed function, uses double-bracket indexing and the identical() function to compare the sub-lists, then uses the binary array that results from laply() to index into the original observed function.
Anyone got a better/cleaner/sexier/faster way?

Resources