假设我有一个列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-matching的对应模式替换z中的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,虽然我无法适应具体的问题。
那么,我如何以一个有效的基数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))发布于 2018-12-12 17:31:19
您可以使用以下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向量中关键字之前和之后的任何字符,并将关键字捕获到Group 1中,而\1替换模式只保留查找的关键字,并在该关键字之前和之后丢弃所有文本。如果没有匹配,就不会有任何变化。
发布于 2018-12-12 17:30:57
我们可以用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解决方案是在这里首先发布的
或者使用来自stringr的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发布于 2018-12-12 20:21:12
下面是一个更长但不那么不透明的解决方案,使用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.25321421https://stackoverflow.com/questions/53747918
复制相似问题