Randomise order of groups in R data table while preserving internal order of groups

This can be done idiomatically by joining to a randomised list of groups.

x[sample(unique(Group)), on = "Group"][, RandomGroupID := .GRP, by = Group][]

You can also do it using split and rbindlist:

x_new <- rbindlist(sample(split(x, by='Group')))

    Group InternalOrder
 1:    d4             1
 2:    d1             1
 3:    d1             2
 4:    d1             3
 5:    d1             4
 6:    d5             1
 7:    d5             2
 8:    d5             3
 9:    d6             1
10:    d7             1
11:    d7             2
12:    d7             3
13:    d7             4
14:    d7             5
15:    d3             1
16:    d3             2
17:    d2             1

Here's one possibility:

x[, RandomGroupID := runif(1), by = Group ]
x[order(RandomGroupID), RandomGroupID := as.numeric(.GRP), by = Group]

Output:

    Group InternalOrder RandomGroupID
 1:    d1             1             4
 2:    d1             2             4
 3:    d1             3             4
 4:    d1             4             4
 5:    d2             1             7
 6:    d3             1             6
 7:    d3             2             6
 8:    d4             1             1
 9:    d5             1             2
10:    d5             2             2
11:    d5             3             2
12:    d6             1             5
13:    d7             1             3
14:    d7             2             3
15:    d7             3             3
16:    d7             4             3
17:    d7             5             3

Tags:

R

Data.Table