以下是一些示例数据:
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
如何在A
中获得C
和x1
以及的总和?
aggregate(.~x1, FUN=sum, data=data, na.action = na.omit)
x1 x2 x3 x4 x5
1 B 11 176 96 80
当我使用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
为什么我在第一行获得<NA>
,但在第三行获得NA
?
它们之间有什么区别?为什么我得到<NA>
?数据中没有<NA>
!
str(data)
'data.frame': 12 obs. of 5 variables:
$ x1: Factor w/ 3 levels "A","B","C": 3 1 1 1 3 1 1 1 2 1 ...
$ x2: int 1 1 1 4 4 1 1 1 4 3 ...
$ x3: int 16 16 16 64 64 16 16 16 64 48 ...
$ x4: int NA 16 16 64 NA 16 16 16 32 48 ...
$ x5: int 16 NA NA NA 64 NA NA NA 32 NA ...
sqldf问题仍然存在,为什么sum(x4)
得到NA
,相反sum(x5)
获得<NA>
?
我可以证明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
因此sqldf以不同方式处理sum(x4)
和sum(x5)
这一事实非常奇怪,我认为sqldf存在逻辑混乱。它可以在其他电脑上复制。请先做,然后继续讨论。
答案 0 :(得分:6)
以下是您感兴趣的data.table
方式:
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
如果您希望sum
在删除NA之后返回NA
而不是总和,请删除na.rm=TRUE
参数。
.SD
这是一个内部data.table
变量,默认情况下构建by
以外的所有列 - 除了x1
之外的所有列。您可以通过执行以下操作检查.SD
的内容:
dt[, print(.SD), by=x1]
了解.SD
是什么。如果您有兴趣,请检查?data.table
其他内部(非常有用)特殊变量,例如.I
,.N
,.GRP
等。
答案 1 :(得分:5)
由于aggregate
的公式方法默认处理NA
值,您需要在使用na.rm
中的sum
参数之前覆盖它。您可以将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
还是<{1}},似乎会将这些列投射到不同类型不。如果是NA
,则该列会被转换为character
。
比较
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
但是,有一个简单的解决方法:将原始名称重新分配给正在创建的新列。也许让我们的SQLite继承以前数据库中的一些信息? (我真的不使用SQL。)
示例(前面创建了相同的“df2”):
sqldf("select sum(A) `A`, sum(B) `B` from df2 group by id")
# A B
# 1 NA 3
# 2 2 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
如果您希望将NA
替换为0
,可采取类似方法:
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
答案 2 :(得分:2)
aggregate(data[, -1], by=list(data$x1), FUN=sum)
我删除了第一列,因为你没有在总和中使用它,它只是一个分组数据的组变量(事实上我在“by”中使用它)
答案 3 :(得分:2)
以下是使用reshape
包执行此操作的方法:
> # 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
或者,您可以在na.rm
过程中完成melt()
。
学习library(reshape)
的好处是,引用作者("Reshaping Data with the
reshape
Package"),
“在R中,有许多可以聚合数据的通用函数, 例如tapply,by和aggregate,以及一个特定的函数 重塑数据,重塑。这些功能中的每一个都易于处理 有一个或两个特定场景,每个场景需要稍微不同 输入参数。在实践中,你需要仔细考虑 将正确的操作顺序放在一起以获取数据 你想要的形式。重塑包装源于我的挫败感 为咨询客户重塑数据,并克服这些 使用两个一般概念框架的问题 功能:熔化和铸造。“