我有一个数据框,其中包含两个字符串变量,字符数相同。这些字符串代表学生对某些考试的回答。第一个字符串包含正确回答的每个问题的+号和每个错误项的错误响应。第二个字符串包含所有正确的答案。我想用第二个字符串中的正确答案替换第一个字符串中的所有+符号。可以使用以下代码创建简化的启发式数据集:
df <- data.frame(v1 = c("+AA+B", "D++CC", "A+BAD"),
v2 = c("DBBAD", "BDCAD","CDCCA"), stringsAsFactors = FALSE)
所以df$v1
中的+符号需要替换为df$v2
中与字符串开头距离相同的字母。有什么想法吗?
答案 0 :(得分:10)
当df$v1
和df$v2
为字符时,我们可以使用
regmatches(df$v1, gregexpr("\\+", df$v1)) <- regmatches(df$v2, gregexpr("\\+", df$v1))
即,
df <- data.frame(v1 = c("+AA+B", "D++CC", "A+BAD"),
v2 = c("DBBAD", "BDCAD", "CDCCA"),
stringsAsFactors = FALSE)
rg <- gregexpr("\\+", df$v1)
regmatches(df$v1, rg) <- regmatches(df$v2, rg)
df
# v1 v2
# 1 DAAAB DBBAD
# 2 DDCCC BDCAD
# 3 ADBAD CDCCA
rg
包含df$v1
中“+”的位置,我们可以方便地利用regmatches
将df$v1
中的匹配替换为df$v2
中的任何内容在相同的位置。
答案 1 :(得分:3)
这个似乎也有效:
mapply(function(x, y) paste0(ifelse(x == "+", y, x), collapse = ""),
strsplit(as.character(df$v1), ""), strsplit(as.character(df$v2), ""))
#[1] "DAAAB" "DDCCC" "ADBAD"
答案 2 :(得分:2)
最有可能的方法是更好的方法,但是这里我将两列放入矩阵然后再查找关键字:
## df<-data.frame(v1 = c("+AA+B", "D++CC", "A+BAD"), v2 = c("DBBAD", "BDCAD","CDCCA"))
dats <- lapply(df, function(x) do.call(rbind, strsplit(as.character(x), "")))
dats[[1]][dats[[1]] == "+"] <- dats[[2]][dats[[1]] == "+"]
apply(dats[[1]], 1, paste, collapse = "")
## [1] "DAAAB" "DDCCC" "ADBAD"
我认为这个可能是一个有趣的基准测试:
Unit: microseconds
expr min lq median uq max neval
Andrea() 296.693 313.953 321.884 328.4155 2443.051 1000
Josh() 300.891 314.420 319.551 326.5500 3748.779 1000
Tyler() 144.148 155.344 159.543 164.2080 2233.593 1000
Jibler() 174.937 188.932 193.597 198.7290 2269.514 1000
Alexis() 154.877 167.007 171.672 175.4040 2342.753 1000
Julius() 394.658 413.317 420.315 429.4120 2549.412 1000
答案 3 :(得分:2)
根据Tyler Rinker的回答,概念上它是相同的,但只使用一个lapply
和ifelse
。
> dats <- lapply(df, function(x) do.call(rbind, strsplit(as.character(x), "")))
> apply(with(dats, ifelse(v1=="+", v2, v1)), 1, paste0, collapse="")
[1] "DAAAB" "DDCCC" "ADBAD"
答案 4 :(得分:1)
df<-data.frame(v1 = c("+AA+B", "D++CC", "A+BAD"),
v2 = c("DBBAD", "BDCAD","CDCCA"),
stringsAsFactors = F)
f <- function(x , y){
xs <- unlist(strsplit(x, split = ""))
ys <- unlist(strsplit(y, split = ""))
paste(ifelse(xs == "+", ys , xs), collapse = "")
}
vapply(df$v1, f , df$v2, FUN.VALUE = character(1))