Sort data maintaining original relative positions of first occurrences of different types

Viewed 32

I have a tibble, d, arranged such that value is decreasing.

I want to gather all the same types together, whilst maintaining the relative arrangements of the first entry of each type. This is shown in d_sorted.

A normal group_by() won't work for me.

How can I sort my data?

library(tidyverse)

#before
d <- tribble(
  ~"type", ~"value",
  "R" , 109,
  "C" , 105,
  "B" , 80,
  "W" , 77,
  "R" , 70,
  "W" , 66,
  "A" , 58,
  "C" , 55
)


#after
d_sorted <- tribble(
  ~"type", ~"value",
  "R" , 109,
  "R" , 70,
  "C" , 105,
  "C" , 55,
  "B" , 80,
  "W" , 77,
  "W" , 66,
  "A" , 58
)

Created on 2021-04-15 by the reprex package (v1.0.0)

3 Answers

You can use arrange with match :

library(dplyr)
d %>% arrange(match(type, unique(type)))

#  type  value
#  <chr> <dbl>
#1 R       109
#2 R        70
#3 C       105
#4 C        55
#5 B        80
#6 W        77
#7 W        66
#8 A        58

In base R :

d[order(match(d$type, unique(d$type))), ]

This could also be done by factoring and using unique

d %>% arrange(type = factor(type, unique(type)))

Output:

# A tibble: 8 x 2
  type  value
  <chr> <dbl>
1 R       109
2 R        70
3 C       105
4 C        55
5 B        80
6 W        77
7 W        66
8 A        58

Another solution with data.table join:

library(tibble)
setDT(d)
d[CJ(type, sorted = F, unique = T), on = .(type)]
   type value
1:    R   109
2:    R    70
3:    C   105
4:    C    55
5:    B    80
6:    W    77
7:    W    66
8:    A    58
Related