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
  • 60,139
  • 8
  • 53
  • 110
Max Beikirch
  • 2,053
  • 5
  • 25
  • 36

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
  • 874,273
  • 37
  • 540
  • 662
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
  • 60,139
  • 8
  • 53
  • 110
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
  • 254,981
  • 17
  • 203
  • 341
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
  • 96,636
  • 9
  • 24
  • 81