R: Упрощение длинного оператора ifelse - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь создать новые переменные на основе переменной кода процедуры со значениями 2500+ в наборе медицинских данных, чтобы вытащить антибиотики, их дозу и маршрут. Я мог сделать это с помощью утверждений ifelse, но это занимало много времени, и было трудно найти и исправить ошибки. Есть ли упрощенный способ сделать это? К сожалению, коды не организованы каким-либо логическим способом.

vet <-mutate(vet, ab = ifelse(ProcedureCode=="6160"|ProcedureCode=="2028"|ProcedureCode=="6121"|ProcedureCode=="6130"|ProcedureCode=="6131"|ProcedureCode=="6132"|ProcedureCode=="6133" |ProcedureCode=="6134"|ProcedureCode=="6135"|ProcedureCode=="6136"|ProcedureCode=="6090" |ProcedureCode=="6137"|ProcedureCode=="6138"|ProcedureCode=="6139" |ProcedureCode=="6140" |ProcedureCode=="6510"|ProcedureCode=="680D" |ProcedureCode=="633E"|ProcedureCode=="661J"|ProcedureCode=="627I" |ProcedureCode=="6198"|ProcedureCode=="6199"|ProcedureCode=="6200" |ProcedureCode=="6201" |ProcedureCode=="6202"|ProcedureCode=="622G" |ProcedureCode=="697C" |ProcedureCode=="698C" |ProcedureCode=="6204"|ProcedureCode=="6775"| ProcedureCode=="6229" |ProcedureCode=="6207" |ProcedureCode=="6203" |ProcedureCode=="6205" |ProcedureCode=="6206" |ProcedureCode=="6212" |ProcedureCode=="6213" |ProcedureCode=="6214" |ProcedureCode=="6215" |ProcedureCode=="6216" |ProcedureCode=="6219" |ProcedureCode=="692C" |ProcedureCode=="643C" |ProcedureCode=="601E" |ProcedureCode=="629G" |ProcedureCode=="6234" |ProcedureCode=="6235" |ProcedureCode=="6236" |ProcedureCode=="6237" |ProcedureCode=="6238" |ProcedureCode=="615J" |ProcedureCode=="6242" |ProcedureCode=="6243" |ProcedureCode=="6244" |ProcedureCode=="6245" |ProcedureCode=="1193" |ProcedureCode=="652G" |ProcedureCode=="657G" |ProcedureCode=="697B"|ProcedureCode=="6336" |ProcedureCode=="6337" |ProcedureCode=="6338" |ProcedureCode=="6152" |ProcedureCode=="603C" |ProcedureCode=="655B" |ProcedureCode=="6357" |ProcedureCode=="6358" |ProcedureCode=="6399" |ProcedureCode=="666B" |ProcedureCode=="695D" |ProcedureCode=="699C" |ProcedureCode=="6365" |ProcedureCode=="6366" |ProcedureCode=="696F" |ProcedureCode=="6497" |ProcedureCode=="6613" |ProcedureCode=="6508" |ProcedureCode=="6509" |ProcedureCode=="617I" |ProcedureCode=="6506" |ProcedureCode=="2029" |ProcedureCode=="6538" |ProcedureCode=="671J" |ProcedureCode=="633H" |ProcedureCode=="621G" |ProcedureCode=="680J" |ProcedureCode=="672G" |ProcedureCode=="673G" |ProcedureCode=="6559" |ProcedureCode=="6652" |ProcedureCode=="6593" |ProcedureCode=="651C" |ProcedureCode=="633B" |ProcedureCode=="659E" |ProcedureCode=="676D" |ProcedureCode=="678D" |ProcedureCode=="620B" |ProcedureCode=="6562" |ProcedureCode=="6564" |ProcedureCode=="6585" |ProcedureCode=="6766" |ProcedureCode=="6595" |ProcedureCode=="6607" |ProcedureCode=="6608" |ProcedureCode=="627B" |ProcedureCode=="6653" |ProcedureCode=="6654" |ProcedureCode=="6655"|ProcedureCode=="6732" |ProcedureCode=="6733" |ProcedureCode=="6734"|ProcedureCode=="6735" |ProcedureCode=="6795"|ProcedureCode=="6745" |ProcedureCode=="6746" |ProcedureCode=="6748" |ProcedureCode=="6758" |ProcedureCode=="697E" |ProcedureCode=="6761" |ProcedureCode=="6032" |ProcedureCode=="6747" |ProcedureCode=="6749" |ProcedureCode=="668A" |ProcedureCode=="648A" |ProcedureCode=="649A" |ProcedureCode=="6765" |ProcedureCode=="6768" |ProcedureCode=="6771" |ProcedureCode=="637B"|ProcedureCode=="6894", 1,0))

