Обновление столбцов фрейма данных на основе других столбцов - PullRequest
0 голосов
/ 07 июня 2019

У меня есть фрейм данных, содержащий стадию человека, как показано ниже (это только очень большая выборка):

df = structure(list(DeceasedDate = c(0.283219178082192, 1.12678843226788, 
2.02865296803653, 0.892465753424658, NA, 0.88013698630137, NA
), LastClinicalEventMonthEnd = c(0.244862981988838, 1.03637744165398, 
10.9464611555048, 0.763698598427194, 3.35011412354135, 0.677397228564181, 
3.83687211440893), FirstYStage = c("N/A", "2", "2", "2", "2", 
"2", "3.1"), SecondYStage = c("N/A", "N/A", "2", "N/A", "2", 
"N/A", "3.1"), ThirdYStage = c("N/A", "N/A", "2", "N/A", "2", 
"N/A", "3.1"), FourthYStage = c("N/A", "N/A", "N/A", "N/A", "2", 
"N/A", "3.1"), FifthYStage = c("N/A", "N/A", "N/A", "N/A", "N/A", 
"N/A", "N/A")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-7L))

5 правых столбцов - это сцена человека, но они еще не содержат всей информации. Мне нужно включить информацию в первые два столбца, в которых цифры указаны в годах, следующим образом:

  • если значение в столбце 1 меньше года, FirstYStage должен быть «Умершим», а также все последующие столбцы (человек все еще мертв ...); если значение находится в диапазоне от 1 до 2, значение SecondYStage должно быть «Умершим» и т. д.

  • если значение в столбце 2 меньше года, значение SecondYStage должно быть «EndOfEvents»; если значение находится между 1 и 2, значение SecondYStage должно быть «EndOfEvents» и т. д.

Таким образом, ожидаемый результат в этом случае должен быть:

df_updated = structure(list(DeceasedDate = c(0.283219178082192, 
1.12678843226788, 
2.02865296803653, 0.892465753424658, NA, 0.88013698630137, NA
), LastClinicalEventMonthEnd = c(0.244862981988838, 1.03637744165398, 
10.9464611555048, 0.763698598427194, 3.35011412354135, 0.677397228564181, 
3.83687211440893), FirstYStage = c("Deceased", "2", "2", "Deceased", 
"2", "Deceased", "3.1"), SecondYStage = c("Deceased", "Deceased", 
"2", "Deceased", "2", "Deceased", "3.1"), ThirdYStage = c("Deceased", 
"Deceased", "Deceased", "Deceased", "2", "Deceased", "3.1"), 
FourthYStage = c("Deceased", "Deceased", "Deceased", "Deceased", 
"2", "Deceased", "3.1"), FifthYStage = c("Deceased", "Deceased", 
"Deceased", "Deceased", "LastEvent", "Deceased", "LastEvent"
)), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame"
))

Одним из важных моментов является то, что «Смерти» следует отдавать приоритет, иными словами, если есть столкновение, и с одной стороны, есть число, а «смерть» противоречит ему, мы должны предпочесть смерть.

Как мне сделать это наиболее эффективным способом? В данный момент я делаю «если», но думаю, что это не лучший курс действий

1 Ответ

1 голос
/ 07 июня 2019

Вот что я бы сделал:

  1. Изменение формы с широкого на длинный формат
  2. Вычисление лет по именам столбцов
  3. Выборочное обновление столбца value
  4. Измените форму обратно на широкоформатный

data.table

Поскольку я более свободно говорю в data.table, чем в dplyr, вот подход, реализованный в data.table синтаксис.(Извините, но я добавлю dplyr решение, если позволит время.)

library(data.table)
long <- melt(setDT(df)[, rn := .I], measure.vars = patterns("Stage$"))
long[, year := as.integer(variable)]   # column index     
long[floor(DeceasedDate) < year, value := "Deceased"]
long[is.na(DeceasedDate) & floor(LastClinicalEventMonthEnd) + 1 < year, value := "EndOfEvents"]
dcast(long, rn + DeceasedDate + LastClinicalEventMonthEnd ~ variable)
   rn DeceasedDate LastClinicalEventMonthEnd FirstYStage SecondYStage ThirdYStage FourthYStage FifthYStage
1:  1    0.2832192                 0.2448630    Deceased     Deceased    Deceased     Deceased    Deceased
2:  2    1.1267884                 1.0363774           2     Deceased    Deceased     Deceased    Deceased
3:  3    2.0286530                10.9464612           2            2    Deceased     Deceased    Deceased
4:  4    0.8924658                 0.7636986    Deceased     Deceased    Deceased     Deceased    Deceased
5:  5           NA                 3.3501141           2            2           2            2 EndOfEvents
6:  6    0.8801370                 0.6773972    Deceased     Deceased    Deceased     Deceased    Deceased
7:  7           NA                 3.8368721         3.1          3.1         3.1          3.1 EndOfEvents

dplyr / tidyr

Как и было обещано, здесь также естьdplyr / tidyr реализация того же подхода:

library(tidyr)
library(dplyr)
df %>% 
  mutate(rn = row_number()) %>% 
  gather(key, val, ends_with("Stage"), factor_key = TRUE) %>% 
  mutate(year = as.integer(key)) %>% 
  mutate(val = if_else(!is.na(DeceasedDate) & floor(DeceasedDate) < year, "Deceased", val)) %>% 
  mutate(val = if_else(is.na(DeceasedDate) & floor(LastClinicalEventMonthEnd) + 1 < year, "EndOfEvents", val)) %>% 
  select(-year) %>% 
  spread(key, val) %>% 
  arrange(rn) 
  DeceasedDate LastClinicalEventMonthEnd rn FirstYStage SecondYStage ThirdYStage FourthYStage FifthYStage
1    0.2832192                 0.2448630  1    Deceased     Deceased    Deceased     Deceased    Deceased
2    1.1267884                 1.0363774  2           2     Deceased    Deceased     Deceased    Deceased
3    2.0286530                10.9464612  3           2            2    Deceased     Deceased    Deceased
4    0.8924658                 0.7636986  4    Deceased     Deceased    Deceased     Deceased    Deceased
5           NA                 3.3501141  5           2            2           2            2 EndOfEvents
6    0.8801370                 0.6773972  6    Deceased     Deceased    Deceased     Deceased    Deceased
7           NA                 3.8368721  7         3.1          3.1         3.1          3.1 EndOfEvents

или без создания столбца year:

df %>% 
  mutate(rn = row_number()) %>% 
  gather(key, val, ends_with("Stage"), factor_key = TRUE) %>% 
  mutate(val = if_else(!is.na(DeceasedDate) & floor(DeceasedDate) < as.integer(key), 
                       "Deceased", val)) %>% 
  mutate(val = if_else(is.na(DeceasedDate) & floor(LastClinicalEventMonthEnd) + 1 < as.integer(key), 
                       "EndOfEvents", val)) %>% 
  spread(key, val) %>% 
  arrange(rn) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...