R: перезапустить счетчик для каждой группы - PullRequest
1 голос
/ 12 марта 2019

Я много читал и много тестировал, но безуспешно.Я пытаюсь создать счетчик для каждой группы, но этот coutner должен перезапускаться каждый раз, когда появляется группа (даже если она «появляется»).

Пример:

Мне нужен seq_along для TYPE_OF_PROMOTIONэто перезапуск для каждой группы.Результат должен быть примерно таким: counter Поскольку промо B снова появляется на 18-й неделе, но это новый вид - перезапустите счетчик.

Если решение работает и для NA - хорошо, я просто сделал небольшую демонстрацию.

   Week TYPE_OF_PROMOTION counter
11   11              <NA>      NA
12   12                 B       1
13   13                 B       2
14   14                 B       3
15   15              <NA>      NA
16   16              <NA>      NA
17   17              <NA>      NA
18   18                 B       1
19   19                 B       2
20   20              <NA>      NA

1 Ответ

1 голос
/ 12 марта 2019

Вот вариант с data.table. Преобразуйте файл «data.frame» в «data.table» (setDT(df1)), сгруппированный по идентификатору длины прогона «TYPE_OF_PROMOTION», создайте последовательность строк (seq_len(.N)), умноженную на строки с NA в 'TYPE_OF_PROMOTION' для создания столбца 'counter'

library(data.table)
setDT(df1)[, counter2 := seq_len(.N) * NA^is.na(TYPE_OF_PROMOTION), 
      by = rleid(TYPE_OF_PROMOTION)]
df1
#    Week TYPE_OF_PROMOTION counter counter2
# 1:   11              <NA>      NA       NA
# 2:   12                 B       1        1
# 3:   13                 B       2        2
# 4:   14                 B       3        3
# 5:   15              <NA>      NA       NA
# 6:   16              <NA>      NA       NA
# 7:   17              <NA>      NA       NA
# 8:   18                 B       1        1
# 9:   19                 B       2        2
#10:   20              <NA>      NA       NA

Или dplyr с использованием rleid из data.table

library(dplyr)
df1 %>%
    group_by(grp = rleid(TYPE_OF_PROMOTION)) %>%
    mutate(counter2 = case_when(is.na(TYPE_OF_PROMOTION) ~ NA_integer_, 
                              TRUE ~ row_number())) %>%
    ungroup %>%
    select(-grp)

или использование base R с rle

with(df1, with(rle(!is.na(TYPE_OF_PROMOTION)), 
          sequence(lengths) * rep(NA^!values, lengths)))
#[1] NA  1  2  3 NA NA NA  1  2 NA

Данные

df1 <- structure(list(Week = 11:20, TYPE_OF_PROMOTION = c(NA, "B", "B", 
"B", NA, NA, NA, "B", "B", NA), counter = c(NA, 1L, 2L, 3L, NA, 
NA, NA, 1L, 2L, NA)), class = "data.frame", row.names = c("11", 
 "12", "13", "14", "15", "16", "17", "18", "19", "20"))
...