[英]How to filter in multiple columns in R if the category starts with specific letter in R?
我有一個龐大的數據集,包含超過 200 萬個 obs 和 100 列。 有 9 列包含 ICD-10 疾病代碼,每列都以不同的字母開頭。
例如:
icd1 <- c("O230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "R433")
icd2 <- c("O230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "Z433")
icd3 <- c("X230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "Z433")
data <- as.data.frame(rbind(icd1, icd2, icd3))
我需要做的是創建一個名為“ICD_Z”的新列,檢查這 9 個 ICD-10 列代碼中的每一個,看看它們是否以字母 Z 開頭,所以如果是這種情況,我創建的列將收到1,否則為 0。但如果所有這 9 列都沒有以字母 O 開頭的 ICD-10 代碼,則它只能接收 1。
所以我的輸出看起來像這樣:
我怎樣才能做到這一點?
您可以使用if_any
和if_all
:
data %>%
mutate(ICD_Z = if_any(V1:V9, ~grepl('^Z', .)) *
if_all(V1:V9, ~!grepl('^O', .)))
V1 V2 V3 V4 V5 V6 V7 V8 V9 ICD_Z
icd1 O230 B540 D990 Y555 E980 J777 P090 Q090 R433 0
icd2 O230 B540 D990 Y555 E980 J777 P090 Q090 Z433 0
icd3 X230 B540 D990 Y555 E980 J777 P090 Q090 Z433 1
編輯:
您可以使用變量來存儲相關列的位置:
nms <- c(1,2,3,5,7,8)
data %>%
mutate(ICD_Z = if_any(all_of(nms), ~grepl('^Z', .)) *
if_all(all_of(nms), ~!grepl('^O', .)))
icd_cols = paste0("V",1:9)
f <- function(v) !any(v=="O") & any(v=="Z")
setDT(data)
set(data, j="icdz", value= apply(data[,..icd_cols],1,\(i) f(substr(i,1,1))))
對於您的大型數據集,您可能會通過這種使用 data.table 的方法加快速度。 在小的 3 行示例中,我非正式地發現這大約快 5 倍。
icd_cols = colnames(data)[c(20,21,37:45)]
icd_cols = paste0("V",1:9)
f <- function(v) !any(v=="O") & any(v=="Z")
setDT(data)
data[, icdz:=(melt(data[,id:=.I],"id",icd_cols)[,f(substr(value,1,1)), by=id]$V1)][id:=NULL]
輸出:
V1 V2 V3 V4 V5 V6 V7 V8 V9 icdz
1: O230 B540 D990 Y555 E980 J777 P090 Q090 R433 FALSE
2: O230 B540 D990 Y555 E980 J777 P090 Q090 Z433 FALSE
3: X230 B540 D990 Y555 E980 J777 P090 Q090 Z433 TRUE
結合rowwise()
和c_across()
非常簡單:
library(dplyr)
icd1 <- c("O230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "R433")
icd2 <- c("O230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "Z433")
icd3 <- c("X230", "B540", "D990", "Y555", "E980", "J777", "P090", "Q090", "Z433")
data <- as.data.frame(rbind(icd1, icd2, icd3))
data %>%
rowwise() %>%
mutate(has_z = any(startsWith(c_across(V1:V9), "Z")),
has_o = any(startsWith(c_across(V1:V9), "O")),
icdz = as.numeric(has_z & !has_o)
) %>%
select(-has_z, -has_o)
#> # A tibble: 3 × 10
#> # Rowwise:
#> V1 V2 V3 V4 V5 V6 V7 V8 V9 icdz
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
#> 1 O230 B540 D990 Y555 E980 J777 P090 Q090 R433 0
#> 2 O230 B540 D990 Y555 E980 J777 P090 Q090 Z433 0
#> 3 X230 B540 D990 Y555 E980 J777 P090 Q090 Z433 1
由reprex 包於 2022-05-25 創建 (v2.0.1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.