#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