Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reversing the order of duplicated sections in a vector

Tags:

r

Consider the following pre-sorted vector x.

x <- c(1, 2, 2, 2, 3, 5, 7, 7, 7, 8)

order() shows us the order of the vector.

( o <- order(x) )
# [1]  1  2  3  4  5  6  7  8  9 10

Now suppose I want to reverse the order of only the duplicated/repeated values of x, meaning I want to reverse just the 2 3 4 and 7 8 9 sections of o because those are the values repeated in x. Then, the desired result would be

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

What is the best way to do that? Right now I've got the following

w <- which(duplicated(x) | duplicated(x, fromLast = TRUE))
o[w] <- rev(o[w])

But that does not give the correct answer here.

o
# [1]  1  9  8  7  5  6  4  3  2 10

PS - I am using this to reverse the column order of duplicated column names.

like image 213
Rich Scriven Avatar asked Sep 22 '15 23:09

Rich Scriven


People also ask

Does remove duplicates remove the first or second?

When duplicates are removed, the first occurrence of the value in the list is kept, but other identical values are deleted. Because you are permanently deleting data, it's a good idea to copy the original range of cells or table to another worksheet or workbook before removing duplicate values.

How do I get rid of duplicate elements?

We can remove duplicate element in an array by 2 ways: using temporary array or using separate index. To remove the duplicate element from array, the array must be in sorted order. If array is not sorted, you can sort it by calling Arrays. sort(arr) method.

How do you remove a repeating element from a vector?

Using std::remove function A simple solution is to iterate the vector, and for each element, we delete all its duplicates from the vector if present. We can either write our own routine for this or use the std::remove algorithm that makes our code elegant. This approach takes constant space but runs in O(n2) time.


2 Answers

Using data.table v1.9.6:

require(data.table)
as.data.table(x)[, .(id = rev(.I)), by=x]
#     x id
#  1: 1  1
#  2: 2  4
#  3: 2  3
#  4: 2  2
#  5: 3  5
#  6: 5  6
#  7: 7  9
#  8: 7  8
#  9: 7  7
# 10: 8 10

Alternatively, you can do:

order(x + sort(runif(length(x)), dec=TRUE))
#  [1]  1  4  3  2  5  6  9  8  7 10

(not entirely sure if there are cases where this could break)

like image 128
Arun Avatar answered Sep 29 '22 15:09

Arun


A base R 1-liner would be using ave to group the ordering by unique values in the original vector, applying rev to reverse the ordering for each group:

ave(order(x), x, FUN=rev)
# [1]  1  4  3  2  5  6  9  8  7 10
like image 38
josliber Avatar answered Sep 29 '22 15:09

josliber