如何在R中连续连接整数向量

soat7uwm  于 2023-06-19  发布在  其他
关注(0)|答案(5)|浏览(100)
vec <- c(1, 3, 2, 37)

我想连续地连接这个向量,这样输出看起来像这样:

> output
[[1]]
[1] 1

[[2]]
[1] 1 3

[[3]]
[1] 1 3 2

[[4]]
[1] 1 3 2 37

我写了一个函数来完成这个任务,但它没有给我正确的输出:

myfun <- function(vec){
  output = vector("list", length(vec))
  output[[1]] = vec[1]
  for(i in 2:length(vec)){
    output[[i]] = paste(output[[i - 1]], vec[i])
    output[[i]] = as.numeric(strsplit(output[[i]], " ")[[1]])
  }
  return(output)
}
> myfun(c(1, 3, 2, 37))
[[1]]
[1] 1

[[2]]
[1] 1 3

[[3]]
[1] 1 2

[[4]]
[1]  1 37
fcwjkofz

fcwjkofz1#

一个直接的方法是Reduce

Reduce(f = c,x = vec,accumulate = TRUE)

有一个purrr::accumulate函数可以完成同样的事情:

purrr::accumulate(.x = vec,.f = c,.simplify = FALSE)

(编辑为合并注解,仅使用c()作为函数,简单得多。

wgmfuz8q

wgmfuz8q2#

我们可以使用lapplyhead(或[)来实现:

lapply(seq_along(vec), head, x = vec)
# [[1]]
# [1] 1
# [[2]]
# [1] 1 3
# [[3]]
# [1] 1 3 2
# [[4]]
# [1]  1  3  2 37
  • seq_along(vec)类似于1:length(vec)(我们也可以使用它,但seq_along在极端情况下更安全);
  • lapply被赋予一个函数时,它通常调用一次,其中第一个参数包含值(将连续地从1到4);由于我们包含了x=vec(这是head的第一个参数),那么lapply将该数字作为head的下一个参数,恰好是n=

我们也可以做lapply(seq_along(vec), function(z) vec[1:z])

  • 编辑 *:后者(vec[1:z]实现)明显比使用head快,我应该知道这一点。
bench::mark(
  a1=lapply(seq_along(vec), head, x = vec),
  a2=lapply(seq_along(vec), function(z) vec[1:z]), 
  a3=lapply(1:length(vec), function(z) vec[1:z]),
  b=Reduce(f = c,x = vec,accumulate = TRUE),
  iterations = 100000)
# # A tibble: 4 × 13
#   expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result     memory     time      
#   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list>     <list>     <list>    
# 1 a1          11.51µs  16.14µs    53800.        0B     3.23 99994     6      1.86s <list [4]> <Rprofmem> <bench_tm>
# 2 a2           2.95µs   4.06µs   215605.        0B     4.31 99998     2    463.8ms <list [4]> <Rprofmem> <bench_tm>
# 3 a3           3.04µs   4.01µs   221482.        0B     2.21 99999     1    451.5ms <list [4]> <Rprofmem> <bench_tm>
# 4 b            3.42µs    4.3µs   209810.        0B     4.20 99998     2   476.61ms <list [4]> <Rprofmem> <bench_tm>
# # ℹ 1 more variable: gc <list>
mccptt67

mccptt673#

我想不出比Reduce(@joran)或lapply(@r2evans)更好的解决方案,它们已经足够高效和简洁了。
这里是另一个基础R选项***但只是为了好玩***

> split(vec[(k <- sequence(seq_along(vec)))], cumsum(k == 1))
$`1`
[1] 1

$`2`
[1] 1 3

$`3`
[1] 1 3 2

$`4`
[1]  1  3  2 37
5rgfhyps

5rgfhyps4#

如果这样做的原因是为了以后可以迭代列表,例如,求和

L <- list(vec[1], vec[1:2], vec[1:3], vec[1:4])
sapply(L, sum)
## [1]  1  4  6 43

那么我们可以通过使用rollapplyr来避免首先创建L:

library(zoo)

rollapplyr(vec, seq_along(vec), sum)  # same but no intermediate L
## [1]  1  4  6 43

注意事项

vec取自问题

vec <- c(1, 3, 2, 37)
41ik7eoe

41ik7eoe5#

另一个基本R方法使用matrix,只是为了完整性

mat <- matrix(vec, nrow=length(vec), ncol=length(vec), byrow=T)
mat[upper.tri(mat)] <- NA
apply(mat, 1, \(x) as.vector(na.omit(x)))
[[1]]
[1] 1

[[2]]
[1] 1 3

[[3]]
[1] 1 3 2

[[4]]
[1]  1  3  2 37

相关问题