在R中对自定义类的元素列表进行排序的列表? [英] Sorting list of list of elements of a custom class in R?

查看:302
本文介绍了在R中对自定义类的元素列表进行排序的列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义类对象(元组列表). 我也定义了<.myclass >.myclass==.myclass.

现在我有一个

a <- obj1 # of myclass
b <- obj2 # of myclass
c <- obj3 # of myclass
L <- list(list(a,12,1),list(b,215,23),list(c,21,9))

我想对索引1上的L进行排序,即我有b < c < a,那么我想按list(list(b,215,23),list(c,21,9),list(a,12,1))

的形式对L进行排序

我该如何实现?

在搜索中,我发现了如何对特定索引进行排序,并使用它编写了以下函数

magic_sort <- function(lst, sortind, dec = T) {
    return(lst[order(sapply(lst,'[[',sortind), decreasing = dec)])
}

但是当我给它赋予索引1时,要对obj1进行排序,它将失败

> magic_sort(L,1)
Error in order(sapply(lst, "[[", sortind), decreasing = dec) : 
    unimplemented type 'list' in 'orderVector1'

对此有任何解决方法吗?总的来说,基于比较运算符的自定义定义,我是否可以具有排序,最小值等功能?

以下可能会帮助您更好地理解结构: http://pastebin.com/0M7JRLTu

library("sets")

a <- list()
class(a) <- "dfsc"
a[[1]] <- tuple(1L, 2L, "C", "a", "B")

b <- list()
class(b) <- "dfsc"
b[[1]] <- tuple(1L, 2L, "A", "b", "B")

c <- list()
class(c) <- "dfsc"
c[[1]] <- tuple(1L, 2L, "A", "a", "B")

L <- list()
L[[1]] <- list(a, 12, 132)
L[[2]] <- list(b, 21, 21)
L[[3]] <- list(c, 32, 123)

`<.dfsc` <- function(c1, c2) {
    return(lt_list(toList(c1),toList(c2)))
}

`==.dfsc` <- function(c1, c2) {
    return(toString(c1) == toString(c2))
}

`>.dfsc` <- function(c1, c2) {
    return(!((c1 < c2) || (c1 == c2)))
}

lt_list <- function(l1, l2) {
    n1 <- length(l1)
    n2 <- length(l2)
    j = 1
    while(j <= n1 && j <= n2) {
        if (l1[[j]] != l2[[j]]) {
            return (l1[[j]] < l2[[j]])
        }
        j = j + 1
    }
    return(n1 < n2)
}

toString.dfsc <- function(x) {
    code_string <- ""
    #for(ii in x[[1]]) {
    for(ii in x) {   
        code_string <- paste(code_string,"(",ii[[1]],",",ii[[2]],",",ii[[3]],",",ii[[4]],",",ii[[5]],")", sep = "")
    }
    return(code_string)
}

现在我希望将L设置为list(list(c,_,_),list(b,_,_),list(a,_,_))

解决方案

来自亚伦的答案确切地说明了什么需要在class ed对象上应用自定义的sort.正如Roland所指出的那样,您实际上实际上需要sort"L",因此,这就是应该重点关注自定义sort的地方.为了提供灵活性,指定在sort上"L"的元素的哪个索引,一种方法是在"L"上存储一个额外的attr:

将"L"转到适当的对象:

class(L) = "myclass"
attr(L, "sort_ind") = 1L

需要定义

Ops方法(提取数据的相关元素):

"<.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind") ## also check if 'x' and 'y' have the same 'attr(, "sort_ind")'
    x[[1]][[i]] < y[[1]][[i]] 
}
"==.myclass" = function(x, y) 
{
     i = attr(x, "sort_ind")
     x[[1]][[i]] == y[[1]][[i]] 
}
">.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind")
    x[[1]][[i]] > y[[1]][[i]] 
}

和子集方法:

"[.myclass" = function(x, i) 
{
    y = .subset(x, i)
    attributes(y) = attributes(x)
    return(y)
}

必须定义上述方法(可能是"<"除外),因为对sort/order的调用最终将调用rank,而该rank需要.gt以便相应地子集每个元素和比较. 最后,获得酱的获取/设置功能:

sort_ind = function(x) attr(x, "sort_ind")
"sort_ind<-" = function(x, value) 
{
    attr(x, "sort_ind") = value
    return(x)
}

并且:

order(L)
#[1] 3 2 1
sort_ind(L) = 3
order(L)
#[1] 2 3 1

也可以创建sort的方法来包装以上所有内容:

sort.myclass = function(x, sort_ind = attr(x, "sort_ind"), ...)
{
    sort_ind(x) = sort_ind
    NextMethod()
}

sort(L)
sort(L, sort_ind = 1)

