R:将值列聚合到多个新列,每个列都基于索引列

时间:2018-04-29 19:52:33

标签: r recursion merge aggregate

假设我有数据:

data.frame(Plot = rep(1:2,3),Index = rep(1:3, each = 2), Val = c(1:6)*10)

  Plot Index Val
1    1     1  10
2    2     1  20
3    1     2  30
4    2     2  40
5    1     3  50
6    2     3  60

我想创建新列,合并/聚合所有Val,共享给定Index的公共Plot。我想为每个Index执行此操作。

  Plot Val1 Val2 Val3
1    1   10   30   50
2    2   20   40   60

我希望任何剩余的列(例如,在此简化示例中仅为Plot)保留在我的最终data.frame中。

我的尝试

我知道我可以使用aggregate()merge()逐步执行此操作,但有没有办法使用单个(或最小)调用执行此操作?

  • 任何方法都很棒,但我总是希望看到一个优雅的基础R方法,如果存在...

更新:

我正在寻找一种在涉及其他列时也能正常运行的解决方案:

dat2 = data.frame(Plot = rep(1:2,each = 8),Year = rep(rep(2010:2011, each = 4),2), 
                  Index = rep(rep(1:2,2),4), Val = rep(c(1:4)*10,4))

   Plot Year Index Val
1     1 2010     1  10
2     1 2010     2  20
3     1 2010     1  30
4     1 2010     2  40
5     1 2011     1  10
6     1 2011     2  20
7     1 2011     1  30
8     1 2011     2  40
9     2 2010     1  10
10    2 2010     2  20
11    2 2010     1  30
12    2 2010     2  40
13    2 2011     1  10
14    2 2011     2  20
15    2 2011     1  30
16    2 2011     2  40

#Resulting in (if aggregating by sum, for example):

  Plot Year Val1 Val2 
1    1 2010   40   60 
2    1 2011   40   60 
3    2 2010   40   60 
4    2 2011   40   60 

另外,理想情况下,可以根据Index值命名新列。

  • 因此,如果我的索引是A:C,我的新列将是ValAValBValC

2 个答案:

答案 0 :(得分:3)

您似乎想要一个基本R解决方案:然后您可以执行以下操作:

m = aggregate(Val~.,dat2,sum)
reshape(m,v.names = "Val",idvar = c("Plot","Year"),timevar = "Index",direction = "wide")
  Plot Year Val.1 Val.2
1    1 2010    40    60
2    2 2010    40    60
3    1 2011    40    60
4    2 2011    40    60

但你可以使用其他功能:

do.call(data.frame,aggregate(Val~Plot+Year,m,I))
  Plot Year Val.1 Val.2
1    1 2010    40    60
2    2 2010    40    60
3    1 2011    40    60
4    2 2011    40    60

或者使用reshape2库,您可以解决问题:

library(reshape2)
dcast(dat2,Plot+Year~Index,sum,value.var = "Val")
  Plot Year  1  2
1    1 2010 40 60
2    1 2011 40 60
3    2 2010 40 60
4    2 2011 40 60

答案 1 :(得分:1)

可以考虑使用gatherunitespread函数来获得OP提到的所需结果。

library(tidyverse)
df <- data.frame(Plot = rep(1:2,3),Index = rep(1:3, each = 2), Val = c(1:6)*10)


df %>% gather(key, value, -Plot, -Index) %>%
  unite("key", c(key,Index), sep="") %>%
  spread(key, value)

#   Plot Val1 Val2 Val3
# 1    1   10   30   50
# 2    2   20   40   60

注意:还有其他简短的选项(正如@Onyambu正确指出的那样),但是每个OP的欲望列的名称都需要更改。

spread(df, Index, Val)
#   Plot  1  2  3
# 1    1 10 30 50
# 2    2 20 40 60

aggregate(Val~Plot,df,I)
#   Plot Val.1 Val.2 Val.3
# 1    1    10    30    50
# 2    2    20    40    60

已更新:基于OP的第二个数据框。

dat2 = data.frame(Plot = rep(1:2,each = 8),Year = rep(rep(2010:2011, each = 4),2), 
                  Index = rep(rep(1:2,2),4), Val = rep(c(1:4)*10,4))


library(tidyverse)
library(reshape2)

dat2 %>% gather(key, value, -Plot, -Index, -Year) %>%
  unite("key", c(key,Index), sep="") %>%
  dcast(Plot+Year~key, value.var = "value")

#   Plot Year Val1 Val2
# 1    1 2010    2    2
# 2    1 2011    2    2
# 3    2 2010    2    2
# 4    2 2011    2    2