【问题标题】:Vectorizing across dataframes跨数据帧矢量化
【发布时间】:2014-01-30 00:58:30
【问题描述】:

我有一个从各种 csv 文件中读取的数据帧列表。每个数据框具有相同的格式(即列相同)。

myList <- list(frame1, frame2, ..., frameN)

我经常需要对每个数据帧中的相应列执行一些计算,例如对给定日期(行)的每个数据帧中的所有工资列求和。

day <- 1
dailyTotal <- NULL

for(i in 1:N){
    dailyTotal <- dailyTotal + myList[[i]]$Salary[day]
}

我想知道如果没有 for 循环,是否有更好的矢量化方法?

【问题讨论】:

  • 你看过lapply吗?
  • 你的 data.frames 有相同的行数吗?如果是这样,创建一个工资矩阵(仍然通过lapply)将使您能够访问矢量化解决方案。如果您对day 的多个值执行此操作,您将真正开始看到好处。
  • lappy,没听说过,现在研究一下。是的,每个数据框都有相同的行数
  • @RJ,flodel 不知道你到底在想什么,但这就是我想出的 sum(sapply(myList, function(x) x$Salary[day]))

标签: r


【解决方案1】:

您确实应该考虑将您的数据帧绑定到一个大数据帧中,然后您可以在该数据帧上执行拆分-应用-组合样式分析。

首先在一个列表中创建 5 个 data.frames(带有 cols 名称和薪水)来尝试复制您的数据:

dfs <- replicate(5, data.frame(name=sample(letters, 10), salary=runif(10, 50000,100000)), simplify=F)

现在rbind将它们合并为一个大数据框,并用额外的列df.name表示原始数据框

dfs.bound <- do.call(rbind, mapply(cbind, df.name=paste("DF# ", 1:length(dfs)), dfs, SIMPLIFY=F)) 
str(dfs.bound)
# 'data.frame':  50 obs. of  3 variables:
# $ df.name: Factor w/ 5 levels "DF#  1","DF#  2",..: 1 1 1 1 1 1 1 1 1 1 ...
# $ name   : Factor w/ 21 levels "a","g","h","j",..: 5 2 4 10 8 1 9 6 3 7 ...
# $ salary : num  94666 74596 78793 77120 60251 ...

然后 split apply combine(显示三种方法,tapply 只适用于一列,plyr/data.table 适用于许多列):

tapply(dfs.bound$salary, dfs.bound$df.name, mean)
#   DF#  1   DF#  2   DF#  3   DF#  4   DF#  5  
# 74342.26 68222.44 71881.49 75840.18 63180.07 

使用plyrdata.table,我们可以添加更多列,以及不同的汇总统计信息。

library(plyr)
ddply(dfs.bound, "df.name", summarise, avg.salary=mean(salary), ppl.count=length(name))
#   df.name avg.salary ppl.count
# 1  DF#  1   74342.26        10
# 2  DF#  2   68222.44        10
# 3  DF#  3   71881.49        10
# 4  DF#  4   75840.18        10
# 5  DF#  5   63180.07        10
library(data.table)
data.table(dfs.bound)[, list(avg.salary=mean(salary), ppl.count=length(name)), by=df.name]
#    df.name avg.salary ppl.count
# 1:  DF#  1   74342.26        10
# 2:  DF#  2   68222.44        10
# 3:  DF#  3   71881.49        10
# 4:  DF#  4   75840.18        10
# 5:  DF#  5   63180.07        10

【讨论】:

    【解决方案2】:

    与@BrodieG 的方法相比,将数据保存为列表有利有弊。这取决于您想在分析的其他部分等中做什么。因此,这是将数据维护为列表的方法:

    # Create dummy data
    list.of.data.frames <- lapply(1:10, function(n) data.frame(matrix(runif(100), nrow = 10)))
    
    # Sum up X1 in each dataframe in the list
    list.of.columnsums.of.x1 <- lapply(list.of.data.frames, function(n) sum(n[,"X1"]))
    
    # Sum up the sums of X1 in each data.frame
    sum.of.X1 <- do.call(sum, list.of.columnsums.of.x1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-07
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      • 2017-11-05
      • 1970-01-01
      • 2019-11-19
      相关资源
      最近更新 更多