在 for 循环中替换部分字符串时的奇怪行为

odd behavior when substituting parts of a string within a for loop

我正在尝试用来自数据框的信息替换字符串中的一系列数字。

我的字符串来自我使用 readr 包导入的文本文件,如下所示:read_file("Human.txt") 我检查了 class,它是字符。该字符串包含以下信息(我将其命名为 treeString):

"(1,2,((((3),884),(((((519,((516,517),(515,(518,(513,514))))),((((((((458,(457,(455,456))),459),(502,(454,(453,(451,452)))))"

我的数据框 (labels.csv) 最初是因子格式,但我使用以下命令将第二列的格式更改为字符格式:labels[,2] = as.character(labels[,2])。看起来像这样

     v1     v2
1    1      name1
2    2      name2
3    3      name3

我的目标是用数据框中相应的名称(即 V2)替换字符串中的每个数字。这应该导致以下结果:

"(name1,name2,((((name3),884),(((((519,((516,517),(515,(518,(513,514))))),((((((((458,(457,(455,456))),459),(502,(454,(453,(451,452)))))"

这是我用来完成此操作的代码:

for(i in 1:nrow(labels)){
  gsub(as.character(i), labels[i,2], treeString)
}

奇怪的是,如果我 运行 gsub() 命令本身(使用指定的数字 - 例如 2)它会进行替换,但是,当我 运行 它在一个循环,它不会替换数字。

正如 Kumar Manglam 在评论中指出的那样,您忘记将 gsub() 的结果分配回 treeString

还有一点您应该注意:您在问题中指定正则表达式的方式也会将 "(241)" 等模式替换为 "(name24name1)"。为避免这种行为,您应该检查要替换的数字前面是否有逗号或左括号 并且 后有逗号或右括号:

# Option1
for(i in 1:nrow(labelnames)){
   reg_pattern <- paste0("(?<=[(,])(", i, ")(?=[),])")
   treeString  <- gsub(reg_pattern, labelnames$v2[i], treeString, perl=T)
}

另一个更好的选择是放弃 for 循环并一次完成所有操作:

# Option2
reg_pattern <- paste0("(?<=[(,])([1-", nrow(labelnames), "])(?=[),])")
treeString  <- gsub(reg_pattern, "name\1", treeString, perl=T)

# Result
treeString
# "(name1,name2,((((name3),884),(((((519,((516,517),(515,(518,(513,514))))),((((((((458,(457,(455,456))),459),(502,(454,(453,(451,452)))))"

数据

 treeString <- "(1,2,((((3),884),(((((519,((516,517),(515,(518,(513,514))))),((((((((458,(457,(455,456))),459),(502,(454,(453,(451,452)))))"
 labelnames <- structure(list(v1 = 1:3, v2 = c("name1", "name2", "name3")), .Names = c("v1", "v2"), class = "data.frame", row.names = c(NA, -3L))