Добавить счетчик последовательных наблюдений за категориальной переменной в R? - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть фрейм данных с переменной, которая группирует мои наблюдения (ID), и другая переменная, которая является категориальной (тип).Я работаю в R и пытаюсь создать новую переменную, которая подсчитывает последовательные наблюдения одного и того же типа в пределах идентификатора (данные являются временными рядами).Смотрите пример таблицы ниже - Counter - это переменная, которую я хочу создать.На самом деле не имеет значения, считается ли 0 или нет.

dat <- data.frame(id = c(rep("a", 7), rep("b", 4)),
                  type = c(0, 1, 1, 2, 2, 0, 1, 1, 1, 2, 0),
                  counter = c(0, 1, 2, 1, 2, 0, 1, 1, 2, 1, 0))

Пока что я могу сделать счетчик, хотя, возможно, не самым эффективным способом, но я борюсь с этим в рамках группировки(ID) и эффективное переключение между type = 1 и type = 2. Код, который я написал для создания счетчика, приведен ниже.Любые идеи о том, как сделать это эффективно?Спасибо.

dat$counter <- 0
counter     <- 0
for(i in 1:nrow(dat)){
  if(dat[i,"type"] != 0){
    counter <- counter + 1
    dat[i,"count"] <- counter
    # use to differentiate between 1 and 2?
    this_group <- dat[i,"type"]
  }
  if(dat[i,"type"] == 0){
    counter <- 0
  }
}

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Для каждой id, type и последовательных строк, начинающихся с type 0, создайте последовательность, используя ave и seq_along.Пакеты не используются:

transform(dat, 
  counter = (type > 0) * ave(type, id, type, cumsum(type == 0), FUN = seq_along))

подача:

   id type counter
1   a    0       0
2   a    1       1
3   a    1       2
4   a    2       1
5   a    2       2
6   a    0       0
7   a    1       1
8   b    1       1
9   b    1       2
10  b    2       1
11  b    0       0
0 голосов
/ 29 ноября 2018
library(dplyr)

dat %>%
  mutate(counter = case_when(
    type == 0 ~ 0,
    id != lag(id) ~ 1,
    type != lag(type) ~ 1
  )) %>%
  mutate(counter = case_when(
    id != lag(id) ~ 1,
    type == lag(type) ~ lag(counter) + 1,
    T ~ counter
  ))

Результат:

   id type counter
1   a    0       0
2   a    1       1
3   a    1       2
4   a    2       1
5   a    2       2
6   a    0       0
7   a    1       1
8   b    1       1
9   b    1       2
10  b    2       1
11  b    0       0

Примечание: часть кода повторяется в обоих аргументах case_when(), но эти повторы необходимы для выполнения множества условий.

Я тестировал этот код в различных условиях, и он казался надежным.Одна вещь, которую он не обрабатывает, это если у вас есть повтор при самом последнем значении (он вернет NA, потому что я использую lag()).

Этот более длинный код также охватывает эту ситуацию и (я думаю) должен работать независимо от вашего кода:

dat %>%
  mutate(counter = case_when(
    type == 0 ~ 0,
    type != lag(type) ~ 1
  )) %>%
  mutate(counter = case_when(
    id != lag(id) ~ 1,
    type == lag(type) ~ lag(counter) + 1,
    T ~ counter
  )) %>%
  mutate(counter = case_when(
    is.na(counter) ~ lag(counter) + 1,
    T ~ counter
  ))
...