2016-03-11 6 views
0

У меня есть большой фрейм данных, каждый из которых относится к допуску в больницу. Каждый допуск сопровождается до 20 диагностических кодов в колонках 5 до 24.R - return boolean, если какие-либо строки в векторе появляются в любом из нескольких столбцов

Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20 
data data data data J123 F456 H789  E468 
data data data data T452 NA  NA   NA 

Отдельно, у меня есть вектор (risk_codes) длиной 136, все строки. Эти строки представляют собой коды риска, которые могут быть похожи на коды с усеченными диагностиками (например, J12 будет в порядке, F4 будет в порядке, H798 не будет).

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

До сих пор, я попытался следующим с наибольшим успехом по сравнению с другими попытками:

for (in in 1:length(risk_codes){ 
    df$newcol <- apply(df,1,function(x) sum(grepl(risk_codes[i], x[c(5:24)]))) 
} 

Это хорошо работает для одной строки и заполняет столбец с 0 для каких-либо подобных кодов и 1 по аналогичному код, но тогда все будет перезаписано при проверке второго кода и т. д. по 136 элементам вектора risk_codes.

Любые идеи, пожалуйста? Запуск цикла над каждым кодом risk_code в каждом столбце для каждой строки не представляется возможным.

решение будет выглядеть следующим образом

Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20 newcol 
data data data data J123 F456 H789  E468  1 
data data data data T452 NA  NA   NA  0 

если мои risk_codes содержали J12, F4, T543, например.

+0

Я представил ответ, но теперь, перечитав вопрос, я не уверен, что правильно понял. Вы хотите 1 в новом col, когда есть идеальное совпадение между risk_code и Diag_, или оно равно 1, если есть частичное совпадение. например: J123 и J1 должны иметь 1 в конце? – zelite

+0

Частичные матчи. Если J123 является кодом диагностики в фрейме данных, тогда все коды риска J123, J12 и J1 должны быть возвращены 1. – tfmunkey

ответ

1

Мы хотим применить grepl со всеми risk_codes сразу. Таким образом, мы получаем один результат за строку сразу. Мы можем сделать это с sapply и any.

Таким образом, мы можем опускать цикл и код становится так:

my_df <- read.table(text="Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20 
data data data data J123 F456 H789  E468 
data data data data T452 NA  NA   NA", header=TRUE) 

risk_codes <- c("F456", "XXX") # test codes 

my_df$newcol <- apply(my_df,1,function(x) 
            any(sapply(risk_codes, 
               function(codes) grepl(codes, 
                   x[c(5:24)])))) 

В результате логический вектор.

Если вы все еще хотите использовать 1 и 0 вместо TRUE/FALSE, вам просто нужно закончить:

my_df$new_col <- ifelse(my_df$newcol, 1, 0) 

Результат будет:

> my_df 
    Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20 newcol 
1 data data data data J123 F456 H789 E468  1 
2 data data data data T452 <NA> <NA> <NA>  0 
+0

Спасибо, что идентифицирует множество релевантных записей. Но, например, вернул бы 1 в новый столбец, если бы вектор risk_codes состоял из c («F45», «XXX»)? Функция grepl позволяет, если искать строки поочередно. Мне понадобится «F45», чтобы быть успешным результатом поиска, поскольку код F45 является подмножеством F456 в фрейме данных. – tfmunkey

+0

Я неправильно истолковал вопрос. Теперь я обновил ответ. в основном я заменяю ваш внешний для цикла вызовом sapply внутри функции (x). – zelite

+0

Это работает отлично. Спасибо Вам большое! Ясно, что мне нужно прочесть некоторые заметки о функциях apply и sapply! – tfmunkey