首页 文章

如何通过group_by中的group-number对数据表进行编号/标记?

提问于
浏览
16

我有一个tbl_df,我希望 group_by(u, v)(u, v) 观察到的每个不同的整数组合 .


EDIT: 这是通过在dplyr 0.4.0中添加 group_indices() 来解决的


a)然后我想为每个不同的组分配一些任意的不同数字标签= 1,2,3 ...组合(u,v)==(2,3)可以得到标签1,(1,3)可以得到2,依此类推 . 如何使用一个 mutate() ,没有三步汇总和自我加入?

dplyr有一个简洁的函数 n() ,但是它给出了组的数量 within ,而不是整个 number of the group . In data.table this would simply be called .GRP .

b)实际上我真正想要分配一个字符串/字符标签('A','B',...) . 但是按整数对组进行编号是足够好的,因为我可以使用 integer_to_label(i) ,如下所示 . 除非有这个部分出汗 .

set.seed(1234)

# Helper fn for mapping integer 1..26 to character label
integer_to_label <- function(i) { substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ",i,i) }

df <- tbl_df(data.frame(u=sample.int(3,10,replace=T), v=sample.int(4,10,replace=T)))

# Want to label/number each distinct group of unique (u,v) combinations
df %>% group_by(u,v) %>% mutate(label = n()) # WRONG: n() is number of element within its group, not overall number of group

   u v
1  2 3
2  1 3
3  1 2
4  2 3
5  1 2
6  3 3
7  1 3
8  1 2
9  3 1
10 3 4

KLUDGE 1: could do df %>% group_by(u,v) %>% summarize(label = n()) , then self-join

5 回答

  • 2

    更新的答案

    get_group_number = function(){
        i = 0
        function(){
            i <<- i+1
            i
        }
    }
    group_number = get_group_number()
    df %>% group_by(u,v) %>% mutate(label = group_number())
    

    您还可以考虑以下稍微不可读的版本

    group_number = (function(){i = 0; function() i <<- i+1 })()
    df %>% group_by(u,v) %>% mutate(label = group_number())
    

    使用 iterators

    library(iterators)
    
    counter = icount()
    df %>% group_by(u,v) %>% mutate(label = nextElem(counter))
    
  • 4

    dplyr有一个 group_indices() 函数,您可以像这样使用:

    df %>% 
        mutate(label = group_indices(., u, v)) %>% 
        group_by(label) ...
    
  • 8

    使用 data.table 的另一种方法是

    require(data.table)
    setDT(df)[,label:=.GRP, by = c("u", "v")]
    

    这导致:

    u v label
     1: 2 1     1
     2: 1 3     2
     3: 2 1     1
     4: 3 4     3
     5: 3 1     4
     6: 1 1     5
     7: 3 2     6
     8: 2 3     7
     9: 3 2     6
    10: 3 4     3
    
  • 38

    用三种不同的方式更新我的答案:

    A)使用 interaction(u,v) 的整洁的非dplyr解决方案:

    > df$label <- factor(interaction(df$u,df$v, drop=T))
     [1] 1.3 2.3 2.2 2.4 3.2 2.4 1.2 1.2 2.1 2.1
     Levels: 2.1 1.2 2.2 3.2 1.3 2.3 2.4
    
    > match(df$label, levels(df$label)[ rank(unique(df$label)) ] )
     [1] 1 2 3 4 5 4 6 6 7 7
    

    B)使Randy的快速和肮脏的发电机功能更加紧凑:

    get_next_integer = function(){
      i = 0
      function(u,v){ i <<- i+1 }
    }
    get_integer = get_next_integer() 
    
    df %>% group_by(u,v) %>% mutate(label = get_integer())
    

    C)这里还有一个使用生成器函数的单行程序滥用this的全局变量赋值:

    i <- 0
    generate_integer <- function() { return(assign('i', i+1, envir = .GlobalEnv)) }
    
    df %>% group_by(u,v) %>% mutate(label = generate_integer())
    
    rm(i)
    
  • 0

    我没有足够的评论声誉,所以我发布了一个答案 .

    使用factor()的解决方案是一个很好的解决方案,但它的缺点是在factor()按字母顺序排列其级别后分配了组号 . dplyr的group_indices()也会发生同样的行为 . 您可能希望根据当前组顺序将组编号从1分配给n . 在这种情况下,您可以使用:

    my_tibble %>% mutate(group_num = as.integer(factor(group_var, levels = unique(.$group_var))) )
    

相关问题