R - List of turns in the DataFrame

There is a list like this starting at 1.

[[7158]] [1] 81 72 [[7159]] [1] 81 69 [[7160]] [1] 81 79 [[7161]] [1] 81 84 

This needs to be changed in the data frame, where the first number in each element is aligned in one column of the data frame, and the second number in each element is placed in the second column of the data frame. So it should end as follows:

 > data.frame("col1" = c(81, 81, 81, 81), "col2" = c(72, 69, 79, 84)) col1 col2 1 81 72 2 81 69 3 81 79 4 81 84 

I tried doing do.call(rbind.data.frame, my_list) , but it seems to put numbers in a huge number of columns, rather than forcing them into two necessary columns. It would be pretty simple to do this with a loop, but what is the R-way to do this? Thanks.

+5
source share
5 answers

Just set the names:

 mylist <- list(c(81,72), c(81,63), c(81,79)) setNames(do.call(rbind.data.frame, mylist), c("col1", "col2")) # col1 col2 #1 81 72 #2 81 63 #3 81 79 

Unlike some other solutions, this will also work for mixed data types:

 mylist <- list(list("a", 72), list("b", 63), list("c", 79)) res <- setNames(do.call(rbind.data.frame, mylist), c("col1", "col2")) str(res) #'data.frame': 3 obs. of 2 variables: # $ col1: Factor w/ 3 levels "a","b","c": 1 2 3 # $ col2: num 72 63 79 
+7
source

You can try any of the following:

 do.call(rbind, my_list) t(simplify2array(my_list)) library(stringi) stri_list2matrix(my_list, byrow = TRUE) 

All of the above would create two matrix columns with the data that you describe, so you can use as.data.frame to get data.frame .

Timing for the above alternatives and @Roland's suggestion can be found in this Gist . To summarize, the string approach will be the fastest of the options presented. If I'm not mistaken, rbindlist in "data.table" should also support vector list conversion, but I did not test the development version on GitHub for verification, so I did not include this parameter here.

+4
source

You can try with

 Reduce( rbind, lapply(t1, t) ) 
+1
source

Another idea:

 mylist = list(c(81, 72), c(81, 69), c(81, 79), c(81, 84)) f4 = function(x) { tlist = lapply(seq_along(x[[1]]), function(i) unlist(lapply(x, "[[", i))) structure(tlist, class = "data.frame", row.names = .set_row_names(as.integer(length(tlist[[1]]))), names = paste("col", seq_along(tlist), sep = "")) } f4(mylist) # col1 col2 #1 81 72 #2 81 69 #3 81 79 #4 81 84 

And a test with other parameters:

 library(stringi) f1 = function(x) setNames(as.data.frame(type.convert(stri_list2matrix(x, byrow = TRUE))), paste("col", seq_along(x[[1]]), sep = "")) f2 = function(x) setNames(do.call(rbind.data.frame, x), paste("col", seq_along(x[[1]]), sep = "")) f3 = function(x) setNames(as.data.frame(Reduce(rbind, lapply(x, t))), paste("col", seq_along(x[[1]]), sep = "")) myls = replicate(1e3, sample(1e2), simplify = F) identical(f1(myls), f2(myls)) #[1] TRUE identical(f1(myls), f3(myls)) #[1] TRUE identical(f1(myls), f4(myls)) #[1] TRUE microbenchmark::microbenchmark(f1(myls), f2(myls), f3(myls), f4(myls), times = 10) #Unit: milliseconds # expr min lq median uq max neval # f1(myls) 57.66834 58.46979 59.39131 61.43861 102.27333 10 # f2(myls) 393.81459 404.29019 418.03128 422.87740 494.79857 10 # f3(myls) 288.39078 299.51680 305.21727 314.75482 374.48683 10 # f4(myls) 52.54991 53.26575 55.34472 59.25559 75.19658 10 
+1
source

In the current version of data.table, v1.9.5 , a new transpose() function has appeared that wraps the list. We can use this together with setDT() as follows.

 require(data.table) # v1.9.5+ ll = lapply(1:1e6, function(x) sample(100, 2)) dt = setDT(transpose(ll)) system.time(setDT(transpose(ll)) # user system elapsed # 0.073 0.000 0.073 

If you need a data.frame file, you can use setDF() for this result (which converts the data.table to data.frame without any copies).

+1
source

Source: https://habr.com/ru/post/1213416/


All Articles