2015-07-07 26 views
9

Tôi có một danh sách các phần tử có tên (testlist), nơi một số trong những cái tên được nhân đôiChuyển đổi một danh sách các phần tử có tên vào một khung dữ liệu hoặc dữ liệu bảng

$x 
[1] "one" 

$x 
[1] "two" 

$y 
[1] "three" 

$y 
[1] "four" 

Và tôi đang cố gắng để kết thúc với một dữ liệu bảng sẽ kết hợp các phần tử với tên chung vào cùng một cột.

 x  y 
1: one three 
2: two four 

Tôi đã thử

testdf <- do.call(cbind, lapply(testlist, data.table)) 

nhưng chỉ kết thúc với:

x.V1 x.V1 y.V1 y.V1 
1: one two three four 

gợi ý Bất kỳ? Đánh giá cao sự trợ giúp!

Trả lời

8

Hãy thử

library(data.table)#v1.9.5+ 
dcast(setDT(stack(testlist))[, N:= 1:.N, ind], 
        N~ind, value.var='values')[,N:=NULL][] 
# x  y 
#1: one three 
#2: two four 

Hoặc một cách tiếp cận base R sẽ

unstack(stack(testlist),values~ind) 
# x  y 
#1 one three 
#2 two four 
+2

Điều đó thật tuyệt! Cảm ơn rất nhiều. – AlexT

+0

@akrun bạn sẽ sử dụng quy trình cơ sở nào cho điều này? –

+1

@PierreLafortune Tôi sẽ sử dụng 'unstack (stack (danh sách kiểm tra), giá trị ~ ind)' – akrun

6

Một cơ sở R thay thế hiệu quả hơn có thể là:

data.frame(split(unlist(L, use.names = FALSE), names(L))) 
#  x  y 
# 1 one three 
# 2 two four 

mẫu dữ liệu:

L <- as.list(setNames(c("one", "two", "three", "four"), c("x", "x", "y", "y"))) 

Ngoài ra, trong "data.table", nó sẽ hiệu quả hơn để tạo ra data.table của bạn bằng tay thay vì sử dụng stack:

library(data.table) # V1.9.4 
dcast.data.table(
    data.table(val = unlist(L, use.names = FALSE), var = names(L))[ 
    , rn := seq(.N), by = var], rn ~ var, value.var = "val")[, rn := NULL][] 

# Required packages 
library(stringi) 
library(microbenchmark) 
library(data.table) 

# Sample data 
set.seed(1) # for reproducible data 
nr = 10000 # final number of rows expected 
nc = 100  # final number of columns expected 
L <- as.list(setNames(sample(100, nc*nr, TRUE), rep(stri_rand_strings(nc, 7), nr))) 

# Functions to benchmark 
funak_b <- function() unstack(stack(L),values~ind) 
funak_dt <- function() { 
    dcast.data.table(setDT(stack(L))[, N:= 1:.N, ind], 
        N ~ ind, value.var = 'values')[, N := NULL][] 
} 
funam_b <- function() data.frame(split(unlist(L, use.names = FALSE), names(L))) 
funam_dt <- function() { 
    dcast.data.table(
    data.table(val = unlist(L, use.names = FALSE), var = names(L))[ 
     , rn := seq(.N), by = var], rn ~ var, value.var = "val")[, rn := NULL][] 
} 

# Results 
microbenchmark(funak_b(), funak_dt(), funam_b(), funam_dt(), times = 20) 
# Unit: milliseconds 
#  expr  min   lq  mean median  uq  max neval 
# funak_b() 2171.53485 2292.55003 2434.8899 2463.1977 2546.4671 2687.5924 20 
# funak_dt() 2364.68148 2598.00309 2646.6790 2643.5328 2694.8609 2902.6150 20 
# funam_b() 91.88414 93.09794 104.0179 96.4256 100.4168 204.0342 20 
# funam_dt() 238.17656 249.59135 344.9249 310.8694 423.6861 508.1844 20 

Tôi đoán tôi muốn gắn bó với cơ sở R trên trang này :-)

+0

Tôi không biết rằng 'stack' là rất kém hiệu quả. – akrun

+0

@akrun Tôi từng là một fan hâm mộ của chức năng đó, nhưng nó không hiệu quả cho bất cứ điều gì khác hơn là dữ liệu rất nhỏ mà tôi không sử dụng nó nữa. Nó thực sự cần được reimplemented trong C. – Roland

+0

@ Roland Cảm ơn ý kiến ​​của bạn. – akrun

Các vấn đề liên quan