在R中的2组数据中查找匹配的字符串
Finding matching character strings in 2 sets of data in R
我有2个数据集;一个包含患者信息,另一个是医疗代码列表
patient <- data.table(ID = rep(1:5, each = 3),
codes = c("13H42", "1B1U", "Eu410", "Je450", "Fg65", "Eu411", "Eu402", "B110", "Eu410", "Eu50",
"1B1U", "Eu513", "Eu531", "Eu411", "Eu608")
)
code <- data.table(codes = c("BG689", "13H42", "BG689", "Ju34K", "Eu402", "Eu410", "Eu50", "JE541", "1B1U",
"Eu411", "Fg605", "GT6TU"),
term = c(NA))
code$term
有值,但在本例中被省略了。
我想要的是 patient
中的指示器列,如果 code
中的代码出现在 patient$codes
中,则显示 1。
patient
ID codes mh
1: 1 13H42 TRUE
2: 1 1B1U TRUE
3: 1 Eu410 TRUE
4: 2 Je450 FALSE
5: 2 Fg65 FALSE
6: 2 Eu411 TRUE
7: 3 Eu402 TRUE
8: 3 B110 FALSE
9: 3 Eu410 TRUE
10: 4 Eu50 TRUE
11: 4 1B1U TRUE
12: 4 Eu513 FALSE
13: 5 Eu531 FALSE
14: 5 Eu411 TRUE
15: 5 Eu608 FALSE
我的解决方案是使用 grepl:
patient$mh <- mapply(grepl, pattern=code$codes, x=patient$codes)
但是这不起作用,因为 code
长度不一样,我收到了警告
Warning message:
In mapply(grepl, pattern = code$codes, x = patient$codes) :
longer argument not a multiple of length of shorter
任何精确匹配的解决方案?
编辑:其他人发布了更好的答案。我自己喜欢@moto 的 %in%。更简洁,更高效。坚持那些:)
这应该可以做到。我使用了一个 for 循环,所以你可能会想出一些更有效的方法。我还将循环分成几行,而不是将其压缩成一行。这只是为了让您看到发生了什么:
for( row in 1:nrow(patient) ) {
codecheck <- patient$codes[row]
output <- ifelse( sum( grepl( codecheck, code$codes ) ) > 0L, 1, 0 )
patient$new[row] <- output
}
所以这只是一个一个地检查患者列表,使用 grepl 检查匹配,然后将结果(1 表示匹配,0 表示不匹配)作为新列放回患者框架中。
这就是你想要的吗?
你可以这样做:
patient[,mh := codes %in% code$codes]
更新:
正如 Pasqui 正确建议的那样,为了获得 0 和 1,
你可以进一步做:
patient[,mh := as.numeric(mh)]
我有2个数据集;一个包含患者信息,另一个是医疗代码列表
patient <- data.table(ID = rep(1:5, each = 3),
codes = c("13H42", "1B1U", "Eu410", "Je450", "Fg65", "Eu411", "Eu402", "B110", "Eu410", "Eu50",
"1B1U", "Eu513", "Eu531", "Eu411", "Eu608")
)
code <- data.table(codes = c("BG689", "13H42", "BG689", "Ju34K", "Eu402", "Eu410", "Eu50", "JE541", "1B1U",
"Eu411", "Fg605", "GT6TU"),
term = c(NA))
code$term
有值,但在本例中被省略了。
我想要的是 patient
中的指示器列,如果 code
中的代码出现在 patient$codes
中,则显示 1。
patient
ID codes mh
1: 1 13H42 TRUE
2: 1 1B1U TRUE
3: 1 Eu410 TRUE
4: 2 Je450 FALSE
5: 2 Fg65 FALSE
6: 2 Eu411 TRUE
7: 3 Eu402 TRUE
8: 3 B110 FALSE
9: 3 Eu410 TRUE
10: 4 Eu50 TRUE
11: 4 1B1U TRUE
12: 4 Eu513 FALSE
13: 5 Eu531 FALSE
14: 5 Eu411 TRUE
15: 5 Eu608 FALSE
我的解决方案是使用 grepl:
patient$mh <- mapply(grepl, pattern=code$codes, x=patient$codes)
但是这不起作用,因为 code
长度不一样,我收到了警告
Warning message:
In mapply(grepl, pattern = code$codes, x = patient$codes) :
longer argument not a multiple of length of shorter
任何精确匹配的解决方案?
编辑:其他人发布了更好的答案。我自己喜欢@moto 的 %in%。更简洁,更高效。坚持那些:)
这应该可以做到。我使用了一个 for 循环,所以你可能会想出一些更有效的方法。我还将循环分成几行,而不是将其压缩成一行。这只是为了让您看到发生了什么:
for( row in 1:nrow(patient) ) {
codecheck <- patient$codes[row]
output <- ifelse( sum( grepl( codecheck, code$codes ) ) > 0L, 1, 0 )
patient$new[row] <- output
}
所以这只是一个一个地检查患者列表,使用 grepl 检查匹配,然后将结果(1 表示匹配,0 表示不匹配)作为新列放回患者框架中。
这就是你想要的吗?
你可以这样做:
patient[,mh := codes %in% code$codes]
更新:
正如 Pasqui 正确建议的那样,为了获得 0 和 1,
你可以进一步做:
patient[,mh := as.numeric(mh)]