【问题标题】:Select top fraction n rows (by value) but if the fraction of n rows is lower than 1 keep all rows选择前 n 行(按值),但如果 n 行的分数小于 1,则保留所有行
【发布时间】:2019-12-16 17:39:15
【问题描述】:

作为一个例子,我有这个 data.frame

df <- structure(list(var_1 = c(7578L, 21L, 4534L, 53L, 457L, 621L, 
                               878L, 636L, 1111L, 25L, 23L, 99L), var_2 = c(1L, 1L, 2L, 2L, 
                                                                            2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                  -12L))

我想按 var_2 分组,然后找到每个组的前 30%。但是如果一个组中有 30% 的行小于 1,那么我想保留所有行。

所以我做了这个函数(改编自dplyr的top_n函数):

top_frac_keep_lower <- function(x, n, wt) {
  if ((nrow(x) * {{ n }}) < 1) {
    x
  } else {
    top_frac(x, {{ n }}, {{ wt }})
  }
}

如果您首先过滤 var_2 中的一个组,则该功能起作用:

df_var_2_1 <- filter(df, df$var_2 == 1)
top_frac_keep_lower(df_var_2_2, 0.3, var_1)

 var_1 var_2
1  7578     1
2    21     1

df_var_2_2 <- filter(df, df$var_2 == 2)
top_frac_keep_lower(df_var_2_2, 0.3, var_1)

  var_1 var_2
1  4534     2
2   878     2
3  1111     2

但是如果你使用 grouped_by 就不行了:

df %>% 
  group_by(var_2) %>% 
  top_frac_keep_lower(n = 0.3, var_1)

# A tibble: 3 x 2
# Groups:   var_2 [1]
  var_1 var_2
  <int> <int>
1  4534     2
2   878     2
3  1111     2

那么为什么这不起作用?我错过了什么?

【问题讨论】:

  • 只有几厘米。我建议将名为 n 的参数更改为 p 或其他内容。通常 n 意味着一个计数,因此将其用作百分比是出乎意料的。我也不确定你为什么要在两个花括号内包装一些值。它不会伤害任何东西,但我不明白为什么它是必要的,再一次......有点令人困惑。

标签: r dplyr


【解决方案1】:

我们可以使用group_split,因为函数使用nrow

library(purrr)
library(dplyr)
df %>% 
 group_split(var_2) %>% 
  map_dfr(top_frac_keep_lower, n = 0.3, var_1)

【讨论】:

  • 感谢这项工作!但是还有一种方法可以使该函数与 group_by 一起使用吗?
  • @Artie16 为此,top_frac_keep_lower 函数可能需要一些更改
  • 确实如此。但是怎么做?我认为应该做的是检查其中一个组中的元素数乘以 n 是否小于 1。但是您如何获得这些信息? nrow 不适用于 group_bycount(x)[2] 给出错误:the condition has length &gt; 1 and only the first element will be used
  • @Artie16 您可以使用do,但使用map 会更有效,即df %&gt;% group_by(var_2) %&gt;% do(if((nrow(.) * 0.3) &lt; 1 ) . else top_frac(., n = 0.3, .$var_1))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 2011-06-23
  • 2013-06-08
  • 2016-08-11
相关资源
最近更新 更多