I would do the operation, and then sorted randomly:
mydf[,list(x,v),by=y][sample(seq_len(nrow(mydf)),replace=FALSE)]
EDIT: random reordering, after grouping:
mydf[,list(sum(x),sum(v)), by=y][sample(seq_len(length(y)),replace=FALSE)]
You can do something similar for grouping and random order before grouping, and it looks like it keeps the reordered order:
mydf[order(setNames(sample(unique(y)),unique(y))[y])] mydf[order(setNames(sample(unique(y)),unique(y))[y]),list(sum(x),sum(v)),by=y]
This is more transparent by adding a column first before the order.
mydf[,new.y := setNames(sample(unique(y)),unique(y))[y]][order(new.y)]
Destruction:
##a random ordering of the elements of y ##(set.seed is used here to get consistent results) set.seed(1); mydf[,{z <- unique(y);sample(z)}] # [1] "B" "E" "D" "c" "A" ##assigning names to the elements of y ##creating a 1-1 bijective function between the elements of y set.seed(1); mydf[,{z <- unique(y);setNames(sample(z),z)}] # AB c DE #"B" "E" "D" "c" "A" ##subsetting by y puts y through the map ##in effect every element of y is posing as an element of y, picked at random ##notice that the names (top row) are the original y ##the values (bottom row) are the mapped-to values # AB c DEAB c DEAB c DEAB c DE #"B" "E" "D" "c" "A" "B" "E" "D" "c" "A" "B" "E" "D" "c" "A" "B" "E" "D" "c" "A" ##ordering by this now orders by the mapped-to values set.seed(1); mydf[{z <- unique(y);order(setNames(sample(z),z)[y])}]
EDIT: Include Arunβs sentence in the commentary use setattr to set names:
mydf[{z <- unique(y); order(setattr(sample(z),'names',z)[y])}] mydf[{z <- unique(y); order(setattr(sample(z),'names',z)[y])},list(sum(x),sum(v)),by=y]