Extract every nth element of a vector
Asked Answered
B

5

161

I would like to create a vector in which each element is the i+6th element of another vector.

For example, in a vector of length 120 I want to create another vector of length 20 in which each element is value i, i+6, i+12, i+18... of the initial vector, i.e. I want to extract every 6th element of the original.

Brezhnev answered 8/3, 2011 at 19:56 Comment(0)
S
201
a <- 1:120
b <- a[seq(1, length(a), 6)]
Saunderson answered 8/3, 2011 at 20:3 Comment(4)
It is better to use seq.int(1L, length(a), 6L), at least for long vectorsInspiration
@WojciechSobala Could you comment why it is better?Abut
@DavidPell seq.int is faster in microbenchmarks, but I suspect that any performance increases in an actual program would be dwarfed by the running time of other parts.Basaltware
I hate to compare Python with R, but how great could PyRon be? a = 1:120; b = [::6]. Python can't do the former, R not the latter.Kenneth
M
55

Another trick for getting sequential pieces (beyond the seq solution already mentioned) is to use a short logical vector and use vector recycling:

foo[ c( rep(FALSE, 5), TRUE ) ]
Magbie answered 8/3, 2011 at 20:43 Comment(2)
An advantage of this approach is it can be used on a temporary; in order to use seq you have to be able to call length on the vector. letters[letters < 'm'][c(TRUE, FALSE, FALSE)]Barkley
This also made it easy to leave out every nth element by swapping places for FALSE and TRUE. (My problem was that I had two time series where one had 20 % higher resolution than the other. I could align them by selecting items 1, 2, 3, 4, 5 and then dropping 6, repeatedly.)Dani
Q
29

I think you are asking two things which are not necessarily the same

I want to extract every 6th element of the original

You can do this by indexing a sequence:

foo <- 1:120
foo[1:20*6]

I would like to create a vector in which each element is the i+6th element of another vector.

An easy way to do this is to supplement a logical factor with FALSEs until i+6:

foo <- 1:120
i <- 1
foo[1:(i+6)==(i+6)]
[1]   7  14  21  28  35  42  49  56  63  70  77  84  91  98 105 112 119

i <- 10
foo[1:(i+6)==(i+6)]
[1]  16  32  48  64  80  96 112
Quintillion answered 8/3, 2011 at 20:10 Comment(2)
So slick! I've used it in the other direction also, foo[1:(i+6)!=(i+6)] i.e. output all values except the sixth.Gamecock
a more general way to subset every nth element of a vector x would be x[1:(length(x)/n)*n]Voletta
J
3

To select every nth element from any starting position in the vector

nth_element <- function(vector, starting_position, n) { 
  vector[seq(starting_position, length(vector), n)] 
  }

# E.g.
vec <- 1:12

nth_element(vec, 1, 3)
# [1]  1  4  7 10

nth_element(vec, 2, 3)
# [1]  2  5  8 11
Juryrig answered 9/7, 2019 at 16:41 Comment(0)
B
2

To select every n-th element with an offset/shift of f=0,...,n-1, use

vec[mod(1:length(vec), n)==f]

Of course, you can wrap this in a nice function:

nth_element <- function(vec, interval, offset=0){
    vec[mod(1:length(vec), interval)==mod(offset, interval)]
}
Boaz answered 14/7, 2021 at 15:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.