重复在向量中的元素与for循环

Max*_*Max 9 loops for-loop r vector repeat

我想在R中从3:50制作一个矢量,看起来像

3 4 4 5 6 6 7 8 8 .. 50 50

我想在for循环中使用for循环,但它不是我想要的wat.

f <- c()
for (i in 3:50) {
  for(j in 1:2) {
    f = c(f, i)
  }
}
Run Code Online (Sandbox Code Playgroud)

这有什么问题?

Jaa*_*aap 16

另一个选择是使用嵌入式rep:

rep(3:50, rep(1:2, 24))
Run Code Online (Sandbox Code Playgroud)

这使:

 [1]  3  4  4  5  6  6  7  8  8  9 10 10 11 12 12 13 14 14 15 16 16 17 18 18 19 20 20
[28] 21 22 22 23 24 24 25 26 26 27 28 28 29 30 30 31 32 32 33 34 34 35 36 36 37 38 38
[55] 39 40 40 41 42 42 43 44 44 45 46 46 47 48 48 49 50 50
Run Code Online (Sandbox Code Playgroud)

这利用了以下事实:times-argument rep也可以是整数向量,其等于x参数的长度.

您可以将此概括为:

s <- 3
e <- 50
v <- 1:2

rep(s:e, rep(v, (e-s+1)/2))
Run Code Online (Sandbox Code Playgroud)

即使使用的混合另一种选择reprep_len:

v <- 3:50
rep(v, rep_len(1:2, length(v)))
Run Code Online (Sandbox Code Playgroud)

  • 这在概念上很简单(虽然你必须考虑它有点看它是如何工作的)并且非常快(我的机器平均只有1微秒). (2认同)

www*_*www 9

基于的解决方案sapply.

as.vector(sapply(0:23 * 2 + 2, function(x)  x + c(1, 2, 2)))

# [1]  3  4  4  5  6  6  7  8  8  9 10 10 11 12 12 13 14 14 15 16 16 17 18 18 19 20 20 21 22 22 23 24 24 25 26 26
# [37] 27 28 28 29 30 30 31 32 32 33 34 34 35 36 36 37 38 38 39 40 40 41 42 42 43 44 44 45 46 46 47 48 48 49 50 50
Run Code Online (Sandbox Code Playgroud)

标杆

以下是所有当前答案的性能比较.结果表明cumsum(rep(c(1, 1, 0), 24)) + 2L(m8)是最快的,而rep(3:50, rep(1:2, 24))(m1)几乎和m8.

library(microbenchmark)
library(ggplot2)

perf <- microbenchmark(
  m1 = {rep(3:50, rep(1:2, 24))},
  m2 = {rep(3:50, each = 2)[c(TRUE, FALSE, TRUE, TRUE)]},
  m3 = {v <- 3:50; sort(c(v,v[v %% 2 == 0]))},
  m4 = {as.vector(t(cbind(seq(3,49,2),seq(4,50,2),seq(4,50,2))))},
  m5 = {as.vector(sapply(0:23 * 2 + 2, function(x)  x + c(1, 2, 2)))},
  m6 = {sort(c(3:50, seq(4, 50, 2)))},
  m7 = {rep(seq(3, 50, 2), each=3) + c(0, 1, 1)},
  m8 = {cumsum(rep(c(1, 1, 0), 24)) + 2L},
  times = 10000L
)

perf
# Unit: nanoseconds
# expr   min    lq      mean median    uq     max neval
#   m1   514  1028  1344.980   1029  1542  190200 10000
#   m2  1542  2570  3083.716   3084  3085  191229 10000
#   m3 26217 30329 35593.596  31871 34442 5843267 10000
#   m4 43180 48321 56988.386  50891 55518 6626173 10000
#   m5 30843 35984 42077.543  37526 40611 6557289 10000
#   m6 40611 44209 50092.131  46779 50891  446714 10000
#   m7 13879 16449 19314.547  17478 19020 6309001 10000
#   m8     0  1028  1256.715   1028  1542   71454 10000
Run Code Online (Sandbox Code Playgroud)


akr*_*ica 8

使用该rep功能,以及使用回收逻辑索引的可能性...[c(TRUE, FALSE, TRUE, TRUE)]

rep(3:50, each = 2)[c(TRUE, FALSE, TRUE, TRUE)]

 ## [1]  3  4  4  5  6  6  7  8  8  9 10 10 11 12 12 13 14 14 15 16 16 17 18 18 19
## [26] 20 20 21 22 22 23 24 24 25 26 26 27 28 28 29 30 30 31 32 32 33 34 34 35 36
## [51] 36 37 38 38 39 40 40 41 42 42 43 44 44 45 46 46 47 48 48 49 50 50
Run Code Online (Sandbox Code Playgroud)

如果使用逻辑向量(TRUE/ FALSE)作为索引(内部[ ]),TRUE则会导致选择相应的元素并FALSE导致遗漏.如果逻辑索引vector(c(TRUE, FALSE, TRUE, TRUE))比索引向量(rep(3:50, each = 2)在您的情况下)短,则索引向量将被重新计算.

另外还有一个注意事项:每当你使用R代码时

 x = c(x, something)
Run Code Online (Sandbox Code Playgroud)

要么

 x = rbind(x, something)
Run Code Online (Sandbox Code Playgroud)

或类似的,你在R中采用类似C的编程风格.这使得你的代码无法复杂,并且如果你使用大型(比方说,200MB +)数据集,可能会导致低性能和内存不足问题.R旨在为您提供数据结构的低级修补.

阅读有关R Inferno,Circle 2:Growing Objects 的馋嘴及其惩罚的更多信息.


MKR*_*MKR 5

我能找到的最简单的方法是创建另一个只包含even值的方法(基于OP的意图),然后简单地连接两个向量.例子可能是:

v <- 3:50
sort(c(v,v[v %% 2 == 0]))

# [1]  3  4  4  5  6  6  7  8  8  9 10 10 11 12 12 13 14 14 15 16 16
#      17 18 18 19 20 20 21 22 22 23 24 24 25 26 26 27 28 28
#[40] 29 30 30 31 32 32 33 34 34 35 36 36 37 38 38 39 40 40 41 42 42
#     43 44 44 45 46 46 47 48 48 49 50 50
Run Code Online (Sandbox Code Playgroud)