在 R 中 data.table 中基于另一个因素聚合一个因素
Aggregating one factor based on another in data.table in R
我有一个 R
data.table
对象 DT
如下:
library(ggplot2)
library(data.table)
DT <- movies[movies$mpaa %in% c("NC-17", "PG", "PG-13", "R"), c("rating", "title", "mpaa")]
setDT(DT)
setnames(DT, colnames(DT), c("Gp", "ID", "FACTOR"))
DT[, FACTOR := droplevels(FACTOR)]
DT[, Gp := as.numeric(as.factor(Gp))]
setkey(DT, ID)
DT <- unique(DT)
DT
Gp ID FACTOR
1: 43 $windle R
2: 61 'A' gai waak PG-13
3: 62 'A' gai waak juk jaap PG-13
4: 39 'R Xmas R
5: 38 'Til There Was You PG-13
---
4899: 57 Zuotian R
4900: 27 Zyosyuu syukeininn Maria R
4901: 57 eXistenZ R
4902: 45 xXx PG-13
4903: 29 xXx: State of the Union PG-13
我正在尝试根据列 Gp
中的元素聚合 FACTOR
列中的数据。我已经能够实现如下。
k <- vector("list", max(DT$Gp))
for (i in 1:max(DT$Gp)) {
names(k)[i] <- i
k[[i]] <- DT[Gp == i, as.vector(table(FACTOR))]
}
k <- lapply(k, function(x) as.data.frame(t(x)))
k <- rbindlist(k)
setnames(k, old = colnames(k), new = c("NC-17", "PG", "PG-13", "R"))
k$Gp <- row.names(k)
setcolorder(k, c("Gp","NC-17", "PG", "PG-13", "R"))
head(k)
Gp NC-17 PG PG-13 R
1: 1 0 0 0 2
2: 2 0 0 0 1
3: 3 0 0 0 2
4: 4 0 0 0 1
5: 5 0 0 0 2
6: 6 0 0 0 3
对于Gp
的每个级别,我想获得FACTOR
每个级别的记录数。如何单独使用 data.table
更优雅地获得想要的结果 k
?
您可以在每组 Gp
中使用 as.list(table(FACTOR))
:
DT[, as.list(table(FACTOR)), by = Gp]
这给出了结果:
Gp NC-17 PG PG-13 R
1: 43 1 8 26 79
2: 61 2 9 22 77
3: 62 0 7 18 63
4: 39 0 17 24 52
5: 38 1 14 13 77
6: 57 1 11 23 72
7: 48 0 16 29 78
...
(要按照示例输出中的 Gp
对它们进行排序,您可以将其更改为 DT[order(Gp), as.list(table(FACTOR)), by = Gp]
)。
我建议为此使用 dcast
:
require(data.table) # v1.9.4
dcast.data.table(DT, Gp ~ FACTOR, fun.aggregate = length)
或者从current devel, v1.9.5(以及以后的版本)开始,我们可以直接使用dcast()
:
require(data.table) # v1.9.5+
dcast(DT, Gp ~ FACTOR, fun.aggregate = length)
as.list()
是一个 S3 通用的,并且随着更多的组会变得相当慢(由于为每个组调度正确的方法所花费的时间)。 table()
是另一个慢函数。
dcast()
也会自动按 Gp
列对结果进行排序。
这里有一个足够大的基准来突出差异:
set.seed(1L)
bmark = data.table(Gp = sample(1e5, 1e7, TRUE),
FACTOR = sample(levels(DT$FACTOR), 1e7, TRUE))
print(object.size(bmark), units="Mb")
# 114.4 Mb
system.time(ans1 <- dcast(bmark, Gp ~ FACTOR, fun.aggregate = length))
# user system elapsed
# 0.998 0.026 1.030
system.time(ans2 <- bmark[, as.list(table(FACTOR)), by=Gp])
# user system elapsed
# 14.666 0.141 15.078
identical(ans1, setkey(ans2, Gp))
# [1] TRUE
数据大小是~114MB,不算大,速度是~15x。
我有一个 R
data.table
对象 DT
如下:
library(ggplot2)
library(data.table)
DT <- movies[movies$mpaa %in% c("NC-17", "PG", "PG-13", "R"), c("rating", "title", "mpaa")]
setDT(DT)
setnames(DT, colnames(DT), c("Gp", "ID", "FACTOR"))
DT[, FACTOR := droplevels(FACTOR)]
DT[, Gp := as.numeric(as.factor(Gp))]
setkey(DT, ID)
DT <- unique(DT)
DT
Gp ID FACTOR
1: 43 $windle R
2: 61 'A' gai waak PG-13
3: 62 'A' gai waak juk jaap PG-13
4: 39 'R Xmas R
5: 38 'Til There Was You PG-13
---
4899: 57 Zuotian R
4900: 27 Zyosyuu syukeininn Maria R
4901: 57 eXistenZ R
4902: 45 xXx PG-13
4903: 29 xXx: State of the Union PG-13
我正在尝试根据列 Gp
中的元素聚合 FACTOR
列中的数据。我已经能够实现如下。
k <- vector("list", max(DT$Gp))
for (i in 1:max(DT$Gp)) {
names(k)[i] <- i
k[[i]] <- DT[Gp == i, as.vector(table(FACTOR))]
}
k <- lapply(k, function(x) as.data.frame(t(x)))
k <- rbindlist(k)
setnames(k, old = colnames(k), new = c("NC-17", "PG", "PG-13", "R"))
k$Gp <- row.names(k)
setcolorder(k, c("Gp","NC-17", "PG", "PG-13", "R"))
head(k)
Gp NC-17 PG PG-13 R
1: 1 0 0 0 2
2: 2 0 0 0 1
3: 3 0 0 0 2
4: 4 0 0 0 1
5: 5 0 0 0 2
6: 6 0 0 0 3
对于Gp
的每个级别,我想获得FACTOR
每个级别的记录数。如何单独使用 data.table
更优雅地获得想要的结果 k
?
您可以在每组 Gp
中使用 as.list(table(FACTOR))
:
DT[, as.list(table(FACTOR)), by = Gp]
这给出了结果:
Gp NC-17 PG PG-13 R
1: 43 1 8 26 79
2: 61 2 9 22 77
3: 62 0 7 18 63
4: 39 0 17 24 52
5: 38 1 14 13 77
6: 57 1 11 23 72
7: 48 0 16 29 78
...
(要按照示例输出中的 Gp
对它们进行排序,您可以将其更改为 DT[order(Gp), as.list(table(FACTOR)), by = Gp]
)。
我建议为此使用 dcast
:
require(data.table) # v1.9.4
dcast.data.table(DT, Gp ~ FACTOR, fun.aggregate = length)
或者从current devel, v1.9.5(以及以后的版本)开始,我们可以直接使用dcast()
:
require(data.table) # v1.9.5+
dcast(DT, Gp ~ FACTOR, fun.aggregate = length)
as.list()
是一个 S3 通用的,并且随着更多的组会变得相当慢(由于为每个组调度正确的方法所花费的时间)。 table()
是另一个慢函数。
dcast()
也会自动按 Gp
列对结果进行排序。
这里有一个足够大的基准来突出差异:
set.seed(1L)
bmark = data.table(Gp = sample(1e5, 1e7, TRUE),
FACTOR = sample(levels(DT$FACTOR), 1e7, TRUE))
print(object.size(bmark), units="Mb")
# 114.4 Mb
system.time(ans1 <- dcast(bmark, Gp ~ FACTOR, fun.aggregate = length))
# user system elapsed
# 0.998 0.026 1.030
system.time(ans2 <- bmark[, as.list(table(FACTOR)), by=Gp])
# user system elapsed
# 14.666 0.141 15.078
identical(ans1, setkey(ans2, Gp))
# [1] TRUE
数据大小是~114MB,不算大,速度是~15x。