【发布时间】:2018-06-20 00:06:28
【问题描述】:
在 dplyr 中使用 group_by 后,如果行数少于 x,我想使用 filter 对组中的所有行进行采样,而如果行数超过 x,我想对特定数字进行子采样来自这些组的行数。我将使用按净度分组的钻石数据集进行说明。
diamonds %>%
group_by(clarity) %>%
summarise(count = n())
# A tibble: 8 x 2
clarity count
<ord> <int>
1 I1 741
2 SI2 9194
3 SI1 13065
4 VS2 12258
5 VS1 8171
6 VVS2 5066
7 VVS1 3655
8 IF 1790
使用此示例,如果清晰度组的行数为 5066 或更少,我想对所有行进行采样,而在超过 5066 行的组中,我想使用 sample_n 而不替换以随机采样 5000 行。仅当size 等于或小于最小组中的行数时,没有替换的sample_n 才有效。在尝试了很多事情后我被困住了,但这是我思考过程的一个例子。
diamonds %>%
group_by(clarity) %>%
if_else(n() > 5066, sample_n(size = 5000, replace = F), filter())
我对 dplyr 还很陌生,而且总体上仍然熟悉 R。我确信这是相对容易的事情,但我没有看到发布的明确解决方案。提前致谢!
编辑:
我非常想要以下代码的输出,但在一行代码中。
# groups below or equal to 5066
low_sample_groups <- diamonds %>%
group_by(clarity) %>%
filter( n() <= 5066)
# groups above 5066
high_sample_groups <- diamonds %>%
group_by(clarity) %>%
filter( n() > 5066) %>%
sample_n(size = 5000, replace = F)
desired_result <- full_join(low_sample_groups, high_sample_groups)
编辑第 2 轮
在这里找到了我想要的答案:custom grouped dplyr function (sample_n)
基本上这是使用 if 语句的解决方案
n <- 5066
desired_result <- diamonds %>%
group_by(clarity) %>%
sample_n(if(n() < n) n() else n)
【问题讨论】:
-
(1) 可以将第一个链改写为
diamonds %>% count(clarity),这样更简洁。 (2) “从这些组中抽取特定数量的行” 我不确定我是否理解您的问题;group_by加上summarise将条目减少到每组一行。换句话说,您不能从每组的多行中抽样,因为只有一个。 -
@MauritsEvers 抱歉,如果不清楚,但我只是想显示每个组的计数。第二个代码块是我用来实际尝试获取的解决问题。
-
那么源数据实际上每组有多行?如果是这样,您能否提供一些代表性示例数据?因为第一个代码块生成的样本数据每组只有一行(通过构造)。
标签: r if-statement filter group-by dplyr