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

时间:2014-04-12 04:38:27

标签: r group-by dplyr indices

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


编辑:通过在dplyr 0.4.0

中添加group_indices()来解决此问题

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

dplyr有一个整洁的函数n(),但是它给出了元素元素的数量,而不是的整体数量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 个答案:

答案 0 :(得分:38)

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

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

答案 1 :(得分: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

答案 2 :(得分:4)

更新回答

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))

答案 3 :(得分:2)

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

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)

答案 4 :(得分:2)

从 dplyr 1.0.4 版开始,函数 cur_group_id() 已取代旧函数 group_indices

在分组的 data.frame 上调用它:

df %>%
  group_by(u, v) %>%
  mutate(label = cur_group_id())

# A tibble: 10 x 3
# Groups:   u, v [6]
       u     v label
   <int> <int> <int>
 1     2     2     4
 2     2     2     4
 3     1     3     2
 4     3     2     6
 5     1     4     3
 6     1     2     1
 7     2     2     4
 8     2     4     5
 9     3     2     6
10     2     4     5