簡體   English   中英

如果類別以 R 中的特定字母開頭,如何過濾 R 中的多個列?

[英]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_anyif_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 倍。

  1. 確定 9 個 ICD 列的列表; 我在這里使用了一個簡單的構造來獲取 V1:V9,但您可以使用icd_cols = colnames(data)[c(20,21,37:45)]
  2. 創建一個評估首字母向量的小函數
  3. 將原始幀設置為 data.table
  4. 通過id融化並應用函數,並將結果分配給原始幀
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM