Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating alternate series in r

Tags:

sorting

r

I have a list of

-0.5, -0.6, 0.7, 1, 1.5, 3, -5

and I would like to sort it as

3, -5, 1.5, -0.6, 1, -0.5, 0.7

In other words, I would like to sparate the list into positive and negative lists, then sort them from largest to smallest, but alternating.

How can I do this?

like image 410
Math Avengers Avatar asked Jan 30 '19 15:01

Math Avengers


4 Answers

How about

pos <- sort(x[x>0], decreasing = T)
neg <- sort(x[x<0], decreasing = T)

c(rbind(pos,neg))[1:length(x)]

#[1]  3.0 -0.5  1.5 -0.6  1.0 -5.0  0.7
like image 133
989 Avatar answered Oct 04 '22 16:10

989


Data

x <- c(-0.5, -0.6, 0.7, 1, 1.5, 3, -5)

Use rbind() to create an alternate indices vector.

ind <- seq_along(x)
sort(x, decreasing = T)[rbind(ind, rev(ind))][ind]
# [1]  3.0 -5.0  1.5 -0.6  1.0 -0.5  0.7

The above method should be memory consuming because it will create a twice longer vector. To conquer it, you can set a midpoint as the end index. In this case, it will be ceiling(7 / 2) = 4.

n <- length(x)
ind <- 1:ceiling(n / 2) # [1] 1 2 3 4
sort(x, decreasing = T)[rbind(ind, (n:1)[ind])][1:n]
# [1]  3.0 -5.0  1.5 -0.6  1.0 -0.5  0.7
like image 30
Darren Tsai Avatar answered Oct 18 '22 03:10

Darren Tsai


We can split the list based on sign and sort them. We then create a new list by taking alternating elements from positive and negative lists making sure to reverse the positive part of the list.

new_list <- sapply(split(x, sign(x)), sort)
c(rbind(rev(new_list[['1']]), new_list[['-1']]))[1:length(x)]
#[1]  3.0 -5.0  1.5 -0.6  1.0 -0.5  0.7

data

x <- c(-0.5, -.6, 0.7, 1, 1.5, 3, -5 )
like image 5
Ronak Shah Avatar answered Oct 18 '22 04:10

Ronak Shah


One option is to split the vector by the sign of the vector into a list of vectors, loop through the vector, order the absolute value of the elements in decreasing order, get the lengths of the list elements same with padding NA at the end, rbind them together as a matrix, convert it to vector with c and remove the NA elements with na.omit

lst1 <- sapply(split(v1, sign(v1)), function(x)  
    x[order(abs(x), decreasing = TRUE)])[2:1]
c(na.omit(c(do.call(rbind, lapply(lst1, `length<-`, max(lengths(lst1)))))))
#[1]  3.0 -5.0  1.5 -0.6  1.0 -0.5  0.7

data

v1 <- c(-0.5, -0.6, 0.7, 1, 1.5, 3, -5)
like image 2
akrun Avatar answered Oct 18 '22 04:10

akrun