根据另一列的最终累积总和创建新变量

时间:2019-04-24 16:19:51

标签: r dplyr

我想创建一个新变量:

  • 总结一列的计数
  • 然后根据最高数量按升序将排名分配给组
  • ,如果两个(或多个)累积计数相同,则将其分配 下一个号码。

这是一个测试小标题:

df.test <- tibble(
  "group"  = c(1, 1, 2, 2, 2, 3, 3, 2, 2, 1, 4),
  "score" = c(0, 2, 1, 3, 2, 2, 1, 2, 0, 0, 2)
)

这就是我想要的样子:

# A tibble: 11 x 4
   group score cum.score  rank
   <dbl> <dbl>     <dbl> <dbl>
 1     1     0         0     1
 2     1     2         2     1
 3     2     1         1     4
 4     2     3         4     4
 5     2     2         6     4
 6     3     2         2     3
 7     3     1         3     3
 8     2     2         8     4
 9     2     0         8     4
10     1     0         2     1
11     4     2         2     2

请注意,第4组被分配为等级2,因为它的得分与被分配为等级1的第1组相同。

这是我得到的最接近的(不是很接近):

df.test %>%
  group_by(group) %>%
  mutate(cum.score = cumsum(score),
         rank = last(cum.score))

但是rank只是将总数归因于他们,而不是实际排名。

3 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是计算子表中的组等级,然后将其与原始表连接起来。您可以使用

df.test %>%
  group_by(group) %>%
  mutate(cum.score = cumsum(score)) %>% {
    x <- .
    x %>% summarize(max = max(cum.score)) %>% 
    mutate(rank=rank(max, ties.method ="first"), max=NULL) %>% 
    left_join(x, .)
  }

这似乎很有必要,因为您希望在组内分配值,但希望在组间分配等级。

答案 1 :(得分:2)

我意识到这是用dplyr标记的,但是由于已经有了不错的dplyr解决方案,因此我将添加一个data.table版本。

data.table中,您可以连接两个表ab,并向b添加b$x列(例如a)到a[b, on = .(somevar), x := i.x] library(data.table) setDT(df.test) df.test[, cum.score := cumsum(score), group] df.test[df.test[, max(cum.score), group][, V1 := frank(V1, ties.method = 'first')] , on = .(group), rank := i.V1] df.test # group score cum.score rank # 1: 1 0 0 1 # 2: 1 2 2 1 # 3: 2 1 1 4 # 4: 2 3 4 4 # 5: 2 2 6 4 # 6: 3 2 2 3 # 7: 3 1 3 3 # 8: 2 2 8 4 # 9: 2 0 8 4 # 10: 1 0 2 1 # 11: 4 2 2 2

Rails.cache.fetch

答案 2 :(得分:2)

首先在组内定义cum.score。还要在组中将rank定义为逻辑变量,该逻辑变量的最后一个值为TRUE。然后在分组之外,使用NA为组内除最后一个值以外的其他值对最后cum.score个值进行排名,即在先前步骤中分配为FALSE的那些值。最后,在第二个分组中,用该组的等级填充NA。

df.test %>%
  group_by(group) %>%
  mutate(cum.score = cumsum(score), rank = 1:n() == n()) %>%
  ungroup %>%
  mutate(rank = replace(NA * score, rank, rank(cum.score[rank], ties = "first"))) %>%
  group_by(group) %>%
  mutate(rank = na.omit(rank)) %>%
  ungroup