【问题标题】:R: replace a value of a vector with multiple valuesR:用多个值替换向量的值
【发布时间】:2019-05-07 11:31:59
【问题描述】:

假设,我有一个向量 alength(a) = ll >= 1

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

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

例如: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"

谢谢!

【问题讨论】:

  • l 看起来有点像1,让我困惑了一秒钟。

标签: r vector replace insert


【解决方案1】:

这是一个简单的基于 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"

【讨论】:

  • 这很好。您可以使用rep(a, 1 + (length(b) - 1)*(a == "x")) 使其更通用。 +1
【解决方案2】:

这是一个使用 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)

#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)
}

【讨论】:

  • @IceCreamToucan 请将您的评论变成答案。我只是在更新基准。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 2016-06-10
相关资源
最近更新 更多