Freeego
Freeego

Reputation: 135

how to select neighbouring elements in a vector and put them into a list or matrix in R

I have a problem about how to select neighboring elements in a vector and put them into a list or matrix in R. For example:

vl <- c(1,2,3,4,5)

I want to get the results like this:

1,2
2,3
3,4
4,5

The results can be in a list or matrix

I know we can use a loop to get results.Like this:

pl <- list()
k=0
for (p in 1: length(vl)) {
          k=k+1
          pl[[k]] <- sort(c(vl[p],vl[p+1]))}

But I have a big data. Using loop is relatively slow. Is there any function to get results directly? Many thanks!

Upvotes: 1

Views: 112

Answers (3)

Uwe
Uwe

Reputation: 42544

The problem can also be solved by applying the sort() function on a rolling window of length 2:

vl <- c(2,5,3,1,6,4)
zoo::rollapply(vl, 2L, sort)

which returns a matrix as requested:

     [,1] [,2]
[1,]    2    5
[2,]    3    5
[3,]    1    3
[4,]    1    6
[5,]    4    6

Note that the modified input vector vl is used which has been posted by the OP in comments here and here.

Besides zoo, there are also other packages which offer rollapply functions, e.g.,

t(rowr::rollApply(vl, sort, 2L, 2L))

Upvotes: 0

lroha
lroha

Reputation: 34471

You can do:

matrix(c(vl[-length(vl)], vl[-1]), ncol = 2)

     [,1] [,2]
[1,]    1    2
[2,]    2    3
[3,]    3    4
[4,]    4    5

If you want to sort two columns rowwise, then you can use pmin() and pmax() which will be faster than using apply(x, 1, sort) with a large number of rows.

sapply(c(pmin, pmax), do.call, data.frame(vl[-length(vl)], vl[-1]))

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

We can use head and tail to ignore the last and first element respectively.

data.frame(a = head(vl, -1), b = tail(vl, -1))

#  a b
#1 1 2
#2 2 3
#3 3 4
#4 4 5

EDIT

If the data needs to be sorted we can use apply row-wise to sort it.

vl <- c(2,5,3,1,6,4)
t(apply(data.frame(a = head(vl, -1), b = tail(vl, -1)), 1, sort))


#     [,1] [,2]
#[1,]    2    5
#[2,]    3    5
#[3,]    1    3
#[4,]    1    6
#[5,]    4    6

Upvotes: 1

Related Questions