Проблема также в том, что мне нужно создать несколько групп (например, антибиотик [да / нет], доза, маршрут), и я чувствую, что есть лучший способ, который я пропускаю, который не включает в себя вырезание и вставку переменной и кавычки каждый раз. Существует ли способ создать фрейм данных и использовать ifelse для присвоения любых кодов, которые также находятся в этом фрейме данных, как 1, а других как 0?

Извините, если это дублируется, я относительно плохо знаком с R, и у меня возникают проблемы с поиском словаря для поиска того, что мне нужно. Я огляделся (как Вложенное ifelse утверждение , но не нашел совсем то, что мне нужно.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Базовый подход R для простого варианта:

# my dummy data
df1 <- data.frame("v1" = c(LETTERS[1:10]), "v2" = rep(NA, 10))

# step 1, fill the column with 0 (the else part of your code)
df1[,'v2'] <- 0

# step 2, create a vector containing ids you want to change
change_vec <- c("A", "C", "D", "F")

# step 3, use %in% to index and replace with 1
df1[,'v2'][df1[,'v1'] %in% change_vec] <- 1

В большинстве случаев этого будет достаточно, но следует помнить о рисках использования векторов индексации, содержащих числовые значения.

https://cran.r -project.org / DOC / FAQ / R-faq.html # Почему-doesn_0027t-R-думаю-эти-номера-в-equal_003f

0 голосов
/ 04 мая 2018

Два альтернативных метода, оба используют слияния / объединения. Одним из преимуществ этого подхода является то, что его гораздо проще поддерживать: у вас есть хорошо структурированные и управляемые таблицы процедур вместо (потенциально очень длинных) строк кода с вашим оператором ifelse. Комментарии, предлагающие %in%, также уменьшают эту проблему, хотя вы будете иметь дело с управляемыми векторами вместо управляемых фреймов.

Поддельные данные:

library(dplyr)
library(tidyr)
vet <- data_frame(ProcedureCode = c('6160', '2028', '2029'))
  1. Один кадр на тип процедуры. Это управляемо, но может раздражать, если у вас много разных типов. Повторите left_join для каждого типа.

    abs <- data_frame(ab=TRUE, ProcedureCode = c('6160', '2028'))
    antis <- data_frame(antibiotic=TRUE, ProcedureCode = c('2029'))
    vet %>%
      left_join(abs, by = "ProcedureCode") %>%
      left_join(antis, by = "ProcedureCode") %>%
      mutate_at(vars(ab, antibiotic), funs(!is.na(.)))
    # # A tibble: 3 × 3
    #   ProcedureCode    ab antibiotic
    #           <chr> <lgl>      <lgl>
    # 1          6160  TRUE      FALSE
    # 2          2028  TRUE      FALSE
    # 3          2029 FALSE       TRUE
    

    Использование ab=TRUE (и т. Д.) Позволяет создать столбец для слияния. У строк, которые не совпадают, будет NA, что требует !is.na(.) для преобразования T,NA,T в T,F,T.

    Вместо этого вы можете использовать векторы кодов процедур, например:

    vet %>%
      left_join(data_frame(ab=TRUE, ProcedureCode=vector_of_abs), by = "ProcedureCode") %>%
      ...
    

    Хотя это действительно помогает только в том случае, если у вас уже есть коды в качестве векторов, в противном случае, кажется, что это будет исключительно в зависимости от того, что вам проще поддерживать.

  2. Один кадр со всеми процедурами, требующий только один кадр для типов и один left_join.

    procedures <- tibble::tribble(
      ~ProcedureCode, ~procedure,
      '6160'        , 'ab',
      '2028'        , 'ab',
      '2029'        , 'antibiotic'
    )
    left_join(vet, procedures, by = "ProcedureCode")
    # # A tibble: 3 × 2
    #   ProcedureCode  procedure
    #           <chr>      <chr>
    # 1          6160         ab
    # 2          2028         ab
    # 3          2029 antibiotic
    

    Вы можете оставить его как есть (если есть смысл хранить его таким образом) или spread, чтобы он был похож на другие:

    left_join(vet, procedures, by = "ProcedureCode") %>%
      mutate(ignore=TRUE) %>%
      spread(procedure, ignore) %>%
      mutate_at(vars(ab, antibiotic), funs(!is.na(.)))
    # # A tibble: 3 × 3
    #   ProcedureCode    ab antibiotic
    #           <chr> <lgl>      <lgl>
    # 1          2028  TRUE      FALSE
    # 2          2029 FALSE       TRUE
    # 3          6160  TRUE      FALSE
    

    (Порядок после объединения / слияния здесь другой, но данные остаются теми же.)

(я использовал logical с, достаточно просто конвертировать их в 1 и 0, возможно mutate(ab=1L*ab) или mutate(ab=as.integer(ab)).)

...