我有以下结构的列表,
myList <- replicate(5, data.frame(id = 1:10, mean = runif(10)), simplify =F)
我想通过合并来减少它

myList %>% reduce(function(x, y) merge(x, y, by = 'id'))

但是,这会导致以下列名:
    id     mean.x    mean.y    mean.x    mean.y       mean

虽然我想要类似的东西
 id     mean1    mean2    mean3    mean4       mean5

其中数字基于 myList 的顺序。

显然我可以迭代 1:length(myList) ,但我发现这个解决方案不优雅。其他选项是在减少函数中引入检查,但这会导致对列表中的每个元素进行新的线性时间搜索,所以我认为它不是很有效。

有没有另一种方法来实现这一目标?

最佳答案

新答案:

使用 rbindlist 包中的 dcastdata.table:

library(data.table)
mydata <- rbindlist(myList, idcol = 'df')
dcast(mydata, id ~ paste0('mean',df), value.var = 'mean')

或者使用 tidyverse 包:
library(dplyr)
library(tidyr)
myList %>%
  bind_rows(., .id = 'df') %>%
  spread(df, mean) %>%
  rename_at(-1, funs(paste0('mean',.)))

两者都给出(显示 data.table -output):



id 中的一个或多个数据帧中有 duplicates in myList 时,您必须将 dcast -step 调整为 dcast(mydata, id + rowid(id,df) ~ paste0('mean',df), value.var = 'mean') 以获得正确的结果。检查以下示例以查看结果:
myList <- replicate(5, data.frame(id = sample(1:10, 10, TRUE), mean = runif(10)), simplify = FALSE)
mydata <- rbindlist(myList, idcol = 'df')
dcast(mydata, id + rowid(id,df) ~ paste0('mean',df), value.var = 'mean')

id 中没有重复项时,这也适用。
tidyverse -code 然后必须适应:
myList %>%
  bind_rows(., .id = 'df') %>%
  group_by(df, id) %>%
  mutate(ri = row_number()) %>%
  ungroup() %>%
  spread(df, mean) %>%
  rename_at(3:7, funs(paste0('mean',.)))

旧答案(仍然有效):

一个可能的解决方案:
# option 1
myList <- mapply(function(x,y) {names(x)[2] = paste0('mean',y); x}, myList, 1:length(myList), SIMPLIFY = FALSE)
Reduce(function(x, y) merge(x, y, by = 'id'), myList)

# option 2 (quite similar to @zx8754's solution)
mydata <- Reduce(function(x, y) merge(x, y, by = 'id'), myList)
setNames(mydata, c('id', paste0('mean', seq_along(myList))))

这使:

10-07 13:03
查看更多