Использование (.) В case_when () как части mutate () в сгруппированном тибле - PullRequest
3 голосов
/ 28 мая 2020

У меня есть данные следующего типа:

library(tidyverse)
library(lubridate)

data <- tibble(a = c(1, 1, 2, 3, 3),
               b = c('x', 'y', 'z', 'z', 'z'),
               c = c('ps', 'ps', 'qs', 'rs', 'rs'),
               d = c(100, 200, 300, 400, 500),
               strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01')),
               fnsh = ymd(c(NA, NA, NA, '2020-06-01', '2016-05-01')))

Операция должна применяться к данным, сгруппированным по a, b, c (т.е. data %>% group_by(a, b, c)). Я хочу добавить столбец, который показывает, есть ли у группы старт в течение последнего года. Чтобы начать работу в течение последнего года, группа должна:

1) иметь строку с strt в течение последнего года

2) не иметь строки с strt до последнего года и fn sh как NA (без дисквалифицирующего перекрытия)

3) Отсутствует строка с strt до последнего года и fn sh равной или более поздней, чем последняя из всех записей в strt (без дисквалификации перекрытие)

Таким образом, я пытаюсь получить:

tibble(a = c(1, 1, 2, 3, 3),
       b = c('x', 'y', 'z', 'z', 'z'),
       c = c('ps', 'ps', 'qs', 'rs', 'rs'),
       d = c(100, 200, 300, 400, 500),
       strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01')),
       fnsh = ymd(c(NA, NA, NA, '2020-06-01', '2016-05-01')),
       startLatestYear = c(0, 1, 0, 1, 1))

Мой текущий подход:

test <- data %>%
  group_by(a, b, c) %>%
  mutate(startLatestYear = case_when(all(is.na(fnsh)) &
                                     min(strt) > today(tzone = 'CET') - years(1) &
                                     min(strt) <= today(tzone = 'CET') ~ 1,
                                     strt > today(tzone = 'CET') - years(1) &
                                     strt <= today(tzone = 'CET') &
                                     nrow(filter(., strt < today(tzone = 'CET') - years(1) &
                                                    fnsh %in% NA)) == 0 &
                                     nrow(filter(., strt < today(tzone = 'CET') - years(1))) > 0 &
                                     strt > max(pull(filter(., strt < today(tzone = 'CET') - years(1)), fnsh)) ~ 1,
                                     TRUE ~ 0))

Первый if в моем использовании case_when() вроде работает, а второй нет. Я подозреваю, что я неправильно использовал .. Как я могу получить желаемый результат?

1 Ответ

1 голос
/ 28 мая 2020

. - это средство, предоставляемое пакетом magrittr, где оно относится к левой части оператора %>%. %>% ничего не знает о глаголах dplyr, поэтому, когда вы используете . внутри mutate, он просто расширяется до объекта, который был передан по конвейеру. В случае сгруппированного df это означает весь df, а не сгруппированные подмножества.

Лучшее решение, которое я нашел до сих пор, - заменить mutate на group_modify:

data %>%
    group_by(a, b, c) %>%
    group_modify(function(.x, .y)
    {
        .x %>% mutate(startLatestYear=case_when(...))
    })

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

...