如何在R中使用多个data.frames或数组进行计算?

时间:2015-02-05 06:53:19

标签: arrays r lapply do.call

更新 - 我需要使用100多个二维表执行计算。我知道这些表可以作为data.frames或数组导入到R中。

这是一个说明我的问题的例子。为简化起见,我的许多表由d1,d2,dd2和dd3表示。请注意,我在列表中添加了更多data.frames,因为@BondedDust提出的解决方案正在替换' sum'通过' +'当列表中有2个data.frames,而不是4个data.frames时工作。

d1 = mtcars
d2 = d1*2
dd2 = d2 * 2
dd3 = d2 * d2

如果操作是' +',下面,d3将是我想要的最终输出。但我需要一种方法来自动化这个过程。

d3 = d1+d2 + dd2 + dd3 
> str(d3)
'data.frame':   32 obs. of  11 variables:
 $ mpg : num  2793 2793 3279 2898 2229 ...
 $ cyl : num  258 258 124 258 440 258 440 124 124 258 ...
 $ disp: num  154720 154720 70740 401190 780120 ...
 $ hp  : num  73370 73370 52545 73370 184975 ...
 $ drat: num  118.6 118.6 115.9 78.5 81.6 ...
 $ wt  : num  59.5 69.7 48.5 84.5 95.1 ...
 $ qsec: num  1741 1857 2208 2404 1857 ...
 $ vs  : num  0 0 13 13 0 13 0 13 13 13 ...
 $ am  : num  13 13 13 0 0 0 0 0 0 0 ...
 $ gear: num  124 124 124 75 75 75 75 124 124 124 ...
 $ carb: num  124 124 13 13 38 13 124 38 38 124 ...

所以我尝试使用列表,但是当我使用do.call时使用' +'使用列表中的4个data.frames它不起作用。

l1 = list(d1,d2,dd2,dd3)
str(l1)

> str(l1)
List of 4
 $ :'data.frame':   32 obs. of  11 variables:
  ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...

d4 = do.call('+', l1)
Error in `+`(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4,  : 
  unused arguments (list(mpg = c(84, 84, 91.2, 85.6, 74.8, 72.4, 57.2, 97.6, 91.2, 76.8, 71.2, 65.6, 69.2, 60.8, 41.6, 41.6, 58.8, 129.6, 121.6, 135.6, 86, 62, 60.8, 53.2, 76.8, 109.2, 104, 121.6, 63.2, 78.8, 60, 85.6), cyl = c(24

这篇文章R - Vector/ Array Addition显示了类似的问题,但他们使用数组而不是data.frames。所以,我尝试使用以下方法将data.frames转换为数组:

d5 = lapply(l1, function(x) data.matrix(x))

但是d5没有正确的结构,例如:

d6 = apply(d5,1:2,sum)

所以,我不确定问题是否与我使用lapply,do.call或者什么有关。任何帮助或指示将不胜感激。很抱歉,如果我错过了之前已经解决过这个问题的帖子,我一整天都在网上搜索并尝试了很多不同的选项而无法获得理想的结果。 谢谢!

2 个答案:

答案 0 :(得分:1)

你应该意识到这些不是"表",至少在技术R的用语中。 R表实际上是矩阵或数组,它非常易于使用" +"," - "," /"或" *"然后做元素操作。您正在显示R数据帧。它们是列表,可以按名称添加名称。您可以循环显示第一个数据帧中的名称,然后添加" +"沿着列:

 d3 <- as.data.frame(
              lapply(names(d1), function(x){ d1[ , x, drop=FALSE] + d2[ ,x]} ) )
 str(d3)

'data.frame':   32 obs. of  11 variables:
 $ mpg : num  63 63 68.4 64.2 56.1 54.3 42.9 73.2 68.4 57.6 ...
 $ cyl : num  18 18 12 18 24 18 24 12 12 18 ...
 $ disp: num  480 480 324 774 1080 ...
 $ hp  : num  330 330 279 330 525 315 735 186 285 369 ...
 $ drat: num  11.7 11.7 11.55 9.24 9.45 ...
 $ wt  : num  7.86 8.62 6.96 9.64 10.32 ...
 $ qsec: num  49.4 51.1 55.8 58.3 51.1 ...
 $ vs  : num  0 0 3 3 0 3 0 3 3 3 ...
 $ am  : num  3 3 3 0 0 0 0 0 0 0 ...
 $ gear: num  12 12 12 9 9 9 9 12 12 12 ...
 $ carb: num  12 12 3 3 6 3 12 6 6 12 ...

需要as.data.frame,因为lapply将返回一个列表(这是数据帧的真实含义),但它会删除将列表建立为数据帧的属性。

答案 1 :(得分:0)

这是基于@ biobirdman评论的解决方案。所有data.frames都具有相同的结构。

在真实模型的上下文中,如果你可以访问一台大型计算机,我可能最终会这样做,所以我会使用这个。

d5=do.call('rbind',l1)
d5.rnames =rep(rownames(l1[[1]]),times=length(l1)) #not sure this is the best way to add a col with the names to do the aggregation
d5$reg=d5.rnames
d6 = aggregate(d5[,1:11], by=list(d5$reg), FUN=sum)