R - return 布尔值,如果向量中的任何字符串出现在多个列中的任何一个
R - return boolean if any strings in a vector appear in any of several columns
我有一个很大的数据框,每一行代表一次入院。每次入院在第 5 至 24 列中附有最多 20 个诊断代码。
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20
data data data data J123 F456 H789 E468
data data data data T452 NA NA NA
另外,我有一个长度为 136 的向量 (risk_codes),所有字符串。这些字符串是类似于截断诊断代码的风险代码(例如 J12 可以,F4 可以,H798 不行)。
如果 any 风险代码与任何诊断代码相似,我希望向数据框添加一列 returns 1。我不需要知道有多少,只要至少有一个就行了。
到目前为止,与其他尝试相比,我尝试了以下最成功的方法:
for (in in 1:length(risk_codes){
df$newcol <- apply(df,1,function(x) sum(grepl(risk_codes[i], x[c(5:24)])))
}
它适用于单个字符串,并用 0 表示没有相似的代码,用 1 表示相似的代码,但是当检查第二个代码时,所有内容都会被覆盖,依此类推 136 个元素risk_codes 向量。
有什么想法吗? 运行 对每一行的每一列中的每个 risk_code 进行循环是不可行的。
解决方案如下所示
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20 newcol
data data data data J123 F456 H789 E468 1
data data data data T452 NA NA NA 0
如果我的 risk_codes 包含 J12、F4、T543,例如。
我们想一次性应用所有 risk_codes 的 grepl。所以我们每行一次得到一个结果。我们可以用 sapply
和 any
.
来做到这一点
所以,我们可以去掉 for 循环,你的代码会变成这样:
my_df <- read.table(text="Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20
data data data data J123 F456 H789 E468
data data data data T452 NA NA NA", header=TRUE)
risk_codes <- c("F456", "XXX") # test codes
my_df$newcol <- apply(my_df,1,function(x)
any(sapply(risk_codes,
function(codes) grepl(codes,
x[c(5:24)]))))
结果是一个逻辑向量。
如果您仍想使用 1 和 0 而不是 TRUE/FALSE,您只需要完成:
my_df$new_col <- ifelse(my_df$newcol, 1, 0)
结果将是:
> my_df
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20 newcol
1 data data data data J123 F456 H789 E468 1
2 data data data data T452 <NA> <NA> <NA> 0
我有一个很大的数据框,每一行代表一次入院。每次入院在第 5 至 24 列中附有最多 20 个诊断代码。
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20
data data data data J123 F456 H789 E468
data data data data T452 NA NA NA
另外,我有一个长度为 136 的向量 (risk_codes),所有字符串。这些字符串是类似于截断诊断代码的风险代码(例如 J12 可以,F4 可以,H798 不行)。
如果 any 风险代码与任何诊断代码相似,我希望向数据框添加一列 returns 1。我不需要知道有多少,只要至少有一个就行了。
到目前为止,与其他尝试相比,我尝试了以下最成功的方法:
for (in in 1:length(risk_codes){
df$newcol <- apply(df,1,function(x) sum(grepl(risk_codes[i], x[c(5:24)])))
}
它适用于单个字符串,并用 0 表示没有相似的代码,用 1 表示相似的代码,但是当检查第二个代码时,所有内容都会被覆盖,依此类推 136 个元素risk_codes 向量。
有什么想法吗? 运行 对每一行的每一列中的每个 risk_code 进行循环是不可行的。
解决方案如下所示
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 ... Diag_20 newcol
data data data data J123 F456 H789 E468 1
data data data data T452 NA NA NA 0
如果我的 risk_codes 包含 J12、F4、T543,例如。
我们想一次性应用所有 risk_codes 的 grepl。所以我们每行一次得到一个结果。我们可以用 sapply
和 any
.
所以,我们可以去掉 for 循环,你的代码会变成这样:
my_df <- read.table(text="Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20
data data data data J123 F456 H789 E468
data data data data T452 NA NA NA", header=TRUE)
risk_codes <- c("F456", "XXX") # test codes
my_df$newcol <- apply(my_df,1,function(x)
any(sapply(risk_codes,
function(codes) grepl(codes,
x[c(5:24)]))))
结果是一个逻辑向量。
如果您仍想使用 1 和 0 而不是 TRUE/FALSE,您只需要完成:
my_df$new_col <- ifelse(my_df$newcol, 1, 0)
结果将是:
> my_df
Col1 Col2 Col3 Col4 Diag_1 Diag_2 Diag_3 Diag_20 newcol
1 data data data data J123 F456 H789 E468 1
2 data data data data T452 <NA> <NA> <NA> 0