代码之家  ›  专栏  ›  技术社区  ›  aaaaa

分组数据。逐列框显,并根据数值向量选择行数

  •  1
  • aaaaa  · 技术社区  · 7 年前

    假设我有一个数据。框架如下:

    df = read.table(text = 'A   B
                    11 98
                    11 87
                    11 999
                    11 22
                    12 34
                    12 34
                    12 44
                    12 98
                    17 77
                    17 67
                    17 87
                    17 66
                    33 6
                    33 45
                    33 12
                    33 10', header = TRUE)
    

    我需要分组 df 按col A 并基于以下向量仅选择给定数量的行:

    n_rows = c(2, 3, 4, 2)
    

    因此,第一组只有2行(无论其顺序如何),第二组只有3行,以此类推。。。

    这里是我的预期输出:

                A   B
                11 98
                11 87
                12 34
                12 34
                12 44
                17 77
                17 67
                17 87
                17 66
                33 6
                33 45
    

    我试着用 dplyr 通过执行以下操作:

      df %>% 
      group_by(A) %>% 
      top_n(n = n_rows, wt =B)
    

    但我得到了以下错误:

    错误: n 必须是标量整数

    有什么建议吗?

    谢谢

    4 回复  |  直到 7 年前
        1
  •  3
  •   Sotos    7 年前

    另一个base R选项,

    do.call(rbind, Map(function(x, y) x[seq(y),], split(df, df$A), n_rows))
    

    因此,

          A  B
    11.1  11 98
    11.2  11 87
    12.5  12 34
    12.6  12 34
    12.7  12 44
    17.9  17 77
    17.10 17 67
    17.11 17 87
    17.12 17 66
    33.13 33  6
    33.14 33 45
    
        2
  •  2
  •   moodymudskipper    7 年前

    这是一种可能性,首先拆分 data.frame 然后使用 map2 :

    library(dplyr)
    library(purr)
    df %>% split(.$A) %>%
      map2_dfr(n_rows,head)
    
    #     A  B
    # 1  11 98
    # 2  11 87
    # 3  12 34
    # 4  12 34
    # 5  12 44
    # 6  17 77
    # 7  17 67
    # 8  17 87
    # 9  17 66
    # 10 33  6
    # 11 33 45
    

    如果顺序无关紧要,你就不需要 top_n , head 工作正常(更快),否则更换 具有 顶部 .

    编辑:

    这里还有一个整洁的解决方案,几个字符长一些,但可能更令人满意,因为你没有将相同“种类”的东西分开,而是完全在内部工作 数据框架 (相同输出)。

    df %>% nest(B) %>% 
      mutate(data = map2(data,n_rows,head)) %>%
      unnest
    
        3
  •  2
  •   Milan ValáÅ¡ek    7 年前

    在底座中 R ,您可以执行以下操作:

    df2 <- data.frame()
    
    for (i in seq_along(unique(df$A))) {
       df2 <- rbind(df2, df[df$A == unique(df$A)[i], ][1:n_rows[i], ])
    }
    
    > df2
        A  B
    1  11 98
    2  11 87
    5  12 34
    6  12 34
    7  12 44
    9  17 77
    10 17 67
    11 17 87
    12 17 66
    13 33  6
    14 33 45
    
        4
  •  2
  •   akrun    7 年前

    这里有一个选项 top_n

    library(tidyverse)
    df %>% 
       split(., .$A) %>% 
       map2_df(., n_rows, ~ top_n(., .y, wt = .$B)) 
    

    如果我们不是在寻找 顶部 ,则另一个选项是 slice

    df %>% 
       group_by(A) %>% 
       nest(B) %>% 
       mutate(newcol = map2(data, n_rows, ~ .x %>% slice(seq(.y)))) %>%
       select(-data) %>%
       unnest