2011-09-22 61 views
10

在R中,我有一个非平凡对象的列表(它们不是像标量这样的简单对象,R可以预期能够定义一个顺序)。我想对列表进行排序。大多数语言允许程序员提供一个函数或类似的函数来比较传递给排序函数的一对列表元素。我如何整理我的列表?对R中非平凡元素的列表排序

+0

你能提供一个这个平凡的元素列表的片段,以便其他人了解你在说什么吗?提示在这里写一个可重现的问题:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Chase

回答

14

为了让这个过程尽可能简单,比如你的对象是带有两个元素的列表,一个名字和一个值。该值是一个数字;这就是我们想要排序的内容。你可以想象有更多的元素,并需要做一些更复杂的排序。

sort帮助页面告诉我们,sort使用xtfrm; xtfrm反过来告诉我们它将使用类的==>方法。

首先,我将定义,我要排序的对象:因为xtfrm作品在x[i]

xx <- lapply(c(3,5,7,2,4), function(i) list(name=LETTERS[i], value=i)) 
class(xx) <- "myobj" 

现在,我需要定义一个[函数返回所需的元素,但仍然有正确的类

`[.myobj` <- function(x, i) { 
    class(x) <- "list" 
    structure(x[i], class="myobj") 
} 

现在我们需要为myobj==>功能;通过适当地向量化这些可能会更聪明;但是对于排序函数,我们知道我们只会传递长度为1的myobj,所以我将使用第一个元素来定义关系。

`>.myobj` <- function(e1, e2) { 
    e1[[1]]$value > e2[[1]]$value 
} 

`==.myobj` <- function(e1, e2) { 
    e1[[1]]$value == e2[[1]]$value 
} 

现在sort只是工作。

sort(xx) 

为你的对象写一个完整的Ops函数可能被认为是更合适的;然而,只要排序,这似乎是你所需要的。请参阅Venables/Ripley的第89-90页关于使用S3风格进行此操作的更多详细信息。此外,如果您可以轻松地为对象编写函数,那将更简单,而且可能更快。

+0

谢谢亚伦。神奇的答案。 – Chris

+1

构建一个不常用的解决方案的工作比构造一个普通的R比特要花费很多工作:这些是'order'排序的两种用法,第一个值是:'xx [order(as.character(sapply(xx,“ [“,”value“)))]',然后在名字上:'xx [order(as。字符(sapply(xx,“[”,“name”)))]'没有任何引用类方法。 –

+0

@DWin是绝对正确的;如果你能做更聪明的事情,你应该! – Aaron

4

order函数将允许您确定字符或数字注释的排序顺序并断开与后续参数的关系。你需要对你想要的更具体。生成一个“非平凡对象”的例子,并在某个R对象中指定你想要的顺序。列出可能是最不矢量对象:

> slist <- list(cc=list(rr=1), bb=list(ee=2, yy=7), zz="ww") 
> slist[order(names(slist))] # alpha order on names() 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1  
$zz 
[1] "ww" 

slist[c("zz", "bb", "cc")] # an arbitrary ordering 
$zz 
[1] "ww" 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1 
1

一种选择是创建你的对象xtfrm方法。诸如order之类的函数会在多个列中使用多个列,这些列在某些情况下可用。对于gtools包中的mixedsort等特定情况,还有一些专用功能。