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