выберите строки, которые соответствуют условию в нескольких столбцах

#r #conditional-statements

#r #условные операторы

Вопрос:

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

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

 id dx_1 dx_2 dx_3 dx_n
1  401  
2  2500 4011
3  18524
  

Я бы хотел, чтобы идентификаторы 1 и 2. Я что-то пробовал, но получаю сообщение об ошибке, и оно работает медленно. Любые указания или предложения приветствуются. Если что-то неясно, я постараюсь предоставить больше информации.

 final_DB[apply(grep(paste("^", i, sep=""), final_DB[,10:29]), 1, any),]
  

i соответствуют номеру, который я хочу, поэтому в этом случае i <- 401 столбцы с 10 по 29 — это все столбцы, в которых может быть этот код.

Ответ №1:

Одним из вариантов было filter_at бы выбрать интересующие столбцы, проверить, имеет ли какая-либо из переменных значение substr , 401 в начале, чтобы отфильтровать строки

 library(dplyr)
df1 %>%
    filter_at(vars(starts_with("dx")), any_vars(substr(., 1, 3) == '401'))
#    id dx_1 dx_2 dx_3 dx_n
#1  1  401   NA   NA   NA
#2  2 2500 4011   NA   NA
  

Или, используя base R , перебирайте интересующие столбцы (в данном случае все столбцы, кроме первого), используйте grepl и проверяйте, есть ли pattern там «^ 401» или нет — возвращает a list логических vector s, которые мы Reduce приводим к одному логическому vector с | , используйте это для подмножества строк данных

 df1[Reduce(`|`, lapply(df1[-1], grepl, pattern = "^401")), ]
  

Что касается проблемы в сообщении OP

 final_DB[apply(grep(paste("^", i, sep=""), final_DB[,10:29]), 1, any),]
  

Здесь grep применяется к data.frame вместо a vector и grep работает дальше vector/matrices . Чтобы исправить это, мы перебираем строки (хотя это было бы неэффективно — просто исправить код)

 i1 <- apply(final_DB[, 10:29], 1, function(x) any(grepl(paste("^", i, sep=""), x)))
  

данные

 df1 <- structure(list(id = 1:3, dx_1 = c(401L, 2500L, 18524L), dx_2 = c(NA, 
 4011L, NA), dx_3 = c(NA, NA, NA), dx_n = c(NA, NA, NA)), 
 class = "data.frame", row.names = c(NA, -3L))
  

Комментарии:

1. Спасибо! Мне особенно нравится использование filter_at , поскольку я начинаю использовать tidyverse библиотеку.

Ответ №2:

Я буду использовать mtcars для демонстрации один метод (в базе R). (Кстати: мне не ясно, что ваши данные — это character или numeric , но это не имеет значения: grep* функции с радостью преобразуются в character , чтобы находить вещи, как в grepl("^123", 122:124) … хотя регулярное выражение с плавающей запятой, очевидно, следует воспринимать с осторожностью.)

Допустим, нам нужна каждая строка, где что-то начинается с 20 по 25:

 mt <- mtcars[1:10, 1:7]
sapply(mt, grepl, pattern = "^2[0-5]")
#         mpg   cyl  disp    hp  drat    wt  qsec
#  [1,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
#  [2,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
#  [3,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
#  [4,]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE
#  [5,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#  [6,] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE
#  [7,] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
#  [8,]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE
#  [9,]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE
# [10,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
  

Чтобы выделить, что это такое:

 mt
#                    mpg   cyl    disp    hp   drat      wt    qsec
# Mazda RX4        *21.0*    6   160.0   110   3.90   2.620   16.46
# Mazda RX4 Wag    *21.0*    6   160.0   110   3.90   2.875   17.02
# Datsun 710       *22.8*    4   108.0    93   3.85   2.320   18.61
# Hornet 4 Drive   *21.4*    6  *258.0*  110   3.08   3.215   19.44
# Hornet Sportabout 18.7     8   360.0   175   3.15   3.440   17.02
# Valiant           18.1     6  *225.0*  105   2.76   3.460  *20.22*
# Duster 360        14.3     8   360.0  *245*  3.21   3.570   15.84
# Merc 240D        *24.4*    4   146.7    62   3.69   3.190  *20.00*
# Merc 230         *22.8*    4   140.8    95   3.92   3.150  *22.90*
# Merc 280          19.2     6   167.6   123   3.92   3.440   18.30
  

Теперь, чтобы использовать это:

 mt[ rowSums(sapply(mt, grepl, pattern = "^2[0-5]")) > 0, ]
#                 mpg cyl  disp  hp drat    wt  qsec
# Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46
# Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02
# Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61
# Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44
# Valiant        18.1   6 225.0 105 2.76 3.460 20.22
# Duster 360     14.3   8 360.0 245 3.21 3.570 15.84
# Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00
# Merc 230       22.8   4 140.8  95 3.92 3.150 22.90
  

Если вам нужно проверить только определенный набор столбцов, добавьте выделение столбца mt в sapply :

 mt[ rowSums(sapply(mt[,c(1,4,7)], grepl, pattern = "^2[0-5]")) > 0, ]
#                 mpg cyl  disp  hp drat    wt  qsec
# Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46
# Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02
# Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61
# Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44
# Valiant        18.1   6 225.0 105 2.76 3.460 20.22
# Duster 360     14.3   8 360.0 245 3.21 3.570 15.84
# Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00
# Merc 230       22.8   4 140.8  95 3.92 3.150 22.90