2013-06-19 33 views
4

我有一个变量,我想分组。这很容易。但是,我希望结果表以随机顺序列出其行。我其实想要做的是更复杂一点。但让我给你看一个简化版本。如何按data.table中的随机顺序对变量和列表进行分组?

mydf = data.table(
    x = rep(1:4, each = 5), 
    y = rep(c('A', 'B','c','D', 'E'), times = 2), 
    v = rpois(20, 30) 
) 

mydf[,list(sum(x),sum(v)), by=y] 
mydf[,list(sum(x),sum(v)), by=list(y=sample(y))] 

#to list all the raw data in order of y 


mydf[,list(x,v), by=y] 
mydf[,list(x,v), by=list(y=sample(y))] 

如果你看一下合成的输出,你会发现,在Y确实是随机的顺序,但它已经成为从在它的行中的数据错乱。

我该怎么办?

+1

为什么不能正常返回'data.table'然后做你的随机排序? – Justin

+0

@Justin,随机排序返回的表将适用于显示总和的表,但它不适用于下一组想要列出原始数据,但仍然希望按y组列出的下一组数据 – Farrel

回答

5

我会做的操作,然后顺序随机:

mydf[,list(x,v),by=y][sample(seq_len(nrow(mydf)),replace=FALSE)] 

编辑:随机重新排序,分组后:

mydf[,list(sum(x),sum(v)), by=y][sample(seq_len(length(y)),replace=FALSE)] 

您可以分组之前做这样的事情,以组和随机顺序,看起来它确实保留了改变的顺序:

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] 

#perhaps more readable: 
mydf[{z <- unique(y); order(setNames(sample(z),z)[y])}] 
mydf[{z <- unique(y); order(setNames(sample(z),z)[y])},list(sum(x),sum(v)),by=y] 

这是更多在订购前先添加一列即可透明。

mydf[,new.y := setNames(sample(unique(y)),unique(y))[y]][order(new.y)] 

其分解:

##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)}] 
# A B c D E 
#"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 
# A B c D E A B c D E A B c D E A B c D E 
#"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])}] 

编辑:结合在评论Arun的建议,使用setattr设置名称:

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] 
+0

该代码仅适用于以随机顺序返回原始原始数据。但是,我希望特定y的所有行(随机排列)都列在一起。 – Farrel

+0

@Farrel请参阅编辑。 –

+0

它的作品,但我几乎不明白你做了什么。什么是'setNames'在做什么?它似乎是随机分配y的每个值与y的不同值。然后它创建了一个对Y的排列,并将该向量的数字作为X中的i值[i] – Farrel

2

我想这是你”重新寻找...?

mydf[,.SD[sample(.N)],by=y] 

通过@ BlueMagister的第二个解决方案的启发,这里的随机化第一种方式:

mydf[sample(nrow(mydf)),.SD,by=y] 

在这里,使用keyby代替by如果希望组按字母顺序显示。

相关问题