我想创建一个新变量:
这是一个测试小标题:
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
只是将总数归因于他们,而不是实际排名。
答案 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
中,您可以连接两个表a
和b
,并向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