【问题标题】:dplyr filter by group conditionally with if elsedplyr 使用 if else 有条件地按组过滤
【发布时间】: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 %&gt;% count(clarity),这样更简洁。 (2) “从这些组中抽取特定数量的行” 我不确定我是否理解您的问题; group_by 加上summarise 将条目减少到每组一行。换句话说,您不能从每组的多行中抽样,因为只有一个。
  • @MauritsEvers 抱歉,如果不清楚,但我只是想显示每个组的计数。第二个代码块是我用来实际尝试获取的解决问题。
  • 那么源数据实际上每组有多行?如果是这样,您能否提供一些代表性示例数据?因为第一个代码块生成的样本数据每组只有一行(通过构造)。

标签: r if-statement filter group-by dplyr


【解决方案1】:

我们可以从split开始按所需变量“分组”数据框,然后根据每个组内的观察数量应用“map”条件抽样。

diamonds %>% split(.$clarity) %>% 
             map(function(x) if (nrow(x) <= 5066) sample_n(size = nrow(x), replace = F,x) else sample_n(size = 5000, replace = F,x)) %>% bind_rows()

更简洁

Sample_FUN <- function(x){
              if (nrow(x) <= 5000) sample_n(size = nrow(x), replace = F,x) 
              else sample_n(size = 5066, replace = F,x)
              } 

diamonds %>% split(.$clarity) %>% map(Sample_FUN) %>% bind_rows()

【讨论】:

  • 这是一个很好的开始,但输出是函数输出的数据帧列表。我正在寻找代码以返回单个数据帧,其中行符合函数中概述的标准。我能够以一种混乱的方式做到这一点,我现在将发布到原始问题。
猜你喜欢
  • 2019-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2018-12-09
  • 2016-02-11
  • 2019-09-10
  • 1970-01-01
相关资源
最近更新 更多