Consider the following list of lists:
lst = list(list(c(1,2), c(3,4)),list(c(5,6), c(7,8)),list(c(9,10), c(11,12)))
The list lst contains three lists, each list containing two vectors as elements. I would like to combine the elements of the underlying lists by index. In other words, I would like to merge vector 1 from list 1 with that of list 2 and list 3, and vector 2 from list 1 with that of list 2 and list 3, etc...
This is the result I am looking to achieve:
res = list(c(1,2,5,6,9,10), c(3,4,7,8,11,12))
I know that this can be achieved as follows in case of two separate lists:
mapply(c, lst1, lst2)
However, I am not sure how to replicate the same logic using a list of lists.
Any efficient way to achieve that? Please keep in mind that in reality, lst is a list of 5000 lists, and each underlying list contains a large number of vectors.
Thanks!
You can do:
do.call(Map, c(c, lst))
You're on the right track:
do.call(function(...) mapply(c,...,SIMPLIFY = FALSE),args = lst)
[[1]]
[1] 1 2 5 6 9 10
[[2]]
[1] 3 4 7 8 11 12
I was looking for something along the lines of the OP's question... but with a list of data frames instead of vectors. In that case, slightly modifying #joran's answer above gives the desired result. Consider:
mylist <-
lapply(1:2, function(y){
df1 <- data.frame(a=y, b=y^2, c=y^3)
df2 <- data.frame(d=y, e=y+1)
return(list(df1=df1, df2=df2))
})
You can then re-combine the sub-list elements into separate data frames based on their common indexes:
mylist2 <- do.call(function(...) Map("rbind", ...), mylist)
Related
I have a list of n vectors. I would like to split it to sub-list where the number of the vectors at each list is different. The number of the vectors is increased sequentially from one list to another. For example,
if I have a list with 6 vectors. Then, I would like to split it to several list as follows:
The first list contains one vector. Then, the second list contains 2 vectors and so on. For example,
Suppose I have the list x as follows:
x <- list(x1=c(1,2,3), x2=c(1,4,3), x3=c(3,4,6), x4=c(4,8,4), x5=c(4,33,4), x6=c(9,6,7))
Then, I would like to split it into 3 lists,
list1 = x1
list2 = list(x2, x3)
list3 = list(x4,x5, x6)
I have similar question (How to splitting a list of vectors to small lists in decreasing order in r) but in a decreasing order.
How I can generate it to arbitrary number of vectors. For example, how if I have 10 or 20 vectors?
Any idea, please?
I'd stick them all in a list of lists
MyLists <- list()
i <- 1
for (inc in 1:3){
MyLists[[inc]] <- x[i:(i+inc-1)]
i <- i+inc
}
Now MyLists[[1]] is list1, etc.
Building off farnsy's answer, If you need each list in a separate indexed list in the global environment you could do something like this.
#your Stater list
x <- list(x1=c(1,2,3), x2=c(1,4,3), x3=c(3,4,6),
x4=c(4,8,4), x5=c(4,33,4), x6=c(9,6,7))
#using a paste parse eval approach to evaluate a string
i<-1
for(inc in 1:3){
eval(parse(text =
paste0("list", inc, "<-list(",
paste0("x$",names(x)[i:(i+inc-1)],collapse = ","),
")")
))
i <- i+inc
}
I am trying to transpose a table I have created from a list of lists.
Each nested list has this format:
list(storm_name=NA, storm_level=NA, file_date=NA, file_time=NA,
date=NA, time=NA, actual_or_forecast=NA, lat=NA, long=NA, max_wind=NA,
gusts=NA, eye_speed=NA, eye_location=NA, storm_end=NA)
In short, each row has 14 elements within it.
storm_df <- as.data.frame(matrix(unlist(list1), nrow=length(unlist(list1[1]))))
The code I have written above so far creates the table where the orientation is 14 rows x N (number of inner lists) columns whereas I would like it to be N rows x 14 columns.
Does anyone see what I am doing wrong?
Thanks in advance!
Let's use do.call, rbind, and lapply:
## data
l1 <- list(storm_name=NA, storm_level=NA, file_date=NA, file_time=NA,
date=NA, time=NA, actual_or_forecast=NA, lat=NA, long=NA, max_wind=NA,
gusts=NA, eye_speed=NA, eye_location=NA, storm_end=NA)
big_list <- list(l1, l1, l1)
## make data.frame
do.call('rbind', lapply(big_list, data.frame))
Stepping through this, first we run lapply on big_list, so for each item in big_list, we create a data.frame. Try data.frame(l1) to see the result of each call.
Then we use do.call('rbind', ...) because the lapply returns a lists of data.frames, we want to "stack" the data on top of each other.
I have a list of lists, where some lists are NULL (contain nothing), and some lists contains 12 columns and 1 row. lets say this list of lists is named: pages.
I would like to merge the lists that contain the 12 columns and 1 row into a dataframe. so that I have a final dataframe of 12 columns and x rows.
I first tried:
final_df <- Reduce(function(x,y) merge(x, y, all=TRUE), pages)
which yielded a dataframe with the right 12 columns, but no rows, so it was empty.
I then tried:
listofvectors <- list()
for (i in 1:length(pages)) {listofvectors <- c(listofvectors, pages[[i]])}
which just pasted every list below each other.
I finally tried playing with:
final<-do.call(c, unlist(pages, recursive=FALSE))
which only resulted in a very long value.
What am I missing? Who can help me out? Thanks a lot for your input.
The merge function is for joining data on common column values (commonly called a join). You need to use rbind instead (the r for row, use cbind to stick columns together).
do.call(rbind, pages) # equivalent to rbind(pages[[1]], pages[[2]], ...)
do.call(rbind, pages[lengths(pages) > 0]) # removing the 0-length elements
If you have additional issues, please provide a reproducible example in your question. This code works on this example:
x = list(data.frame(x = 1), NULL, data.frame(x = 2))
do.call(rbind, x)
# x
# 1 1
# 2 2
I have a large list of 2 elements containing lists of species containing lists of 25 vectors, resembling a set like this:
l1 <- list(time=runif(100), space=runif(100))
l2 <- list(time=runif(100), space=runif(100))
list1 <- list(test1=list(species1=l1, species2=l2),test2=list(species1=l1, species2=l2))
I think, its essentially a list of a list of lists.of vectors.
I want to create a data.frame from all space-vectors of all 'species' in just one of the two sublists:
final <- as.data.frame(cbind(unlist(list1[[2]]$species1$space), unlist(list1[[2]]$species2$space)))
names(final) <- names(list1[[2]])
Essentially, i need a loop/apply command that navigates me through list1[[2]]$species and picks all vectors called space.
Thank you very much!
We can use a nested loop to extract the 'space' elements
data.frame(lapply(list1, function(x)
sapply(x, "[", 'space')))
In R, I have a list comprised of objects with an unequal number of elements. For example,
l <- list(a=c(1,2), b=3, c=4)
I have figured out how to find the maximum length of any object:
lmax <- max(unlist(lapply(l,length)))
And also how to identify which objects are not the longest:
notlongest <- unlist(lapply(l,length)) != max(unlist(lapply(l,length)))
What I need to do now: for those objects in the list that are notlongest, repeat their elements the number of times of lmax and get a new list. That is, for objects b and c, repeat their elements twice so I get a new list that looks something that this:
newl <- list(a=c(1,2), b=c(3,3), c=c(4,4))
I'm sure there is an easy answer with the lapply function but I can't figure it out. Apologies if this question has been asked before. Thank you!
lmax <- max(sapply(l,length))
ll <- lapply(l, function(x) c(x, rep(x, lmax-length(x)) ) )
ll
$a
[1] 1 2
$b
[1] 3 3
$c
[1] 4 4
From R 3.2.0, lengths(l) can be used in place of sapply(l,length)
lmax <- max(lengths(l))
The simplest way is that I can think of is to use R's recycling rule and data.frame to group the lists into a list of equal length lists:
dat <- do.call('data.frame', l)
You can operate directly out of that structure now but if you want to create separate lists again you use sapply to break it back apart into separate lists:
sapply(dat, list)