将字符串变量中的给定字符替换为另一个长度相等的字符串变量中的字符

时间:2013-12-17 21:31:24

标签: r regex

我有一个数据框,其中包含两个字符串变量,字符数相同。这些字符串代表学生对某些考试的回答。第一个字符串包含正确回答的每个问题的+号和每个错误项的错误响应。第二个字符串包含所有正确的答案。我想用第二个字符串中的正确答案替换第一个字符串中的所有+符号。可以使用以下代码创建简化的启发式数据集:

df <- data.frame(v1 = c("+AA+B", "D++CC", "A+BAD"), 
                 v2 = c("DBBAD", "BDCAD","CDCCA"), stringsAsFactors = FALSE)

所以df$v1中的+符号需要替换为df$v2中与字符串开头距离相同的字母。有什么想法吗?

5 个答案:

答案 0 :(得分:10)

df$v1df$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中“+”的位置,我们可以方便地利用regmatchesdf$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

enter image description here

答案 3 :(得分:2)

根据Tyler Rinker的回答,概念上它是相同的,但只使用一个lapplyifelse

> 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))