(我假设您的toList函数看起来像toList = function(x) x[[1L]]一样)

I have a custom class object (list of tuples). I have defined <.myclass >.myclass and ==.myclass on it as well.

Now I have a

a <- obj1 # of myclass
b <- obj2 # of myclass
c <- obj3 # of myclass
L <- list(list(a,12,1),list(b,215,23),list(c,21,9))

I want to sort L, on index 1. i.e. I have b < c < a then, I want sorted L in this form list(list(b,215,23),list(c,21,9),list(a,12,1))

How do I achieve this?

In my searches, I found how to sort on particular index, and using that I wrote the following function

magic_sort <- function(lst, sortind, dec = T) {
    return(lst[order(sapply(lst,'[[',sortind), decreasing = dec)])
}

But when I give index 1 to it, to sort on obj1, it fails with

> magic_sort(L,1)
Error in order(sapply(lst, "[[", sortind), decreasing = dec) : 
    unimplemented type 'list' in 'orderVector1'

Is there any fix for this? In general, can I have functions like sort, minimum and so on, based on custom definition of comparison operators?

Edit: Following perhaps will help understand the structure better: http://pastebin.com/0M7JRLTu

Edit 2:

library("sets")

a <- list()
class(a) <- "dfsc"
a[[1]] <- tuple(1L, 2L, "C", "a", "B")

b <- list()
class(b) <- "dfsc"
b[[1]] <- tuple(1L, 2L, "A", "b", "B")

c <- list()
class(c) <- "dfsc"
c[[1]] <- tuple(1L, 2L, "A", "a", "B")

L <- list()
L[[1]] <- list(a, 12, 132)
L[[2]] <- list(b, 21, 21)
L[[3]] <- list(c, 32, 123)

`<.dfsc` <- function(c1, c2) {
    return(lt_list(toList(c1),toList(c2)))
}

`==.dfsc` <- function(c1, c2) {
    return(toString(c1) == toString(c2))
}

`>.dfsc` <- function(c1, c2) {
    return(!((c1 < c2) || (c1 == c2)))
}

lt_list <- function(l1, l2) {
    n1 <- length(l1)
    n2 <- length(l2)
    j = 1
    while(j <= n1 && j <= n2) {
        if (l1[[j]] != l2[[j]]) {
            return (l1[[j]] < l2[[j]])
        }
        j = j + 1
    }
    return(n1 < n2)
}

toString.dfsc <- function(x) {
    code_string <- ""
    #for(ii in x[[1]]) {
    for(ii in x) {   
        code_string <- paste(code_string,"(",ii[[1]],",",ii[[2]],",",ii[[3]],",",ii[[4]],",",ii[[5]],")", sep = "")
    }
    return(code_string)
}

Now I want the L desired to be list(list(c,_,_),list(b,_,_),list(a,_,_))

解决方案

This answer from Aaron demonstrates, exactly, what is needed to apply a customized sort on a classed object. As Roland notes, you -actually- need to sort "L" and, thus, that is where the focus on custom sort should be. To provide flexibility specifying on which index of "L" 's elements to sort, a way would be to store an extra attr on "L":

Turn "L" to an appropriate object:

class(L) = "myclass"
attr(L, "sort_ind") = 1L

Ops methods need to be defined (extract the relevant element of your data):

"<.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind") ## also check if 'x' and 'y' have the same 'attr(, "sort_ind")'
    x[[1]][[i]] < y[[1]][[i]] 
}
"==.myclass" = function(x, y) 
{
     i = attr(x, "sort_ind")
     x[[1]][[i]] == y[[1]][[i]] 
}
">.myclass" = function(x, y) 
{
    i = attr(x, "sort_ind")
    x[[1]][[i]] > y[[1]][[i]] 
}

And a subset method:

"[.myclass" = function(x, i) 
{
    y = .subset(x, i)
    attributes(y) = attributes(x)
    return(y)
}

The above methods are necessary (perhaps, except "<") to be defined since a call to sort/order will end up calling rank which needs .gt in order to subset accordingly each element and compare. Finally, a get/set function for sauce:

sort_ind = function(x) attr(x, "sort_ind")
"sort_ind<-" = function(x, value) 
{
    attr(x, "sort_ind") = value
    return(x)
}

And:

order(L)
#[1] 3 2 1
sort_ind(L) = 3
order(L)
#[1] 2 3 1

A method for sort can be, also, created to wrap all the above:

sort.myclass = function(x, sort_ind = attr(x, "sort_ind"), ...)
{
    sort_ind(x) = sort_ind
    NextMethod()
}

sort(L)
sort(L, sort_ind = 1)

(I assumed that your toList function would look like something toList = function(x) x[[1L]])

这篇关于在R中对自定义类的元素列表进行排序的列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