Использование mutate в функции Summarise с использованием R

#r #dataframe #dplyr #tidyr #lubridate

#r #фрейм данных #dplyr #tidyr #lubridate

Вопрос:

У меня есть фрейм данных, подобный показанному ниже

 identifier date       from       to         type  shift_back_max shift_forward_max
   <chr>      <date>     <date>     <date>     <chr>          <dbl>             <dbl>
   11         2011-12-31 2011-01-01 2011-12-31 last             364                 0
   11         2009-07-11 2009-01-01 2009-12-31 last             191               173
   11         NA         NA         NA         last              NA                NA
   11         2013-05-21 2013-01-01 2013-12-31 last             140               224
   11         2017-06-06 2017-01-01 2017-12-31 last             156               208
   12         2014-04-03 2014-01-01 2014-12-31 NA                92               272
   12         2016-08-04 2016-01-01 2016-12-31 NA               216               149
   12         2014-03-05 2014-01-01 2014-12-31 NA                63               301
   13         2011-02-07 2011-01-01 2011-12-31 NA                37               327
   14         2014-04-04 2014-01-01 2014-12-31 first             93               271
   14         2011-01-01 2011-01-01 2011-12-31 first              0               364
   14         2016-06-21 2016-01-01 2016-12-31 first            172               193
   16         NA         NA         NA         NA                NA                NA
   17         NA         NA         NA         NA                NA                NA
   18         NA         NA         NA         NA                NA                NA
   19         NA         NA         NA         NA                NA                NA
  

Я пробую следующие сценарии

Сценарий — 1 (с использованием mutate во всем stmt)

 data %>%
   group_by(identifier) %>%
   summarize(shift_back_max = - min(shift_back_max, na.rm = TRUE),
            shift_forward_max = min(shift_forward_max, na.rm = TRUE),
            mutate(across(starts_with("shift"), ~ ifelse(is.infinite(.x), 30 * sign(.x), .x))))
  

Сценарий — 2 (без использования mutate во всем stmt)

 data %>%
   group_by(identifier) %>%
   summarize(shift_back_max = - min(shift_back_max, na.rm = TRUE),
            shift_forward_max = min(shift_forward_max, na.rm = TRUE),
            across(starts_with("shift"), ~ ifelse(is.infinite(.x), 30 * sign(.x), .x)))
  

Оба сценария выдают один и тот же результат, как показано ниже. Итак , какая польза от mutate stmt в across stmt?Можете ли вы сообщить мне, является ли это плохой практикой программирования или это приведет к неправильному выводу в каком-либо конкретном случае? Я использую across stmt для замены -Inf на -30 и Inf на 30 . Я уже применил сценарий 2 к своим данным из нескольких миллионов записей и сделал это. Должен ли я перезапускать снова, поскольку это может иметь неверный вывод или это просто плохая практика программирования?

какой из двух сценариев является правильным? означает ли это, что другие сценарии могут выдавать неверный вывод? можете мне помочь, пожалуйста?

введите описание изображения здесь

Ответ №1:

Я нахожу использование mutate внутри summarize очень запутанным и на самом деле не знаю, чего от этого ожидать (я, честно говоря, удивлен, что это вообще работает). Если я правильно понимаю, то то, что вы хотите сделать, лучше всего выразить как (Сценарий — 3):

 data %>%
   group_by(identifier) %>%
   summarize(shift_back_max = - min(shift_back_max, na.rm = TRUE),
             shift_forward_max = min(shift_forward_max, na.rm = TRUE)) %>%
   ungroup() %>%
   mutate(across(starts_with("shift"), ~ ifelse(is.infinite(.x), 30 * sign(.x), .x))))
  

(это означает, что вы сначала суммируете по идентификатору, затем применяете обработку ко всему результату)

Вы можете сравнить результаты различных подходов с all.equal() . Я бы ожидал, что все эти подходы дадут одинаковый результат, но не будут такими понятными для читателя.

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

1. Спасибо. Поддержано.. как насчет сценария 2? Это тоже неверно?

2. Это несколько субъективно, но я тоже нахожу это неясным, поскольку, когда я вижу, summarize() я знаю, что вы собираетесь агрегировать значение для данного group , и когда я вижу mutate() , я знаю, что вы собираетесь применить операцию к столбцу. Итак, с вашим across() в summarize я ожидаю, что группировка в некотором роде важна. Итак, не неверно, но не так ясно, как могло бы быть.

3. Большое спасибо за вашу помощь. Я новичок в R и применил сценарий 2 к своим данным, которые содержат миллионы записей (огромный набор данных). Для повторного запуска может потребоваться время. Следовательно, я хотел проверить, может ли это привести к неправильному выводу. Как вы предложили, если это проблема с удобочитаемостью, я могу исправить код, но не запускать его повторно. Следовательно, пытался проконсультироваться с экспертами здесь, на форуме

4. Я думаю, что это должно сработать (но я не уверен, насколько я эксперт). Вы можете проверить 10 000 записей (с помощью slice() ), чтобы убедиться.

5. Могу ли я любезно уточнить у вас, что заставляет вас «думать», что это сработает, вместо того, чтобы быть «уверенным», что это сработает? Вы думаете о каких-либо сценариях, когда это может привести к сбою? Просто спрашиваю, когда я пробовал с тестовыми записями, все работает нормально.