7

Suppose I have a vector

test<-c("a","b","c","d","e")

I am changing the order using another vector of indexes (this is essential):

sortvect<-c(2,3,5,4,1)
test2<-test[sortvect]

After that I do some operations on test2 and after that I want to switch back to initial order, having sortvect:

test<-give_my_order_back(test2,sortvect)

I have tried test2[sortvect] and test2[rev(sortvect)] but the solution is apparently different.

Slowpoke
  • 1,069
  • 1
  • 13
  • 37

4 Answers4

9

Alternatively order can also do this quite simply

test2[order(sortvect)]
# [1] "a" "b" "c" "d" "e"
dww
  • 30,425
  • 5
  • 68
  • 111
7

It is not that difficult. match(test, test2) will give you the index for reordering back.

test <- c("a","b","c","d","e")
sortvect <- c(2,3,5,4,1)
test2 <- test[sortvect]
sortback <- match(test, test2)
test2[sortback]
# [1] "a" "b" "c" "d" "e"
Zheyuan Li
  • 71,365
  • 17
  • 180
  • 248
  • This won't work if values in `test2` have changed in between – HubertL Oct 05 '16 at 22:41
  • @HubertL @ZheyuanLi I did `match(c(1,2,3,4,5),sortvect)` for my purposes – Slowpoke Oct 05 '16 at 22:47
  • 1
    @ZheyuanLi I've just noticed that the approach with `match()` potentially gives bigger powers (however I don't need them at the moment): one can roll back the order at particular stage, e.g. if there were two orderings applied sequentially: `sortvect1` and `sortvect2` – Slowpoke Oct 05 '16 at 22:54
  • @ZheyuanLi I think match is faster only on short vectors (when speed doesn't really matter). But try benchmarking large vectors, you will see order is faster. – dww Oct 05 '16 at 23:06
  • 1
    @Slowpoke you can of course also use `order` to undo sequentially applied orderings using `order (sortvec2)` followed by `order (sortvec1)` – dww Oct 05 '16 at 23:08
3

As pointed out by dww, to reverse the ordering, just use order on the index you used for deordering:

test <- c("a","b","c","d","e")
sortvect <- c(2,3,5,4,1)
test2 <- test[sortvect]
test2[order(sortvect)]
[1] "a" "b" "c" "d" "e"

this allows you to go back to original order even if you modified the object in between:

test <- c("a","b","c","d","e")
sortvect <- c(2,3,5,4,1)
test2 <- test[sortvect]
set.seed(12)
test2 <- paste0(sample(c("a","b","c","d","e"), 5, replace = F),test2)
test2[order(sortvect)]
[1] "ba" "ab" "dc" "ed" "ce"
HubertL
  • 19,246
  • 3
  • 32
  • 51
0

you can use rank() to compute the inverse permutation rather than sort(sort(x)). its the same calculation.

> test[order(sortvect)][rank(sortvect)]
[1] "a" "b" "c" "d" "e"

in general the below identities hold:

set.seed(0)
x<-matrix(rnorm(100),1)

all(order(order(x))==rank(x))
all(x==x[order(x)][rank(x)])
Nick Nassuphis
  • 257
  • 2
  • 6