如何在R中从多个列表中获取并合并一个元素?

ccrfmcuu  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(131)

我有一个如下所示的函数。

f1<-function(x)
{
  df1 <- rowSums(x)
  df2 <- colSums(x)
  return(list(Actuals = df1,Summary = df2))
}

我按组调用该函数,如下所示。

out <- by( mtcars, INDICES = mtcars$gear, f1, simplify = TRUE )

现在,我只需要从所有组中获取Summary,并将它们合并到一个 Dataframe 中。
我可以用下面的代码来做。

summary <- do.call( rbind, sapply( out, function(x) x$Summary, simplify = FALSE ) )
summary <- cbind( Gear = as.integer( row.names(summary) ), summary )

但是这个过程非常慢。我的原始数据集中有数千个组,这种方法大约需要20分钟才能完成。
有谁能提供一个更好的data.table或其他包的方法吗?
先谢了。

6jjcrrmo

6jjcrrmo1#

即使有数万个组,当前解决方案中的整形操作也只需要几秒钟,我怀疑几乎所有的处理时间都花在了实际的f1函数上。
下面是使用data.table完成(本质上)相同任务的一种方法,它的运行速度大约是data.table的两倍。

  • 示例 * f1函数(根据注解“f1函数只是一个示例。我有非常冗长和复杂的函数。但以列表格式返回两个 Dataframe 。”修改):
f1 <- function(x) {
  df1 <- as.data.frame(t(rowSums(x)))
  df2 <- as.data.frame(t(colSums(x)))
  return(list(Actuals = df1, Summary = df2))
}

修改f1以返回嵌套列表。

f2 <- function(x) {
  df1 <- as.data.frame(t(rowSums(x)))
  df2 <- as.data.frame(t(colSums(x)))
  return(list(Actuals = list(df1), Summary = list(df2)))
}

制作一个更大的数据集进行说明。

library(data.table)
bigcars <- setDT(copy(mtcars))
bigcars <- rbindlist(lapply(1:1e4, function(i) copy(bigcars[,gear := gear + 3L])))

原始溶液:

system.time({
  out <- by(bigcars, INDICES = bigcars$gear, f1, simplify = TRUE)
  summary <- do.call(rbind, sapply(out, function(x) x$Summary, simplify = FALSE))
  summary <- cbind(Gear = as.integer(row.names(summary)), summary)
})
#>    user  system elapsed 
#>   11.82    0.15   11.99

data.table溶液:

system.time({
  out2 <- setDT(copy(bigcars))[, f2(.SD), gear]
  summary2 <- rbindlist(out2$Summary)
})
#>    user  system elapsed 
#>    5.34    0.11    5.47

请注意,[, f2(.SD), gear]操作不会将分组变量传递给f2,因此gear不会出现在summary2中。可能需要根据f1函数的实际操作来修改该操作。

相关问题