R:用多个值替换向量的值

时间:2018-12-05 20:15:52

标签: r vector replace insert

比方说,我有一个alength(a) = l的向量l >= 1

元素"x"a中至少发生一次,但我们不知道确切位置。

我想用值"x"替换a中的每个c(1,2,3)

例如:a = ("y","x","z"),那么我希望替换后的结果为a = ("y",1,2,3,"z")

我想这样做:

l <- length(a)
pos.x <- which(a == "x")

if(l == 1L & pos.x == 1L) {
  a <- c(1,2,3)
} else if (l > 1L & pos.x == 1) {
  a <- c(1,2,3,a[-1])
} else if (l > 1L & pos.x == l) {
  a <- c(a[-l],1,2,3)
} else if (l >= 3 & pos.x != 1 & pos.x != l) {
  a <- c(a[1:(pos.x - 1)],1,2,3,a[(pos.x + 1):l])
}

虽然此代码确实有效,但我的问题是,是否存在一种更“优雅”的方法来解决此问题,需要更少的处理能力并且可以替换多个"x"

谢谢!

2 个答案:

答案 0 :(得分:4)

这是一个以R为底的简单向量化解决方案-

a <- c("y","x","z","y","x","z") # vector to search
b <- 1:3 # replacement values

a <- rep(a, 1 + (length(b) - 1)*(a == "x")) # repeat only "x" length(b) times

a[a == "x"] <- b # replace "x" with replacement values i.e. b

[1] "y" "1" "2" "3" "z" "y" "1" "2" "3" "z"

答案 1 :(得分:3)

这里是使用for循环的选项

a <- c("y","x","z","y","x","z")
b <- c(1,2,3)

“技巧”是先创建一个列表,然后将所有"x"替换为b,最后调用unlist

a_list <- as.list(a)
for(i in which(a_list == "x")) {
  a_list[[i]] <- b
}

结果

unlist(a_list)
#[1] "y" "1" "2" "3" "z" "y" "1" "2" "3" "z"

请考虑@Shree的答案!

这是原因:

n <- 1e6
set.seed(1)
a <- sample(c("x", "y", "z"), size = n, replace = TRUE)
b <- 1:3

library(microbenchmark)
benchmark <- microbenchmark(
  markus = markus(a, b),
  IceCreamToucan = IceCreamToucan(a, b),
  Shree = Shree(a, b)
)

autoplot(benchmark)

enter image description here

#Unit: milliseconds
#           expr       min        lq     mean    median       uq       max neval
#        markus 403.38464 467.03277 615.8078 556.74067 754.5117 1095.7035   100
#IceCreamToucan 401.34614 462.92680 602.1556 526.08280 687.8436 1422.0629   100
#         Shree  52.33867  65.32323 157.6680  97.34066 162.0638  650.2571   100

功能

markus <- function(a, b) {
  a_list <- as.list(a)
  for(i in which(a_list == "x")) {
    a_list[[i]] <- b
  }
  unlist(a_list)  
}

Shree <- function(a, b) {
  a <- rep(a, 1 + (length(b) - 1)*(a == "x"))
  a[a == "x"] <- b
  a
}

# from the comments
IceCreamToucan <- function(a, b) {
  a_list <- as.list(a)
  w <- which(a_list == "x")
  a_list[w] <- rep(list(b), length(w)) # changed your answer slightly here
  unlist(a_list)
}