4

suppose I have the following vector:

v1 = c(1,2,3,4)

I need to iterate over this vector in a pairwise fashion, like (1,2), (2,3), (3,4). For python, there is a solution to this problem here: Iterate over all pairs of consecutive items in a list. Can a similar solution be achieved in R?

jay.sf
  • 46,523
  • 6
  • 46
  • 87
Max Beikirch
  • 1,943
  • 3
  • 23
  • 34

4 Answers4

9

We can remove the first and last elements and concatenate in Map

Map(c,  v1[-length(v1)], v1[-1])
#[[1]]
#[1] 1 2

#[[2]]
#[1] 2 3

#[[3]]
#[1] 3 4

Or rbind and use asplit

asplit(rbind(v1[-length(v1)], v1[-1]), 2)
akrun
  • 789,025
  • 32
  • 460
  • 575
4

Just cbind the shifted vector.

cbind(v1[-length(v1)], v1[-1])
#      [,1] [,2]
# [1,]    1    2
# [2,]    2    3
# [3,]    3    4

R is vectorized, no need for iteration.

jay.sf
  • 46,523
  • 6
  • 46
  • 87
3

These solutions all easily generalize to windows of greater than 2 by replacing 2 with some other number.

1) rollapply Replace toString with whatever function you want to use.

library(zoo)
rollapply(v1, 2, toString)
## [1] "1, 2" "2, 3" "3, 4"

1a) or create a 2 column matrix and then iterate over that in a second step:

library(zoo)
m <- rollapply(v1, 2, c)
apply(m, 1, toString)
## [1] "1, 2" "2, 3" "3, 4"

2) embed or use embed. This does not use any packages.

e <- embed(v1, 2)[, 2:1]
apply(e, 1, toString)
## [1] "1, 2" "2, 3" "3, 4"
G. Grothendieck
  • 233,926
  • 16
  • 195
  • 321
2

A base R option using embed + asplit

> asplit(embed(v1,2)[,2:1],1)
[[1]]
[1] 1 2

[[2]]
[1] 2 3

[[3]]
[1] 3 4
ThomasIsCoding
  • 80,151
  • 7
  • 17
  • 65