说我有一列df1$z
,其中包含一些“脏”字符串
> df1$z
[1] alpha uybkh kilo-mdjfyrs lima qxaucnpe gamma-qpnej
[5] beta-okmwy beta-uybkh gamma mdjfyrs lima qxaucnpe
[9] beta qpnej kilo okmwy
9 Levels: alpha uybkh beta-okmwy beta-uybkh ... lima qxaucnpe
某些字符串以包含在另一个向量a
中的模式开头。
> a
[1] "alpha" "beta" "gamma"
这些a
中与z
匹配的字符串要替换为向量a
的相应模式,以便得到以下结果:
# [1] "alpha" "kilo-mdjfyrs" "lima qxaucnpe" "gamma"
# [5] "beta" "beta" "gamma" "lima qxaucnpe"
# [9] "beta" "kilo okmwy"
我写了一个函数使我接近,但是它不能一次替换字符串,而且我无法将所有东西放在一起:
> lapply(seq_along(a), function(x) {z[grep(paste0("^", a[x]), z)] <- a[x]; z})
[[1]]
[1] "beta sfrmyijl" "lima-xudwfkm" "lima-kirvpys" "gamma wriygcb"
[5] "alpha" "alpha" "kilo xudwfkm" "alpha"
[9] "gamma wriygcb" "kilo-wvxgar"
[[2]]
[1] "beta" "lima-xudwfkm" "lima-kirvpys" "gamma wriygcb"
[5] "alpha wvxgar" "alpha-sfrmyijl" "kilo xudwfkm" "alpha-kirvpys"
[9] "gamma wriygcb" "kilo-wvxgar"
[[3]]
[1] "beta sfrmyijl" "lima-xudwfkm" "lima-kirvpys" "gamma"
[5] "alpha wvxgar" "alpha-sfrmyijl" "kilo xudwfkm" "alpha-kirvpys"
[9] "gamma" "kilo-wvxgar"
我也尝试了一些我认为可能有用的mapply()
方法,并调查了一些现有的答案,例如this one,但我无法适应我的特定问题。
那么我将如何以有效的 base R 方式进行此操作? 注意,应将替换项放回数据帧df1
中,而不会干扰行的顺序。
a <- c("alpha", "beta", "gamma")
set.seed(105056)
z <- paste0(sample(c(a, "kilo", "lima"), 10, replace=TRUE),
sample(c("-", " "), 10, replace=TRUE),
replicate(5, paste0(sample(letters, sample(5:9)), collapse="")))
df1 <- data.frame(z, x=rnorm(10))
答案 0 :(得分:1)
您可以使用以下sub
解决方案:
> sub(paste0(".*\\b(",paste(a, collapse="|"),")\\b.*"), "\\1", df1$z)
[1] "alpha" "kilo-mdjfyrs" "lima qxaucnpe" "gamma" "beta"
[6] "beta" "gamma" "lima qxaucnpe" "beta" "kilo okmwy"
该模式将匹配a
向量中关键字之前和之后的所有字符,并将关键字捕获到组1中,而\1
替换模式将仅保留找到的关键字并丢弃之前的所有文本之后。如果没有匹配项,则不会有任何变化。
请参见regex demo。
答案 1 :(得分:0)
我们可以使用sub
。从'a'中创建单个字符串后,使用paste
创建模式,然后使用它来捕获替换中带有后向引用(\\1
)的模式
sub(paste0(".*\\b(", paste(a, collapse="|"), ")\\b.*"), "\\1", df1$z)
#[1] "alpha" "kilo-mdjfyrs" "lima qxaucnpe" "gamma" "beta" "beta" "gamma"
#[8] "lima qxaucnpe" "beta" "kilo okmwy"
注意:sub
解决方案首先在此处发布
或使用str_replace
中的stringr
library(tidyverse)
df1 %>%
mutate(z = str_replace(z,
paste0(".*\\b(", paste(a, collapse="|"), ")\\b.*"), "\\1"))
# z x
#1 alpha -0.18973111
#2 kilo-mdjfyrs -0.88150363
#3 lima qxaucnpe 0.01665189
#4 gamma 0.62647841
#5 beta -0.29526632
#6 beta 0.42480082
#7 gamma 1.03653486
#8 lima qxaucnpe -1.51910745
#9 beta 1.21504343
#10 kilo okmwy 1.25321421
答案 2 :(得分:0)
使用ifelse
和grepl
,这是一个更长一些但不透明的解决方案:
df1$z <- ifelse(grepl("alpha.*", df1$z), a[1],
ifelse(grepl("beta.*", df1$z), a[2],
ifelse(grepl("gamma.*", df1$z), a[3], as.character(df1$z))))
df1
z x
1 alpha -0.18973111
2 kilo-mdjfyrs -0.88150363
3 lima qxaucnpe 0.01665189
4 gamma 0.62647841
5 beta -0.29526632
6 beta 0.42480082
7 gamma 1.03653486
8 lima qxaucnpe -1.51910745
9 beta 1.21504343
10 kilo okmwy 1.25321421