объединение data.frame и списка data.frames без общих переменных в R - PullRequest
0 голосов
/ 26 мая 2018

У меня есть фрейм данных (D) и список фреймов данных (L), которые я хочу объединить в новый фрейм данных.Есть одна строка в D для каждого фрейма данных в L, и я хочу объединить эти данные вместе, чтобы каждая строка в D была сопоставлена ​​с соответствующим фреймом данных в L и реплицирована по каждой строке.Кадры данных в L имеют разные номера строк, но все они имеют одинаковые столбцы и могут быть легко объединены в один кадр данных (например, используя plyr::rbind.fill).Нет общих переменных между D и фреймами данных в L - я знаю, какие строки сочетаются друг с другом по порядку их появления в D и L.

Вот игрушечные данные с одинаковой структуройкак мои данные:

# the data frame
D <- data.frame(name = c("john","sally","ben"), age = c(23, 31, 27))

# the list of data frames
john <- data.frame(attempt = 1:3, result = c("fail","fail","fail"))
sally <- data.frame(attempt = 1, result = c("success"))
ben <- data.frame(attempt = 1:5, result = c("fail","fail","success","fail","success"))
L <- list(john, sally, ben)

Глупый способ, которым я пытался это сделать, заключается в цикле for:

# loop to combine data frame and list
new_D <- data.frame()
for (i in 1:nrow(D)) {
    add <- cbind(D[i,], L[[i]])
    new_D <- rbind(new_D, add)
}

Это работает, но очень медленно и мои файлыдовольно большие, так что это не практично.Какой более чистый и эффективный способ сделать это в R?

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

Назовите элементы списка, преобразуйте список в один data.table с помощью столбца индекса («имя»), объедините с исходными данными в столбце «имя»:

names(L) <- D$name
D2 <- data.table::rbindlist(L, use.names = TRUE, idcol = "name")  
D2[D, on = "name"]
#     name attempt  result age
# 1:  john       1    fail  23
# 2:  john       2    fail  23
# 3:  john       3    fail  23
# 4: sally       1 success  31
# 5:   ben       1    fail  27
# 6:   ben       2    fail  27
# 7:   ben       3 success  27
# 8:   ben       4    fail  27
# 9:   ben       5 success  27
0 голосов
/ 26 мая 2018

Мы можем сделать split по последовательности строк, а затем с помощью Map cbind наборов данных

do.call(rbind, Map(cbind, split(D, seq_len(nrow(D))), L))

Или установить имена 'L' с помощью pasteed строки 'D', связать строки и separate в два столбца

library(tidyverse)
do.call(paste, c(D, sep = ",")) %>%
     set_names(L, .) %>%
     bind_rows(.id = 'grp') %>% 
     separate(grp, into = c('name', 'age'))
...