使用数据框中的不同值替换字符串的某些相等元素
Replacement of some equal elements of a string using different values in a data frame
我想用 'a' 列中的每个元素替换 'test' 数据框的 'b' 列中的每个 'COL' 单词,并将结果放入在其他列中,但保留列 'b'.
的字符串的顺序和结构
test <- data.frame(a = c("COL167", "COL2010;COL2012"),
b = c("COL;MO, K", "P;COL, NY, S, COL"))
我尝试了以下方法,但不是我需要的结果:
for(i in 1:length(test$a)){
test$c[i] <- gsub(pattern = "COL", x = test$b[i], replacement = test$a[i])
}
> test
a b c
1 COL167 COL;MO, K COL167;MO, K
2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010;COL2012, NY, S, COL2010;COL2012
我希望得到以下结果:
a b c
1 COL167 COL;MO, K COL167;MO, K
2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2012
基于您已经完成的工作,我认为这可行,但请注意,如果您的 table 很大,您可能会遇到一些性能问题。另请注意,这假定要替换的值的大小等于用于替换的值。
由于gsub
不允许向量化替换(用替换的第一个值替换所有匹配的实例),这里我将字符串和替换都转换为向量,所以我可以单独替换每个匹配的子字符串.
test <- data.frame(a = c("COL167", "COL2010;COL2012"),
b = c("COL;MO, K", "P;COL, NY, S, COL"))
re = function(string, replacement){
gsub('COL', replacement, string)
}
for(i in 1:nrow(test)){
#splitting values of column a into vector, this is required for replacement
replacement = unlist(strsplit(test$a[i], ';'))
#split values of column b into vecto, this is required for replacement
b_value = unlist(strsplit(test$b[i], ' '))
#select those which have 'COL' substring
ind_to_replace = which(grepl('COL', b_value))
#replace matched values
result = mapply(re, b_value[ind_to_replace], replacement)
#replace the column b value with new string
b_value[ind_to_replace] = result
#join the string
test$results[i] = paste(b_value, collapse = ' ')
}
test
#> a b results
#> 1 COL167 COL;MO, K COL167;MO, K
#> 2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2012
由 reprex package (v0.3.0)
于 2020-09-05 创建
我将使用 dplyr
的 rowwise
函数提出一个解决方案。
虽然 gsub
确实没有矢量化,但同名包中的 mgsub
函数是矢量化的。我的方法是每一行:
将 b 列中的所有 COL 实例转换为向量
从 a 列的所有 COL+ 条目创建一个向量
使用向量 2 替换 b 中 COL 的旧值。 mutate
使用结果创建一个新列。
library(mgsub)
library(stringr)
library(dplyr)
test %>%
rowwise() %>%
mutate(new_col =
unlist((mgsub(b,
unlist(str_extract_all(b,"COL")),
unlist(str_extract_all(a,"COL.*?\b")))
)))
# A tibble: 2 x 3
# Rowwise:
a b new_col
<chr> <chr> <chr>
1 COL167 COL;MO, K COL167;MO, K
2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2010
mgsub
有 3 个参数。您正在处理的字符串、要在该字符串中替换的表达式以及要用作替换的表达式。这个包允许你有多个模式来替换和被替换——两者都可以显示为矢量。
我将此函数应用于每一行 - 首先我将 b 列指定为感兴趣的字符串。其次,b 列中的所有 COL
都是我们要替换的内容,我使用 stringr::str_extract_all
将其制作成一个向量。我提取了 COL
的所有实例,然后我们必须取消列出此输出,因为 str_extract_all
returns 是一个列表。第三,我使用相同的过程从 a 列中提取 COL+
条目。总之,我们使用 a 列中的条目替换 b 列中感兴趣的字符。
"COL.*?\b"
选择字母 COL
后跟尽可能少的字符,然后到达单词边界,这样我们就可以将 a 列中的条目变成多个项目(COL2010、COL2012 等)。
我们必须取消列出变异的行(即第一个“取消列出”),因为 dplyr
输出 list-column.
我想用 'a' 列中的每个元素替换 'test' 数据框的 'b' 列中的每个 'COL' 单词,并将结果放入在其他列中,但保留列 'b'.
的字符串的顺序和结构test <- data.frame(a = c("COL167", "COL2010;COL2012"),
b = c("COL;MO, K", "P;COL, NY, S, COL"))
我尝试了以下方法,但不是我需要的结果:
for(i in 1:length(test$a)){
test$c[i] <- gsub(pattern = "COL", x = test$b[i], replacement = test$a[i])
}
> test
a b c
1 COL167 COL;MO, K COL167;MO, K
2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010;COL2012, NY, S, COL2010;COL2012
我希望得到以下结果:
a b c
1 COL167 COL;MO, K COL167;MO, K
2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2012
基于您已经完成的工作,我认为这可行,但请注意,如果您的 table 很大,您可能会遇到一些性能问题。另请注意,这假定要替换的值的大小等于用于替换的值。
由于gsub
不允许向量化替换(用替换的第一个值替换所有匹配的实例),这里我将字符串和替换都转换为向量,所以我可以单独替换每个匹配的子字符串.
test <- data.frame(a = c("COL167", "COL2010;COL2012"),
b = c("COL;MO, K", "P;COL, NY, S, COL"))
re = function(string, replacement){
gsub('COL', replacement, string)
}
for(i in 1:nrow(test)){
#splitting values of column a into vector, this is required for replacement
replacement = unlist(strsplit(test$a[i], ';'))
#split values of column b into vecto, this is required for replacement
b_value = unlist(strsplit(test$b[i], ' '))
#select those which have 'COL' substring
ind_to_replace = which(grepl('COL', b_value))
#replace matched values
result = mapply(re, b_value[ind_to_replace], replacement)
#replace the column b value with new string
b_value[ind_to_replace] = result
#join the string
test$results[i] = paste(b_value, collapse = ' ')
}
test
#> a b results
#> 1 COL167 COL;MO, K COL167;MO, K
#> 2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2012
由 reprex package (v0.3.0)
于 2020-09-05 创建我将使用 dplyr
的 rowwise
函数提出一个解决方案。
虽然 gsub
确实没有矢量化,但同名包中的 mgsub
函数是矢量化的。我的方法是每一行:
将 b 列中的所有 COL 实例转换为向量
从 a 列的所有 COL+ 条目创建一个向量
使用向量 2 替换 b 中 COL 的旧值。
mutate
使用结果创建一个新列。library(mgsub) library(stringr) library(dplyr) test %>% rowwise() %>% mutate(new_col = unlist((mgsub(b, unlist(str_extract_all(b,"COL")), unlist(str_extract_all(a,"COL.*?\b"))) ))) # A tibble: 2 x 3 # Rowwise: a b new_col <chr> <chr> <chr> 1 COL167 COL;MO, K COL167;MO, K 2 COL2010;COL2012 P;COL, NY, S, COL P;COL2010, NY, S, COL2010
mgsub
有 3 个参数。您正在处理的字符串、要在该字符串中替换的表达式以及要用作替换的表达式。这个包允许你有多个模式来替换和被替换——两者都可以显示为矢量。
我将此函数应用于每一行 - 首先我将 b 列指定为感兴趣的字符串。其次,b 列中的所有 COL
都是我们要替换的内容,我使用 stringr::str_extract_all
将其制作成一个向量。我提取了 COL
的所有实例,然后我们必须取消列出此输出,因为 str_extract_all
returns 是一个列表。第三,我使用相同的过程从 a 列中提取 COL+
条目。总之,我们使用 a 列中的条目替换 b 列中感兴趣的字符。
"COL.*?\b"
选择字母 COL
后跟尽可能少的字符,然后到达单词边界,这样我们就可以将 a 列中的条目变成多个项目(COL2010、COL2012 等)。
我们必须取消列出变异的行(即第一个“取消列出”),因为 dplyr
输出 list-column.