dplyr :: mutate_at () с внешними переменными и условием их значений - PullRequest
0 голосов
/ 16 июня 2020

У меня есть набор данных в длинном формате (т.е. несколько наблюдений на ID). Каждый ID содержит несколько посещений, во время которых у человека была диагностирована болезнь (в примере с игрушкой я показываю 3, но в моих реальных данных их целых 30), которые закодированы в последовательных столбцах (disease1-disease3). Значение 1 означает, что у них было диагностировано заболевание на момент diagnosis_dt, а значение 0 означает, что у них его не было. Для каждого ID мне интересно суммировать, были ли у них какие-либо заболевания во всех посещениях, где diagnosis_dt попадает в между start_dt и end_dt. Некоторые ID не содержат диагностической информации и, следовательно, кодируются как NA в соответствующих столбцах. Я все еще хотел бы сохранить эту информацию.

Игрушечный пример моего набора данных ниже:

library(dplyr)
library(data.table)

ex_dat <- data.frame(ID = c(rep("a",3),
                  rep("b",4),
                  rep("c",5)),
                  start_dt = as.Date(c(rep("2009-01-01",3),
                                       rep("2009-04-01",4),
                                       rep("2009-02-01",5))),
                  end_dt = as.Date(c(rep("2010-12-31",3),
                                rep("2011-03-31",4),
                                rep("2011-01-31",5))),
           diagnosis_dt = c(as.Date(c("2011-01-03","2010-11-01","2009-12-01")),
                            as.Date(c("2011-04-03","2010-11-01","2009-12-01","2011-12-01")),
                            rep(NA,5)),
           disease1 = c(c(1,0,0),
                        c(1,1,0,1),
                        rep(NA,5)),
           disease2 = c(c(1,1,0),
                        c(0,0,0,1),
                        rep(NA,5)),
           disease3 = c(c(0,0,0),
                        c(0,0,1,0),
                        rep(NA,5))
           )

Желаемый результат:

  ID disease1 disease2 disease3
1  a        0        1        0
2  b        1        0        1
3  c       NA       NA       NA

I ' я пробовал это уже несколько часов, и моя последняя попытка:

out <- ex_dat %>% group_by(ID) %>%
           mutate_at(vars(disease1:disease3),
                     function(x) ifelse(!is.na(.$diagnosis_dt) & 
                                          between(.$diagnosis_dt,.$start_dt,.$end_dt) & 
                                          sum(x)>0,
                                        1,0)) %>%
           slice(1) %>%
           select(ID,disease1:disease3)

Ответы [ 2 ]

2 голосов
/ 16 июня 2020

Вот решение tidyverse, использующее filter для удаления строк, которые не соответствуют желаемому условию, а затем complete для заполнения отсутствующих групп с помощью NA.

library(tidyverse)

ex_dat %>%
  #Group by ID 
  group_by(ID) %>%
  # Stay with the rows for which diagnosis_dt is between start_dt and end_dt
  filter(diagnosis_dt >= start_dt & diagnosis_dt <= end_dt ) %>%
  # summarize all variables that start with disease by taking its max value
  summarize_at(vars(starts_with("disease")), max) %>%
  # Complete the missing IDs, those that only had NA or did not meet the criteria in  
  # the filter
  complete(ID)

# A tibble: 3 x 4
#  ID    disease1 disease2 disease3
# <fct>    <dbl>    <dbl>    <dbl>
# 1 a            0        1        0
# 2 b            1        0        1
# 3 c           NA       NA       NA
1 голос
/ 16 июня 2020

Вот подход с функциональностью dplyr across (версия> = 1.0.0):

library(dplyr)
ex_dat %>%
  group_by(ID) %>%
  summarize(across(-one_of(c("start_dt","end_dt","diagnosis_dt")),
                   ~ if_else(any(diagnosis_dt > start_dt & diagnosis_dt < end_dt & .),
                             1, 0)))
## A tibble: 3 x 4
#  ID    disease1 disease2 disease3
#  <fct>    <dbl>    <dbl>    <dbl>
#1 a            0        1        0
#2 b            1        0        1
#3 c           NA       NA       NA

Обратите внимание, что использование оператора & в целочисленном столбце . преобразуется в логично. Я использую глагол -one_of tidyselect, потому что тогда нам даже не нужно знать, сколько болезней существует. Столбцы, которые активно изменяются group_by, автоматически исключаются.

Ваша версия не работает, потому что 1) вам нужно суммировать, а не изменять, и 2) внутри вызова функции . относится к столбец, над которым работаете, а не данные из трубопроводов. Вместо этого вам нужно получить доступ к этим столбцам без $ из вызывающей среды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...