Идентифицировать изменение значения (категориальное) по группе. R

#r #group-by #dplyr #lag

#r #группировать по #dplyr #задержка

Вопрос:

Ниже вы можете увидеть образец моего набора данных.

 Fac Date        Type        Change  StartDT     EndDT
AAA 1/1/2019    General     0   1/1/2019    1/2/2019
AAA 1/2/2019    General     0   1/1/2019    1/2/2019
AAA 1/3/2019    Special     1   1/3/2019    1/4/2019
AAA 1/4/2019    Special     1   1/3/2019    1/4/2019
AAA 1/5/2019    Intensive   2   1/5/2019    1/5/2019
BBB 1/1/2019    General     0   1/1/2019    1/4/2019
BBB 1/2/2019    General     0   1/1/2019    1/4/2019
BBB 1/3/2019    General     0   1/1/2019    1/4/2019
BBB 1/4/2019    General     0   1/1/2019    1/4/2019
BBB 1/5/2019    Reserve     1   1/5/2019    1/6/2019
BBB 1/6/2019    Reserve     1   1/5/2019    1/6/2019
  

Я хотел бы создать переменную для отслеживания изменений в моей переменной типа (change). Раньше я работал в Stata, и логика для этого заключается в том, чтобы сначала отследить, изменилось ли значение по сравнению с предыдущей записью (0/1) для каждой панели / группы, а затем получить текущую сумму этого значения.

 bysort Facility (Date): gen byte era = sum(Type != Type[_n-1] amp; _n > 1) 
  

Как я могу это сделать в R? Также после создания переменной изменения мне нужно будет сгенерировать начальную и конечную (минимальную, максимальную) даты для каждого Fac и изменения («era»).

Я был бы признателен за любую помощь! Заранее спасибо! Марвин

Комментарии:

1. Пожалуйста, объясните, почему здесь изменение = 2 AAA 1/5/2019 Intensive 2 1/5/2019 1/5/2019

2. Потому что оно перешло из специального в интенсивное. Любое изменение в этой переменной должно отслеживаться. Итак, если тип объекта AAA снова изменится, нам нужно будет записать это, и это будет 3.

Ответ №1:

Вот одно из решений, использующее dplyr:

 dat =
  tibble(
    fac = c(rep("A", 10), rep("B", 10)),
    type = sample(1:3, 20, replace = TRUE)
  )

dat %>% 
  group_by(fac) %>% 
  mutate(
    change = case_when(
      type != lag(type) ~ TRUE,
      TRUE ~ FALSE
    ),
    n_change = cumsum(change)
  )
  

Для вашего кода вы могли бы затем добавить:

 group_by(Fac, n_change) %>%
mutate(
  min_start_date = min(StartDT),
  max_start_date = max(EndDT)
)
  

Ответ №2:

Рассмотрите возможность перебора последовательности номеров строк с sapply , чтобы проверить соответствие между значениями типа текущей строки и предыдущей. И использовать ave для встроенной агрегации итогов по группе Fac:

 dat <- within(dat, {
  # CONVERT DATES
  Date <- with(dat, as.Date(Date, format="%m/%d/%Y"))
  StartDT <- with(dat, as.Date(StartDT, format="%m/%d/%Y"))
  EndDT <- with(dat, as.Date(StartDT, format="%m/%d/%Y"))

  # CALCULATE TYPE CHANGES
  type_delta <- c(NA, sapply(2:nrow(dat), function(i) 
                               ifelse(dat$Type[i] != dat$Type[i-1], 1, 0)
                             )
                 )
  era <- ave(type_delta, Fac, FUN=function(x) sum(x, na.rm=TRUE))
})

dat    
#    Fac       Date      Type Change    StartDT      EndDT era type_delta
# 1  AAA 2019-01-01   General      0 2019-01-01 2019-01-01   2         NA
# 2  AAA 2019-01-02   General      0 2019-01-01 2019-01-01   2          0
# 3  AAA 2019-01-03   Special      1 2019-01-03 2019-01-03   2          1
# 4  AAA 2019-01-04   Special      1 2019-01-03 2019-01-03   2          0
# 5  AAA 2019-01-05 Intensive      2 2019-01-05 2019-01-05   2          1
# 6  BBB 2019-01-01   General      0 2019-01-01 2019-01-01   2          1
# 7  BBB 2019-01-02   General      0 2019-01-01 2019-01-01   2          0
# 8  BBB 2019-01-03   General      0 2019-01-01 2019-01-01   2          0
# 9  BBB 2019-01-04   General      0 2019-01-01 2019-01-01   2          0
# 10 BBB 2019-01-05   Reserve      1 2019-01-05 2019-01-05   2          1
# 11 BBB 2019-01-06   Reserve      1 2019-01-05 2019-01-05   2          0
  

Ответ №3:

Огромное спасибо @Parfait и @user2363777 за всю помощь! Это потрясающе. Я использовал решение user2363777, поскольку я больше знаком с dplyr. Для последнего блока кода я просто включил функцию ungroup() в конце. Тогда я просто сохраняю одну запись на объект и эпоху.

 Fac Era Type            StartDT     EndDT
AAA 0   General         1/1/2019    1/2/2019
AAA 1   Special         1/3/2019    1/4/2019
AAA 2   Intensive       1/5/2019    1/5/2019
BBB 0   General         1/1/2019    1/4/2019
BBB 1   Reserve         1/5/2019    1/6/2019
  

Моя конечная цель — сгенерировать график, который отображает изменения в типах объектов с течением времени (изменение категориальной переменной с течением времени). Я собираюсь исследовать, как я могу отобразить это на графике. Возможно, я скоро опубликую что-нибудь по этому поводу. Спасибо!!