使用data.table创建组

时间:2016-04-22 20:43:58

标签: r ggplot2 data.table graphing

工作数据集如下所示:

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&gt; 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]

现在的问题是如何根据level自动创建grp群组(我必须创建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组并可以通过其他方式直接创建单独的图形?

1 个答案:

答案 0 :(得分:1)

如果只有几个组,则可以使用fct_collapse()包中的forcats函数。它允许轻松地将因子级别折叠为手动定义的组。

这样,可以直接创建新变量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)并且他希望使用有限数量的观察值重新分组数据。以this comment中提议的方式使用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&#39; s grp)的唯一值的数量分为6个级别,并在方面(this comment之后)中绘制:< / p>

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)

enter image description here

此处,方面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)

enter image description here

现在,观察结果更均匀地分布在各个方面。

代码计算每Name个观察的数量,按N的降序排序,对累积观察总和使用cut()来创建数据。{{1}新的水平。最后,新级别与原始数据集lvls正确连接。