Sorting list of list of elements of a custom class in R?

半腔热情 提交于 2019-12-01 21:58:09
alexis_laz

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]])

I wanted to make use of internal and supposedly more efficient sort, but doesn't seem like this sort has facility to take custom comparison operator. So I ended up using implementation of quicksort to sort lists of lists at arbitrary index, assuming comparison exists between the elements at that index.

part_qsort <- function(l, idx, low, high) {
    lst <- l
    pivot <- lst[[high]][[idx]]
    i <- low - 1

    for(j in low:(high-1)) {
        if ((lst[[j]][[idx]] < pivot) || (lst[[j]][[idx]] == pivot)) {
            i <- i + 1
            swap(lst[[i]],lst[[j]])
        }
    }
    swap(lst[[(i+1)]],lst[[high]])
    eval.parent(substitute(l <- lst))
    return(i+1)
}

# recursive calls to quicksort
qsort <- function(l,idx,low,high) {
    if (low < high) {
        lst <- l
        pi <- part_qsort(lst,idx,low,high)
        qsort(lst, idx, low, pi-1)
        qsort(lst, idx, pi+1, high)
        eval.parent(substitute(l <- lst))
    }
}

Another thing to look into can be library("rlist") which seems to have a bunch of functions implemented on lists.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!