从狭窄的data.frame快速生成列表

时间:2018-10-15 16:16:02

标签: r performance lapply

我有一个像这样的窄格式的data.frame:

test_data<-data.frame(id=rep(1:200,50), 
variable=sample(LETTERS,10000,T), 
value=sample(letters,10000,T), stringsAsFactors = F)

我想获取一个列表,其中包含每个id的列表,其中每个变量作为向量在内部(类似于简单的JSON格式):

list("1"=list(A=c("a","b"), B=character(), C="v" ...

我的代码:

return_data <-
   sapply(unique(test_data$id), function (r)
      sapply(LETTERS, function(q)
        test_data[test_data$id == r & test_data$variable == q, "value"],
      USE.NAMES = T,simplify = F),
    USE.NAMES = T,simplify = F)

它可以工作,但是对于大样本来说太慢了。我已经用数据重写了它。表,但仍然很慢。我对parSapply进行了一些改进,但是我相信应该有更有效的算法...

1 个答案:

答案 0 :(得分:5)

由于split的行为(默认情况下已启用,但在此处明确传递以提高可读性),因此可以将variabledrop = FALSE一起使用。使用magrittr:

library(magrittr)

res = test_data %>% 
  transform(variable = factor(variable)) %>% 
  split(.["id"]) %>% 
  lapply(function(x) split(x$value, x["variable"], drop = FALSE))

all.equal(unname(res), return_data) # TRUE

没有magrittr的情况相同:

new_test_data = transform(test_data, variable = factor(variable))
sp_id = split(new_test_data , new_test_data["id"])
res2 = lapply(sp_id, function(x) split(x$value, x["variable"], drop = FALSE))

all.equal(unname(res2), return_data) # TRUE