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.
的值不正确
我在使用聚合函数时遇到问题。我的 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.