Сортировка списка нетривиальных элементов в R

В R у меня есть список нетривиальных объектов (они не простые объекты, такие как скаляры, которые, как можно ожидать, могут определять порядок для). Я хочу отсортировать список. Большинство языков позволяют программисту предоставить функцию или подобное, которое сравнивает пару элементов списка, которые передаются функции сортировки. Как я могу отсортировать список?

Ответ 1

Чтобы сделать это так просто, я могу сказать, что ваши объекты представляют собой списки с двумя элементами, имя и значение. Значение - числовое; что мы хотим сортировать. Вы можете представить, что у вас больше элементов и нужно делать что-то более сложное для сортировки.

Страница справки sort сообщает нам, что sort использует xtfrm; xtfrm в свою очередь говорит нам, что он будет использовать методы == и > для класса x[i].

Сначала я определяю объект, который я хочу сортировать:

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

Теперь, поскольку xtfrm работает с x[i], мне нужно определить функцию [, которая возвращает нужные элементы, но все же с правильным классом

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

Теперь нам нужны функции == и > для класса myobj; это потенциально может быть более умным, путем векторизации их должным образом; но для функции сортировки мы знаем, что мы будем проходить только в myobj длины 1, поэтому я просто использую первый элемент для определения отношений.

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

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

Теперь работает sort.

sort(xx)

Можно считать более правильным написать полную функцию Ops для вашего объекта; однако, чтобы просто сортировать, это, кажется, все, что вам нужно. См. Стр .89-90 в Venables/Ripley для получения дополнительной информации об этом, используя стиль S3. Кроме того, если вы можете легко написать функцию xtfrm для своих объектов, это будет проще и, скорее всего, быстрее.

Ответ 2

Функция 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

Ответ 3

Один из вариантов заключается в создании метода xtfrm для ваших объектов. Такие функции, как order, принимают несколько столбцов, которые работают в некоторых случаях. Существуют также специальные функции для конкретных случаев, таких как mixedsort в пакете gtools.