使用 data.table 创建组
Creating groups using data.table
工作数据集如下所示:
library('data.table')
df <- data.table(Name = c("a","a","b","b","c","c","d","d","e","e","f","f"),
Y = sample(1:30,12),
X = sample(1:30,12))
df
Name Y X
1: a 14 23
2: a 19 18
3: b 10 16
4: b 23 11
5: c 2 12
6: c 12 24
7: d 8 14
8: d 26 2
9: e 16 26
10: e 6 4
11: f 29 28
12: f 28 30
我最终想要的是按组制作图表(基于Name
)进行比较:
library(ggplot2)
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ Name)
由于实际数据集包含更多的观察结果和 grp
。我正在创建的 ggplot 需要太多时间来处理,最终图表不可读 (grp
> 300)。我计划用有限数量的观察结果对数据进行重新分组,并分别绘制图表(例如,每次绘制 10 组图表)。
所以最终的数据集应该是这样的:
Name Y X grp level
1: a 14 23 1 1
2: a 19 18 1 1
3: b 10 16 2 1
4: b 23 11 2 1
5: c 2 12 3 1
6: c 12 24 3 1
7: d 8 14 4 2
8: d 26 2 4 2
9: e 16 26 5 2
10: e 6 4 5 2
11: f 29 28 6 2
12: f 28 30 6 2
然后我可以根据新组进行绘图 level
:
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
在上图中,我简单地创建了 grp
:
df[, grp := .GRP, by = Name]
现在的问题是如何根据grp
自动创建level
组(我必须创建grp
而不是直接使用Name
作为基础,因为,在原始数据集中,Name
) 中没有模式?
我试过类似的方法:
setkey(df, grp)
i <- 1
j <- 1
while(i < 4 ) {
df[levels(factor(grp)) == (i:i+2), level := j]
i <- i + 2
j <- j + 1
}
它不能很好地满足我的需要。谁能给我一些建议如何解决这个问题?我真的被困在这里了。我想可能有一种简单的方法可以做到这一点,也许我什至不需要创建 level
组并且可以通过其他方式直接创建单独的图形?
如果只有几个组,可以使用forcats
包中的fct_collapse()
函数。它允许轻松地将因子级别折叠到手动定义的组中。
这样就可以直接创建新变量level
,不用绕组号和cut()
了。并且,可以为级别分配有意义的标签。
library('data.table')
df <- data.table(Name = rep(letters[1:6], each = 2),
Y = sample(1:30,12),
X = sample(1:30,12))
df[, level := forcats::fct_collapse(Name, "a-c" = letters[1:3], "d-e" = letters[4:6])]
df
# Name Y X level
# 1: a 11 13 a-c
# 2: a 29 12 a-c
# 3: b 16 5 a-c
# 4: b 12 6 a-c
# 5: c 25 28 a-c
# 6: c 27 11 a-c
# 7: d 5 9 d-e
# 8: d 23 20 d-e
# 9: e 13 26 d-e
#10: e 17 19 d-e
#11: f 19 8 d-e
#12: f 22 3 d-e
但是,OP提到有很多组
(df[, uniqueN(Name)] > 300
) 并且他希望 重新分组具有有限数量观察的数据 。按照中建议的方式使用cut()
可能会导致不理想的结果。
为了证明这一点,我们需要创建一个更大的 100 行样本数据集:
N <- 100
set.seed(1234)
df <- data.table(Name = sample(letters, N, replace = TRUE),
Y = sample(seq.int(3*N), N),
X = sample(seq.int(3*N), N))
df
请注意,set.seed()
用于使数据可重现。
现在,Name
(对应于 OP 的 grp
)的唯一值的数量被分成 6 个级别并绘制在方面(在 之后):
n_lvls <- 6
df[, level := as.numeric(cut(as.integer(factor(Name)), breaks = n_lvls))]
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
在这里,方面 3 仅包含几个数据点,而其他方面显得非常拥挤。
为了克服这个问题,可以安排水平包含大约 相同数量的数据点 而不是相同数量的因子水平:
lvls <- df[, .N, by = Name][order(-N), level := cut(cumsum(N), n_lvls, labels = FALSE)]
df <- lvls[df, on = "Name"]
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
现在,观察值在各个方面的分布更加均匀。
代码计算每个 Name
的观察次数,按 N
的降序排序,使用 cut()
对观察的累积总和创建 data.table lvls
个新关卡。最后,将新的级别与原始数据集 df
.
右连接
工作数据集如下所示:
library('data.table')
df <- data.table(Name = c("a","a","b","b","c","c","d","d","e","e","f","f"),
Y = sample(1:30,12),
X = sample(1:30,12))
df
Name Y X
1: a 14 23
2: a 19 18
3: b 10 16
4: b 23 11
5: c 2 12
6: c 12 24
7: d 8 14
8: d 26 2
9: e 16 26
10: e 6 4
11: f 29 28
12: f 28 30
我最终想要的是按组制作图表(基于Name
)进行比较:
library(ggplot2)
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ Name)
由于实际数据集包含更多的观察结果和 grp
。我正在创建的 ggplot 需要太多时间来处理,最终图表不可读 (grp
> 300)。我计划用有限数量的观察结果对数据进行重新分组,并分别绘制图表(例如,每次绘制 10 组图表)。
所以最终的数据集应该是这样的:
Name Y X grp level
1: a 14 23 1 1
2: a 19 18 1 1
3: b 10 16 2 1
4: b 23 11 2 1
5: c 2 12 3 1
6: c 12 24 3 1
7: d 8 14 4 2
8: d 26 2 4 2
9: e 16 26 5 2
10: e 6 4 5 2
11: f 29 28 6 2
12: f 28 30 6 2
然后我可以根据新组进行绘图 level
:
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
在上图中,我简单地创建了 grp
:
df[, grp := .GRP, by = Name]
现在的问题是如何根据grp
自动创建level
组(我必须创建grp
而不是直接使用Name
作为基础,因为,在原始数据集中,Name
) 中没有模式?
我试过类似的方法:
setkey(df, grp)
i <- 1
j <- 1
while(i < 4 ) {
df[levels(factor(grp)) == (i:i+2), level := j]
i <- i + 2
j <- j + 1
}
它不能很好地满足我的需要。谁能给我一些建议如何解决这个问题?我真的被困在这里了。我想可能有一种简单的方法可以做到这一点,也许我什至不需要创建 level
组并且可以通过其他方式直接创建单独的图形?
如果只有几个组,可以使用forcats
包中的fct_collapse()
函数。它允许轻松地将因子级别折叠到手动定义的组中。
这样就可以直接创建新变量level
,不用绕组号和cut()
了。并且,可以为级别分配有意义的标签。
library('data.table')
df <- data.table(Name = rep(letters[1:6], each = 2),
Y = sample(1:30,12),
X = sample(1:30,12))
df[, level := forcats::fct_collapse(Name, "a-c" = letters[1:3], "d-e" = letters[4:6])]
df
# Name Y X level
# 1: a 11 13 a-c
# 2: a 29 12 a-c
# 3: b 16 5 a-c
# 4: b 12 6 a-c
# 5: c 25 28 a-c
# 6: c 27 11 a-c
# 7: d 5 9 d-e
# 8: d 23 20 d-e
# 9: e 13 26 d-e
#10: e 17 19 d-e
#11: f 19 8 d-e
#12: f 22 3 d-e
但是,OP提到有很多组
(df[, uniqueN(Name)] > 300
) 并且他希望 重新分组具有有限数量观察的数据 。按照cut()
可能会导致不理想的结果。
为了证明这一点,我们需要创建一个更大的 100 行样本数据集:
N <- 100
set.seed(1234)
df <- data.table(Name = sample(letters, N, replace = TRUE),
Y = sample(seq.int(3*N), N),
X = sample(seq.int(3*N), N))
df
请注意,set.seed()
用于使数据可重现。
现在,Name
(对应于 OP 的 grp
)的唯一值的数量被分成 6 个级别并绘制在方面(在
n_lvls <- 6
df[, level := as.numeric(cut(as.integer(factor(Name)), breaks = n_lvls))]
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
在这里,方面 3 仅包含几个数据点,而其他方面显得非常拥挤。
为了克服这个问题,可以安排水平包含大约 相同数量的数据点 而不是相同数量的因子水平:
lvls <- df[, .N, by = Name][order(-N), level := cut(cumsum(N), n_lvls, labels = FALSE)]
df <- lvls[df, on = "Name"]
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level)
现在,观察值在各个方面的分布更加均匀。
代码计算每个 Name
的观察次数,按 N
的降序排序,使用 cut()
对观察的累积总和创建 data.table lvls
个新关卡。最后,将新的级别与原始数据集 df
.