18

我有一个 tbl_df,我想在其中group_by(u, v)观察到的每个不同的整数组合(u, v)


编辑:这随后通过group_indices()dplyr 0.4.0中添加(现已弃用)来解决


a)然后我想为每个不同的组分配一些任意不同的数字标签= 1,2,3 ...例如组合(u,v)==(2,3)可以获得标签1,(1,3)可以得到 2,以此类推。mutate()如果没有三步汇总和自联接,如何使用 one 来做到这一点?

dplyr 有一个简洁的功能n(),但它给出了其组内元素的数量,而不是的总数。data.table这将简单地称为.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 <- tibble::as_tibble(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
4

6 回答 6

43

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

df %>% 
    mutate(label = group_indices(., u, v)) %>% 
    group_by(label) ...
于 2015-03-16T11:13:36.893 回答
11

Another approach using data.table would be

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

which results in:

    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
于 2016-08-23T18:09:00.090 回答
6

更新的答案

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))
于 2014-04-12T05:24:31.280 回答
4

从 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
于 2021-02-25T19:47:28.717 回答
2

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

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

> 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)
于 2014-04-12T06:14:35.353 回答
1

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

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

my_tibble %>% mutate(group_num = as.integer(factor(group_var, levels = unique(.$group_var))) )
于 2018-06-26T22:13:39.950 回答