1

I have a vector of integers that I want to split by 3, then I have to order the splitted parts and put bac into integer vector.

as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))

First step - split like this:

16,9,2
17,10,3
18,11,4
19,12,5
20,13,6
21,14,7
22,15,8

Second step - order:

2,9,16
3,10,17
4,11,18
5,12,19
6,13,20
7,14,21
8,15,22

Third step - put back into integer vector:

2,9,16,3,10,17,4,11,18,5,12,19,6,13,20,7,14,21,8,15,22
Maël
  • 45,206
  • 3
  • 29
  • 67
Mar
  • 117
  • 10
  • 1
    How are you actually defining the sort operation in the second step - are you sorting the columns based on the first row? Or are you sorting each row? Or sorting the entire matrix (which would be the same as sorting the vector)? It would help if you posted an example with some data where these did not all lead to the same output. – SamR Nov 09 '22 at 13:44

6 Answers6

3

With matrix + sort:

x <- as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))
c(apply(matrix(x, ncol = 3, byrow = T), 1, sort))
#[1]  2  9 16  3 10 17  4 11 18  5 12 19  6 13 20  7 14 21  8 15 22

Or with split + gl:

unlist(lapply(split(x, gl(length(x) / 3, 3)), sort))

Another shorter approach with split + rev (only works if rev and sort are the same):

c(do.call(rbind, rev(split(x, 1:3))))
#[1]  2  9 16  3 10 17  4 11 18  5 12 19  6 13 20  7 14 21  8 15 22
Maël
  • 45,206
  • 3
  • 29
  • 67
  • This would only work if all groups of 3 are sorted decreasingly, right? But it's a very elegant solution! – swolf Nov 09 '22 at 13:32
  • @swolf I think it'd work either way. `rev` is not `sort`; `rev` only reverse the vector, irrespective of sorting. – Maël Nov 09 '22 at 13:39
  • 1
    @SamR it's not my example data but you are right. if the groups of 3 are not simply reversable every time, the example data should reflect that. – swolf Nov 09 '22 at 13:39
  • 2
    Oh, I see what you mean! I thought you wanted to reverse, but you want to sort! Then changing the function is simple, replace `rev` by `sort`. – Maël Nov 09 '22 at 13:40
2

No {dplyr} required here.

x <- as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))
spl.x <- split(x, ceiling(seq_along(x)/3)) # split the vector
spl.x <- lapply(spl.x, sort) # sort each element of the list
Reduce(c, spl.x) # Reduce list to vector

Second line (splitting) is from this answer: https://stackoverflow.com/a/3321659/2433233

This also works if the length of your original vector is no multiple of 3. The last list element is shorter in this case.

swolf
  • 1,020
  • 7
  • 20
1

Here is one way to do steps in order:

vector=as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))
chunk <- 3
n <- length(vector)
r  <- rep(1:ceiling(n/chunk),each=chunk)[1:n]
list_of3 <- split(vector,r)
# > list_of3
# $`1`
# [1] 16  9  2
# 
# $`2`
# [1] 17 10  3
# 
# $`3`
# [1] 18 11  4
# 
# $`4`
# [1] 19 12  5
# 
# $`5`
# [1] 20 13  6
# 
# $`6`
# [1] 21 14  7
# 
# $`7`
# [1] 22 15  8
sorted_list<- lapply(list_of3, function(x)sort(x))
final_vector <- unname(unlist(sorted_list))
final_vector
# > final_vector
# [1]  2  9 16  3 10 17  4 11 18  5 12 19  6 13 20  7 14 21  8 15 22```
islem
  • 236
  • 1
  • 6
  • 1
    If you use `sapply()` with `USE.NAMES = FALSE`, you can eliminate your `unname(unlist())` step. (+1) – zephryl Nov 09 '22 at 13:46
0

Here is one way to do it:

v <- as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))
res <- split(v, 0:(length(v)-1) %/%3)
unlist(lapply(res, sort), use.names = FALSE)
Clemsang
  • 5,053
  • 3
  • 23
  • 41
0

You can put your data into a 3 column matrix by row, sort rowwise, transpose and convert back to vector:

v <- as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))
m <- matrix(v, ncol = 3, byrow = TRUE)
c(t(matrix(m[order(row(m), m)], nrow(m), byrow = TRUE)))

[1]  2  9 16  3 10 17  4 11 18  5 12 19  6 13 20  7 14 21  8 15 22
Ritchie Sacramento
  • 29,890
  • 4
  • 48
  • 56
0

Something like this goes through every step:

v = as.integer(c(16,9,2,17,10,3,18,11,4,19,12,5,20,13,6,21,14,7,22,15,8))

v2 = v  %>% matrix(ncol= 3, byrow = T) 


# [,1] [,2] [,3]
# [1,]   16    9    2
# [2,]   17   10    3
# [3,]   18   11    4
# [4,]   19   12    5
# [5,]   20   13    6
# [6,]   21   14    7
# [7,]   22   15    8

v3 = v2[, rev(seq_len(ncol(v2)))]

# [,1] [,2] [,3]
# [1,]    2    9   16
# [2,]    3   10   17
# [3,]    4   11   18
# [4,]    5   12   19
# [5,]    6   13   20
# [6,]    7   14   21
# [7,]    8   15   22


v4 = v3 %>% as.vector

# [1]  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22
Juan C
  • 5,846
  • 2
  • 17
  • 51