【问题标题】:Filter grouped data by the top X groups based on certain variable根据特定变量按前 X 组过滤分组数据
【发布时间】:2021-07-05 08:59:43
【问题描述】:

我想按在某个变量中表现出最大值的一定数量的用户过滤分组数据集。该变量的值在组内没有变化。

简单示例:假设有 3 个个人,我们观察他们的访问总数。

da = data.frame(id = c(1,1,1,2,2,2,3,3,3), n_visits = c(3,3,3,2,2,2,1,1,1))
da
  id n_visits
1  1        3
2  1        3
3  1        3
4  2        2
5  2        2
6  2        2
7  3        1
8  3        1
9  3        1

现在我要选择访问次数最多的 2 个用户,在我的示例中是 id 为“1”和“2”的用户。

我尝试了“top_n”函数,但它输出了三个人的数据。

da %>% group_by(id) %>%
   top_n(2, n_visits)

# A tibble: 9 x 2
# Groups:   id [3]
     id n_visits
  <dbl>    <dbl>
1     1        3
2     1        3
3     1        3
4     2        2
5     2        2
6     2        2
7     3        1
8     3        1
9     3        1

我期望的输出是:

         id n_visits
      <dbl>    <dbl>
    1     1        3
    2     1        3
    3     1        3
    4     2        2
    5     2        2
    6     2        2

【问题讨论】:

    标签: r select filter dplyr


    【解决方案1】:

    这是一种使用 join 的方法:

    inner_join(da, da %>% unique() %>% top_n(2, n_visits))
    # Joining, by = c("id", "n_visits")
    #   id n_visits
    # 1  1        3
    # 2  1        3
    # 3  1        3
    # 4  2        2
    # 5  2        2
    # 6  2        2
    

    【讨论】:

    • 谢谢,这行得通。我的数据非常大,并且在使用您的 inner_join 解决方案时运行时间很长(...尚未完成) - 有没有更快的解决方案?
    • @Scijens,如果您的数据量很大,使用 data.table 应该更快,就像 Yuriy 的回答一样。
    【解决方案2】:

    这行得通吗:

    da %>% mutate(rank = dense_rank(desc(n_visits))) %>% 
         filter(rank %in% c(1,2)) %>% 
             select(-rank)
      id n_visits
    1  1        3
    2  1        3
    3  1        3
    4  2        2
    5  2        2
    6  2        2
    

    【讨论】:

      【解决方案3】:

      尝试使用 data.table

      library(data.table)
      da = data.frame(id = c(1,1,1,2,2,2,3,3,3), n_visits = c(3,3,3,2,2,2,1,1,1))
      setDT(da)
      merge(da, unique(da)[order(-n_visits)][1:2], all.y = T, by = c("id", "n_visits"))
      #>    id n_visits
      #> 1:  1        3
      #> 2:  1        3
      #> 3:  1        3
      #> 4:  2        2
      #> 5:  2        2
      #> 6:  2        2
      

      reprex package (v2.0.0) 于 2021-04-09 创建

      【讨论】:

      • 谢谢,t 适用于示例,在我的真实数据上输出: Fehler in vecseq(f__, len__, if (allow.cartesian || notjoin || !anyDuplicated(f__, : Join results in 17557500 行;超过 9252065 = nrow(x)+nrow(i)。检查 i 中的重复键值,每个键值都一遍又一遍地加入 x 中的同一组。如果没问题,请尝试 by=.EACHI 运行j 为每个组分配以避免大分配。如果您确定要继续,请重新运行 allow.cartesian=TRUE。否则,请在 FAQ、Wiki、Stack Overflow 和 data.table 问题跟踪器中搜索此错误消息建议。
      • 你在我电脑上的错误是不可重现的n &lt;- 200 x &lt;- 1:100000 y &lt;- 100000:1 dt &lt;- data.table(id = rep(x, each = n), n_visits = rep(y, each = n)) nrow(dt) merge(dt, unique(dt)[order(-n_visits)][1:2], all.y = T, by = c("id", "n_visits"))也许更有经验的data.table用户会回答
      【解决方案4】:

      基本 R 选项

      subset(
        da,
        n_visits %in% head(sort(unique(n_visits), decreasing = TRUE), 2)
      )
      

      给予

        id n_visits
      1  1        3
      2  1        3
      3  1        3
      4  2        2
      5  2        2
      6  2        2
      

      【讨论】:

        猜你喜欢
        • 2017-03-07
        • 2018-06-11
        • 2022-10-20
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 2018-11-15
        • 2014-05-23
        • 1970-01-01
        相关资源
        最近更新 更多