1

Is there a function in R which switches the first element with the last one in a vector? I have a for loop which need that reordering. From:

months = seq(1:12)
[1]  1  2  3  4  5  6  7  8  9 10 11 12

I would like to have:

[1]  12 1  2  3  4  5  6  7  8  9 10 11

and then again:

[1]  11 12  1  2  3  4  5  6  7  8  9 10

... until the 12th position.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Ruser_edf
  • 13
  • 2

4 Answers4

4

If you need a matrix output

 cbind(c(months),embed(c(months, months), 12)[-13,-12])
 #       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 # [1,]    1   12   11   10    9    8    7    6    5     4     3     2
 # [2,]    2    1   12   11   10    9    8    7    6     5     4     3
 # [3,]    3    2    1   12   11   10    9    8    7     6     5     4
 # [4,]    4    3    2    1   12   11   10    9    8     7     6     5
 # [5,]    5    4    3    2    1   12   11   10    9     8     7     6
 # [6,]    6    5    4    3    2    1   12   11   10     9     8     7
 # [7,]    7    6    5    4    3    2    1   12   11    10     9     8
 # [8,]    8    7    6    5    4    3    2    1   12    11    10     9
 # [9,]    9    8    7    6    5    4    3    2    1    12    11    10
 #[10,]   10    9    8    7    6    5    4    3    2     1    12    11
 #[11,]   11   10    9    8    7    6    5    4    3     2     1    12
 #[12,]   12   11   10    9    8    7    6    5    4     3     2     1

Or another approached suggested by @Marat Talipov

 z <- length(months)
 i <- rep(seq(z),z) + rep(seq(z),each=z) - 1
 matrix(months[ifelse(i>z,i-z,i)],ncol=z)
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Another approach to obtain matrix: `z <- length(months); i <- rep(seq(z),z) + rep(seq(z),each=z) - 1; matrix(months[ifelse(i>z,i-z,i)],ncol=z)` – Marat Talipov Feb 17 '15 at 16:26
  • No, because it produces symmetric matrix, in which the first row contains the original vector, and every subsequent row rotates the previous row to the left by one position. – Marat Talipov Feb 17 '15 at 16:30
  • Oh, I've just noticed that your solution not only rotates but also reverses the original vector (e.g. see the last row of your sample output). – Marat Talipov Feb 17 '15 at 16:32
  • @MaratTalipov I was looking through the columns instead of the rows. – akrun Feb 17 '15 at 16:35
3

I'm afraid that you have to come up with a home-made function, something like this one:

rotate <- function(v,i=1) {
  i <- i %% length(v)
  if (i==0) return(v)
  v[c(seq(i+1,length(v)),seq(i))]
}

Couple of examples:

v <- seq(12)
rotate(v,1)
# [1]  2  3  4  5  6  7  8  9 10 11 12  1

rotate(v,-1)
# [1] 12  1  2  3  4  5  6  7  8  9 10 11
Marat Talipov
  • 13,064
  • 5
  • 34
  • 53
2

You can also use tail and head functions:

x = c(tail(x,n), head(x,-n))

and modify n to rotate n times

ClementWalter
  • 4,814
  • 1
  • 32
  • 54
2

The permute package can do this for you:

ap <- allPerms(length(months),
               control = how(within = Within(type = "series"),
                             observed = TRUE))
ap[rev(seq_len(nrow(ap))), ]

(because of the way allPerms() does its work, we need to reverse the order of the rows, which is what the last line does.)

This gives:

> ap[rev(seq_len(nrow(ap))), ]
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1    2    3    4    5    6    7    8    9    10    11    12
 [2,]   12    1    2    3    4    5    6    7    8     9    10    11
 [3,]   11   12    1    2    3    4    5    6    7     8     9    10
 [4,]   10   11   12    1    2    3    4    5    6     7     8     9
 [5,]    9   10   11   12    1    2    3    4    5     6     7     8
 [6,]    8    9   10   11   12    1    2    3    4     5     6     7
 [7,]    7    8    9   10   11   12    1    2    3     4     5     6
 [8,]    6    7    8    9   10   11   12    1    2     3     4     5
 [9,]    5    6    7    8    9   10   11   12    1     2     3     4
[10,]    4    5    6    7    8    9   10   11   12     1     2     3
[11,]    3    4    5    6    7    8    9   10   11    12     1     2
[12,]    2    3    4    5    6    7    8    9   10    11    12     1

Technically this only works because months is the vector 1:12 and allPerms() returns a permutation matrix of the indices of the thing you want permuted. For different inputs, use ap to index into the thing you want to permute

perms <- ap
perms[] <- months[ap[rev(seq_len(nrow(ap))), ]]
perms
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453