Создать новую переменную на основе итоговой кумулятивной суммы другого столбца - PullRequest
1 голос
/ 24 апреля 2019

Я хотел бы создать новую переменную, которая:

  • суммирует количество столбцов
  • затем присваивает ранг группе в соответствии с наибольшим количеством в порядке возрастания
  • и если два (или более) кумулятивных счета одинаковы, он присваивает их следующий номер.

Вот тестовый тиббл:

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 ]

2 голосов
/ 24 апреля 2019

Я понимаю, что это помечено 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
2 голосов
/ 24 апреля 2019

Сначала определите cum.score в группе.Также определите rank внутри группы как логическую переменную, которая равна TRUE для последнего значения.Затем за пределами группировки ранжируют последние cum.score значения, используя NA для значений, отличных от последних в группе, то есть для тех значений, которые были присвоены FALSE на предыдущем шаге.Наконец, во второй группе заполните АН с рангом для этой группы.

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
2 голосов
/ 24 апреля 2019

Один из способов сделать это состоит в том, чтобы вычислить ранги групп в вложенной таблице и объединить их с оригиналом.Вы можете сделать это с помощью

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, .)
  }

Это кажется необходимым, потому что вы хотите, чтобы значения были назначены внутри группы, но вы хотите, чтобы ранг назначался между группами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...