R 如何获得聚合函数中的所有和?
以下是一些示例数据:R 如何获得聚合函数中的所有和?,r,aggregate,R,Aggregate,以下是一些示例数据: dat="x1 x2 x3 x4 x5 1 C 1 16 NA 16 2 A 1 16 16 NA 3 A 1 16 16 NA 4 A 4 64 64 NA 5 C 4 64 NA 64 6 A 1 16 16 NA 7 A 1 16 16 NA 8 A 1 16 16 NA 9 B 4 64 32 32 10 A 3 48 48 NA 11 B 4 64 32 32 12 B 3 48 32 16" d
dat="x1 x2 x3 x4 x5
1 C 1 16 NA 16
2 A 1 16 16 NA
3 A 1 16 16 NA
4 A 4 64 64 NA
5 C 4 64 NA 64
6 A 1 16 16 NA
7 A 1 16 16 NA
8 A 1 16 16 NA
9 B 4 64 32 32
10 A 3 48 48 NA
11 B 4 64 32 32
12 B 3 48 32 16"
data<-read.table(text=dat,header=TRUE)
aggregate(cbind(x2,x3,x4,x5)~x1, FUN=sum, data=data)
x1 x2 x3 x4 x5
1 B 11 176 96 8
当我使用sqldf
时:
library("sqldf")
sqldf("select sum(x2),sum(x3),sum(x4),sum(x5) from data group by x1")
sum(x2) sum(x3) sum(x4) sum(x5)
1 12 192 192 <NA>
2 11 176 96 80
3 5 80 NA 80
sqldf问题仍然存在,为什么sum(x4)
获取NA
,相反sum(x5)
获取
我可以通过以下方式证明x4和x5中的所有NA
:
data[is.na(data)] <- 0
> data
x1 x2 x3 x4 x5
1 C 1 16 0 16
2 A 1 16 16 0
3 A 1 16 16 0
4 A 4 64 64 0
5 C 4 64 0 64
6 A 1 16 16 0
7 A 1 16 16 0
8 A 1 16 16 0
9 B 4 64 32 32
10 A 3 48 48 0
11 B 4 64 32 32
12 B 3 48 32 16
data[is.na(data)]数据
x1x2x3x4x5
1C116016
216160
316160
4 A 4 64 0
5C464064
616160
716160
816160
9 B 4 64 32
10A 348480
11 B 4 64 32
12 B 3 48 32 16
因此,sqldf以不同的方式处理sum(x4)
和sum(x5)
的事实非常奇怪,我认为sqldf中存在逻辑混乱。它可以在其他电脑上复制。请先复制,然后继续讨论。aggregate(数据[,-1],by=list(数据$x1),FUN=sum)
我删除了第一列,因为在求和中不使用它,它只是一个分组变量,用于分割数据(事实上,我在“by”中使用了它)以下是
数据。如果您感兴趣,可以使用表的方式:
require(data.table)
dt <- data.table(data)
dt[, lapply(.SD, sum, na.rm=TRUE), by=x1]
# x1 x2 x3 x4 x5
# 1: C 5 80 0 80
# 2: A 12 192 192 0
# 3: B 11 176 96 80
了解什么是.SD
。如果您有兴趣,请检查?data.table
,查看其他内部(非常有用)特殊变量,如.I
、.N
、.GRP
等。因为聚合的公式方法默认情况下处理NA
值,在使用sum
中的na.rm
参数之前,需要重写该参数。您可以通过将na.action
设置为NULL
或na.pass
来执行此操作:
aggregate(cbind(x2,x3,x4,x5) ~ x1, FUN = sum, data = data,
na.rm = TRUE, na.action = NULL)
# x1 x2 x3 x4 x5
# 1 A 12 192 192 0
# 2 B 11 176 96 80
# 3 C 5 80 0 80
aggregate(cbind(x2,x3,x4,x5) ~ x1, FUN = sum, data = data,
na.rm = TRUE, na.action = na.pass)
# x1 x2 x3 x4 x5
# 1 A 12 192 192 0
# 2 B 11 176 96 80
# 3 C 5 80 0 80
关于sqldf
,根据第一个分组变量的第一行中的项是否为NA
,似乎列被转换为不同的类型。如果是NA
,则该列将转换为字符
比较:
df1 <- data.frame(id = c(1, 1, 2, 2, 2),
A = c(1, 1, NA, NA, NA),
B = c(NA, NA, 1, 1, 1))
sqldf("select sum(A), sum(B) from df1 group by id")
# sum(A) sum(B)
# 1 2 <NA>
# 2 NA 3.0
df2 <- data.frame(id = c(2, 2, 1, 1, 1),
A = c(1, 1, NA, NA, NA),
B = c(NA, NA, 1, 1, 1))
sqldf("select sum(A), sum(B) from df2 group by id")
# sum(A) sum(B)
# 1 <NA> 3
# 2 2.0 NA
您可以轻松使用paste
创建select
语句:
Aggs <- paste("sum(", names(data)[-1], ") `",
names(data)[-1], "`", sep = "", collapse = ", ")
sqldf(paste("select", Aggs, "from data group by x1"))
# x2 x3 x4 x5
# 1 12 192 192 NA
# 2 11 176 96 80
# 3 5 80 NA 80
str(.Last.value)
# 'data.frame': 3 obs. of 4 variables:
# $ x2: int 12 11 5
# $ x3: int 192 176 80
# $ x4: int 192 96 NA
# $ x5: int NA 80 80
下面是如何使用重塑
软件包:
> # x1 = identifier variable, everything else = measured variables
> data_melted <- melt(data, id="x1", measured=c("x2", "x3", "x4", "x5"))
>
> # Thus we now have (measured variable and it's value) per x1 (id variable)
> head(data_melted)
x1 variable value
1 C x2 1
2 A x2 1
3 A x2 1
4 A x2 4
5 C x2 4
6 A x2 1
> tail(data_melted)
x1 variable value
43 A x5 NA
44 A x5 NA
45 B x5 32
46 A x5 NA
47 B x5 32
48 B x5 16
> # Now aggregate using sum, passing na.rm to it
> cast(data_melted, x1 ~ ..., sum, na.rm=TRUE)
x1 x2 x3 x4 x5
1 A 12 192 192 0
2 B 11 176 96 80
3 C 5 80 0 80
#x1=标识符变量,其他一切=测量变量
>数据融合
>#因此,我们现在有每个x1(id变量)的(测量变量及其值)
>头部(数据单元)
x1变量值
1 C x2 1
2 A x2 1
3 A x2 1
4a x2 4
5cx24
6a x2 1
>尾部(数据_)
x1变量值
43 A x5 NA
44 A x5 NA
45 B x5 32
46 A x5 NA
47 B x5 32
48 B x5 16
>#现在使用sum进行聚合,将na.rm传递给它
>铸造(数据,x1~…,总和,na.rm=TRUE)
x1x2x3x4x5
1 A 12 192 0
2 B 11 176 96 80
3C580080
或者,您可以在melt()
-ing过程中执行na.rm
学习库(重塑)
的最大好处是引用作者()的话
“在R中,有许多通用函数可以聚合数据,
例如,tapply、by和aggregate,以及专门用于
重塑数据,重塑。这些函数中的每一个都处理得很好
有一个或两个特定场景,每个场景要求略有不同
输入参数。在实践中,你需要仔细思考才能拼凑
将正确的操作顺序放在一起,以将数据放入
你想要的形式。重塑包来自我的挫折
为咨询客户重塑数据,并克服这些问题
仅使用两种方法的一般概念框架的问题
功能:熔化和浇铸。”
什么是<代码>数据[,-1 ] < /代码>?我消除了第一列,因为你不必在求和中考虑它,它只是一个你必须用来分割数据的组变量(事实上我是用它来表示的),也许你可以在你的答案中加上这个解释,使它更完整和有用;完成。谢谢你的建议;-)您可能还需要,na.rm=TRUE
?(取决于OPs真实数据-在本例中,组中的所有值都是NA
或都不是NA
。这可能有助于:让
从NA
的字符表示中区分真实的NA
值,例如“NA”
。如果您查看运行该命令的返回值,您会得到一个data.frame
,其中前三列的类型为integer
,第四列的类型为character
。我猜sqldf
正在将第四列转换为一个因子。请尝试str(sqldf)(“选择sum(x2),sum(x3)、sum(x4)、sum(x5)from data group by x1”)
了解我的意思。SQLite根据列的第一行分配列关联性,并在其为NULL时使用文本。一些解决方法是:(1)将输出列的名称用作输入,在这种情况下,sqldf将推断您想要强制返回到该类型,(2)使用total
代替sum
,在这种情况下,零行将总计为0,而不是NULL,这样问题就不会发生,(3)使用sqldf的方法
arg指定类,(4)使用sqldf支持的其他数据库之一(H2、MySQL、PostgreSQL)代替SQLite。请参阅?sqldf
,了解更多信息。亲爱的Ananda Mahto,您仍然没有回答为什么sqldf会以不同的方式对待NA。@这是一篇文献,我没有确切的答案,但我有一个解决方案。我猜这并不是“sqldf”方面的问题,但更多与SQLite有关。有关在中读取数据时出现的类似问题,请参阅。我认为这里也发生了类似的情况。
df1 <- data.frame(id = c(1, 1, 2, 2, 2),
A = c(1, 1, NA, NA, NA),
B = c(NA, NA, 1, 1, 1))
sqldf("select sum(A), sum(B) from df1 group by id")
# sum(A) sum(B)
# 1 2 <NA>
# 2 NA 3.0
df2 <- data.frame(id = c(2, 2, 1, 1, 1),
A = c(1, 1, NA, NA, NA),
B = c(NA, NA, 1, 1, 1))
sqldf("select sum(A), sum(B) from df2 group by id")
# sum(A) sum(B)
# 1 <NA> 3
# 2 2.0 NA
sqldf("select sum(A) `A`, sum(B) `B` from df2 group by id")
# A B
# 1 NA 3
# 2 2 NA
Aggs <- paste("sum(", names(data)[-1], ") `",
names(data)[-1], "`", sep = "", collapse = ", ")
sqldf(paste("select", Aggs, "from data group by x1"))
# x2 x3 x4 x5
# 1 12 192 192 NA
# 2 11 176 96 80
# 3 5 80 NA 80
str(.Last.value)
# 'data.frame': 3 obs. of 4 variables:
# $ x2: int 12 11 5
# $ x3: int 192 176 80
# $ x4: int 192 96 NA
# $ x5: int NA 80 80
Aggs <- paste("sum(ifnull(", names(data)[-1], ", 0)) `",
names(data)[-1], "`", sep = "", collapse = ", ")
sqldf(paste("select", Aggs, "from data group by x1"))
# x2 x3 x4 x5
# 1 12 192 192 0
# 2 11 176 96 80
# 3 5 80 0 80
> # x1 = identifier variable, everything else = measured variables
> data_melted <- melt(data, id="x1", measured=c("x2", "x3", "x4", "x5"))
>
> # Thus we now have (measured variable and it's value) per x1 (id variable)
> head(data_melted)
x1 variable value
1 C x2 1
2 A x2 1
3 A x2 1
4 A x2 4
5 C x2 4
6 A x2 1
> tail(data_melted)
x1 variable value
43 A x5 NA
44 A x5 NA
45 B x5 32
46 A x5 NA
47 B x5 32
48 B x5 16
> # Now aggregate using sum, passing na.rm to it
> cast(data_melted, x1 ~ ..., sum, na.rm=TRUE)
x1 x2 x3 x4 x5
1 A 12 192 192 0
2 B 11 176 96 80
3 C 5 80 0 80