R中id变量的简单聚合

Simple aggregation by id variables in R

我在使用聚合函数时遇到问题。我的 data.frame 看起来像这样:

**Region    Sex   SNI      value**
orebro      Man     0       497
orebro      Man     0        1
orebro      Man     1       120
referens    Man     96      3045
referens    Man     96       41
referens    Woman   0       2061
referens    Woman   0       2450

但我希望它看起来像这样:

**  Region      Sex   SNI      value**
    orebro      Man     0       498
    orebro      Man     1       120
    referens    Man     96      3086
    referens    Woman   0       4106

所以我想合并所有对 Region、Sex 和 SNI 具有相同值的观察结果。我试过了:

mydata2 <-aggregate(mydata, by=list(mydata$Region, mydata$Sex, mydata$SNI), 
                FUN=mean, na.rm=TRUE)

但我收到警告消息:

50: In mean.default(X[[50L]], ...) :
  argument is not numeric or logical: returning NA

并且生成的数据帧已损坏。我究竟做错了什么?我想这与尝试合并字符串有关?

如果 aggregate() 的第一个参数是 data.frame,那么它会尝试使用 FUN() 分别聚合 data.frame 的每一列。这意味着它将通过 mean() 运行 您的区域、性别和 sni 列,这是不正确的。相反,您只需要在第一个参数中传递值列,并且需要注意不要提取向量(与保留 data.frame 结构相反),否则您会丢失列名。

其次,第二个参数中的列表是未命名的,这意味着结果将丢失分组列的列名。您可以通过显式命名它们来解决这个问题,即 list(Region=mydata$Region, ... ),但还有更好的方法,即仅从 data.frame 中索引出分组列。这是可行的,因为 data.frames 是内部列表。

以下是使用 2D 索引的工作原理:

df <- data.frame(region=c('orebro','orebro','orebro','referens','referens','referens','referens'), sex=c('Man','Man','Man','Man','Man','Woman','Woman'), sni=c(0,0,1,96,96,0,0), value=c(497,1,120,3045,41,2061,2450) );
aggregate(df[,'value',drop=F],by=df[,c('region','sex','sni')],sum,na.rm=T);
##     region   sex sni value
## 1   orebro   Man   0   498
## 2 referens Woman   0  4511
## 3   orebro   Man   1   120
## 4 referens   Man  96  3086

或者,使用列表索引:

aggregate(df['value'],by=df[c('region','sex','sni')],sum,na.rm=T);
##     region   sex sni value
## 1   orebro   Man   0   498
## 2 referens Woman   0  4511
## 3   orebro   Man   1   120
## 4 referens   Man  96  3086

现在其实还有一个更好的方法,就是使用aggregate():

的公式接口
aggregate(value~region+sex+sni,df,sum,na.rm=T);
##     region   sex sni value
## 1   orebro   Man   0   498
## 2 referens Woman   0  4511
## 3   orebro   Man   1   120
## 4 referens   Man  96  3086

此外,您可能已经注意到我使用 sum() 而不是 mean()。我这样做是因为您的预期输出有总和而不是平均值,尽管 referens/Woman/0.

的值不正确