R: создать один новый столбец на основе совпадающей строки в нескольких других столбцах - PullRequest
0 голосов
/ 20 января 2019

У меня есть набор данных с очень большим количеством строковых столбцовых переменных, представляющих процедурные коды.Есть еще один столбец переменных, который представляет формат кодирования (некоторые из них ICD9, некоторые другие более загадочные форматы).Каждое наблюдение - это пациент.Мне нужно:

  1. Поиск по каждому имени переменной с определенным префиксом
  2. Убедитесь, что используемый код является кодом ICD9 (представленным «02»).
  3. Найдите, какой из этих кодов соответствует первым 3 символам конкретной строки
  4. Создайте новую переменную столбца = 1, если любая из переменных начинается с этих трех символов, и = 0, если ни одна не соответствует

Слишком много переменных для тривиального создания списка каждой из них вручную через c ("cd1", "cd2", ...), и мне потенциально нужно делать это много разпоэтому я хотел бы сделать это как можно более общим решением.

Вот упрощенный пример, где строки, которые мне нужно найти, начинаются с "231":

ID   cd1    type1  cd2    type2  cd3    type3  cd4    type4
1    "231"  "02"   "219"  "02"   "1321" "02"  "2314"  "02"
2    "222"  "02"  
3    "123"  "142"   
4    "145"  "02"   "521"  "02"   "2313" "02"   
5    "231"  "01"

Я хотел бы получить следующее:

ID   cd1    type1  cd2    type2  cd3    type3  cd4    type4   flag_var
1    "231"  "02"   "219"  "02"   "1321" "02"  "2314"  "02"    1
2    "222"  "02"                                              0
3    "123"  "142"                                             0
4    "145"  "02"   "521"  "02"   "2313" "02"                  1
5    "231"  "01"                                              0

(ID # 5 установлен в 0, потому что, хотя код cd1 равен «231», переменная type1 равна «01» и, следовательно, не в правильном кодированииformat ")

Я несколько преуспел в этомg mutate и case_when:

df <- df %>%
  mutate(flag_var = case_when(
    startsWith(cd1, "231") ~ 1, 
    startsWith(cd2, "231") ~ 1, 
    startsWith(cd3, "231") ~ 1, 
    startsWith(cd4, "231") ~ 1, 
    TRUE ~ 0))

Как я уже говорил, фактический набор данных имеет слишком много переменных и потенциальных поисков, чтобы иметь смысл жестко закодировать его описанным выше способом.Я думаю, что должен быть хороший способ сделать это, используя mutate_at или другую функцию dplyr, но я не смог понять это.

Мне удалось использовать следующий код, чтобы получить набор новых переменных, равный 1 или 0, но не одну переменную.Затем я могу использовать rowSums для суммирования по всем столбцам и проверить, является ли это значение ненулевым.Но это уродливо и кропотливо:

df <- df %>% mutate_at(vars(starts_with("cd")),
                       funs(testvar = ifelse(startsWith(., "231"), 1, 0)))
test_names = df %>% select(ends_with("_testvar")) %>% names()
df <- df %>% mutate(flag_var = (rowSums(.[test_names]) == 1))
df <- df %>% select(-ends_with("_testvar"))

У кого-нибудь есть более простые идеи?Большое спасибо!

РЕДАКТИРОВАТЬ: я понял, что я также должен включить переменные типа кодирования.Исходные таблицы данных образцов были отредактированы, чтобы отразить это.

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Вот еще одно решение:

df$flag_var <- 1*(rowSums(substring(as.matrix(df[, 2:ncol(df)]), 1, 3) == '231') > 0)

#   ID cd1 cd2  cd3  cd4 flag_var
# 1  1 231 219 1321 2314        1
# 2  2 222                      0
# 3  3 123 142                  0
# 4  4 145 521 2313  122        1

В обновленном примере, поскольку столбцы cd и столбцы type спарены, должен работать следующий код:

cd.cols <- grepl('^cd', colnames(df))
type.cols <- grepl('^type', colnames(df))

flag <- substring(as.matrix(df[,cd.cols]), 1, 3) == '231' & df[,type.cols] == '02'
df$flag_var <- 1 * (rowSums(flag) > 0)

# > df
#   ID cd1 type1 cd2 type2  cd3 type3  cd4 type4 flag_var
# 1  1 231    02 219    02 1321    02 2314    02        1
# 2  2 222    02                                        0
# 3  3 123   142                                        0
# 4  4 145    02 521    02 2313    02                   1
# 5  5 231    01                                        0
0 голосов
/ 20 января 2019

Мы могли бы перебрать столбцы и выполнить частичное совпадение с grepl, Reduce list из vector с одним логическим vector и привести значения к двоичному

df$flag_var <- +(Reduce(`|`, lapply(df[-1], grepl, pattern = '^231')))

данные

df <- structure(list(ID = c("1", "2", "3", "4"), cd1 = c("231", "222", 
"123", "145"), cd2 = c("219", "", "142", "521"), cd3 = c("1321", 
 "", "", "2313"), cd4 = c("2314", "", "", "122")), row.names = c(NA, 
 -4L), class = "data.frame")
0 голосов
/ 20 января 2019

Это может ответить на вопрос или вам нужно 0-1 в качестве значений строки?

library(tidyverse)

dat <- tribble(~ID,   ~cd1,      ~cd2,      ~cd3,      ~cd4,
        1,    "231",    "219",    "1321",   "2314",
        2,    "222",    ""      , ""    ,   "",
        3,    "123",    "142",    ""    ,   "",
        4,    "145",    "521",    "2313",   "122")

dat %>% 
  gather("cd_type", "code", 2:5) %>% 
  mutate(flag_var = case_when(
    startsWith(code, "231") ~ 1,
    TRUE ~ 0
  ))
#> # A tibble: 16 x 4
#>       ID cd_type code  flag_var
#>    <dbl> <chr>   <chr>    <dbl>
#>  1     1 cd1     231          1
#>  2     2 cd1     222          0
#>  3     3 cd1     123          0
#>  4     4 cd1     145          0
#>  5     1 cd2     219          0
#>  6     2 cd2     ""           0
#>  7     3 cd2     142          0
#>  8     4 cd2     521          0
#>  9     1 cd3     1321         0
#> 10     2 cd3     ""           0
#> 11     3 cd3     ""           0
#> 12     4 cd3     2313         1
#> 13     1 cd4     2314         1
#> 14     2 cd4     ""           0
#> 15     3 cd4     ""           0
#> 16     4 cd4     122          0

Или сделайте это, чтобы вернуться в исходный широкоформатный формат

dat %>% 
  gather("cd_type", "code", 2:5) %>% 
  mutate(flag_var = case_when(
    startsWith(code, "231") ~ 1,
    TRUE ~ 0
  )) %>% 
  spread(cd_type, code) %>% 
  select(ID, cd1:cd4, flag_var)
#> # A tibble: 6 x 6
#>      ID cd1   cd2   cd3   cd4   flag_var
#>   <dbl> <chr> <chr> <chr> <chr>    <dbl>
#> 1     1 <NA>  219   1321  <NA>         0
#> 2     1 231   <NA>  <NA>  2314         1
#> 3     2 222   ""    ""    ""           0
#> 4     3 123   142   ""    ""           0
#> 5     4 145   521   <NA>  122          0
#> 6     4 <NA>  <NA>  2313  <NA>         1

Создано в 2019-01-19 пакетом Представить (v0.2.1)

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