Быстрая генерация списка из узких data.frame - PullRequest
0 голосов
/ 15 октября 2018

У меня есть data.frame в узком формате, подобном этому:

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

Я хочу получить список, содержащий списки для каждого идентификатора с каждой переменной в виде вектора внутри (что-то вроде простого формата 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 голосов
/ 15 октября 2018

Вы можете использовать split с variable как фактор, благодаря поведению drop = 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
...