r-插入同一字符串的多个匹配项或将其替换为正在运行的计数器



我有一个RIS(文本(文件,大致如下所示:

mylist <- c("TI  - a", "AU  - b", "ER  -", " ",
"TI  - c", "AU  - d", "ER  -", " ",
"TI  - e", "AU  - f", "ER  -")

我想插入一个运行ID标签如下

mylist_with_ids <- c("TI  - a", "AU  - b", "ID  - 1", "ER  -", " ",
"TI  - c", "AU  - d", "ID  - 2", "ER  -", " ",
"TI  - e", "AU  - f", "ID  - 3", "ER  -")

我最初的方法是编写一个stringr::str_replace循环,在其中我预先生成ID列表。

cc_id_replace <- paste0("ID  - ", 1:3, "nER  -")
for (i in 1:3) {
mylist_with_ids <- str_replace(mylist, "^ER  -", cc_id_replace[i])
}

当然,这不起作用的原因不止一个。还有什么更好的方法呢?(存在许多正则表达式和多个数组问题,但到目前为止我还无法找到答案。(

您可以尝试:

list[list == "ER  -"] <- paste("ID   -", seq_along(which(list == "ER  -")), "nER  -")

我认为这里可以使用游程编码。

(顺便说一句:我不喜欢使用list作为变量名,因为它是一个经常使用的R函数。虽然R很清楚你在引用时的意思,但这可能会被愚弄,并且故障排除会有问题。所以我在这里将其命名为mylist。(

mylist <- c("TI  - a", "AU  - b", "ER  -", " ",
"TI  - c", "AU  - d", "ER  -", " ",
"TI  - e", "AU  - f", "ER  -")
non_ER_runs <- rle(mylist == "ER  -")
non_ER_runs
# Run Length Encoding
#   lengths: int [1:6] 2 1 3 1 3 1
#   values : logi [1:6] FALSE TRUE FALSE TRUE FALSE TRUE

RLE告诉我们每个类别中有多少人。对我们来说,分类是"匹配和不匹配"。这里的$values向量告诉我们,第一个元素不匹配(FALSE(,并且有两个元素。第二批确实匹配(TRUE(,并且是一个长的。等等

inds <- cumsum(non_ER_runs$lengths)
newlist <- mapply(function(a,b) mylist[a:b], c(1, 1+head(inds, n=-1)), inds)
newlist
# [[1]]
# [1] "TI  - a" "AU  - b"
# [[2]]
# [1] "ER  -"
# [[3]]
# [1] " "       "TI  - c" "AU  - d"
# [[4]]
# [1] "ER  -"
# [[5]]
# [1] " "       "TI  - e" "AU  - f"
# [[6]]
# [1] "ER  -"

好吧,我们把每一批都分解成了自己的向量。再次使用rle的返回,我们可以只选择要附加内容的元素:

newlist[ non_ER_runs$values ]
# [[1]]
# [1] "ER  -"
# [[2]]
# [1] "ER  -"
# [[3]]
# [1] "ER  -"
Map(function(vec, vec2) c(vec, vec2),
newlist[ non_ER_runs$values ],
sprintf("ID  - %i", seq_along(newlist[ non_ER_runs$values ])))
# [[1]]
# [1] "ER  -"   "ID  - 1"
# [[2]]
# [1] "ER  -"   "ID  - 2"
# [[3]]
# [1] "ER  -"   "ID  - 3"

现在只需要用新元素替换列表元素,然后unlist就可以了。

newlist[ non_ER_runs$values ] <-
Map(function(vec, vec2) c(vec, vec2),
newlist[ non_ER_runs$values ],
sprintf("ID  - %i", seq_along(newlist[ non_ER_runs$values ])))
newlist <- unlist(newlist)
newlist
#  [1] "TI  - a" "AU  - b" "ER  -"   "ID  - 1" " "      
#  [6] "TI  - c" "AU  - d" "ER  -"   "ID  - 2" " "      
# [11] "TI  - e" "AU  - f" "ER  -"   "ID  - 3"
ris <- c("TI  - a", "AU  - b", "ER  -", " ",
"TI  - c", "AU  - d", "ER  -", " ",
"TI  - e", "AU  - f", "ER  -")

另一个建议是对循环使用dirty;(

1.找到要在前面插入ID元素的位置(这里使用一点正则表达式(。使用pos矢量生成正确数量的ID:

pos <- grep("^ER", ris)
ids <- paste0("ID = ", seq_along(pos))

2.循环所有位置,插入、粘贴、重复(并更新pos(:

for (i in seq_along(pos)) {
ris <- c(ris[1:(pos[i]-1)], ids[i], ris[pos[i]:length(ris)] )
pos <- pos + 1
}
ris

退货:

[1] "TI  - a" "AU  - b" "ID = 1"  "ER  -"  
[5] " "       "TI  - c" "AU  - d" "ID = 2" 
[9] "ER  -"   " "       "TI  - e" "AU  - f"
[13] "ID = 3"  "ER  -"  

最新更新