В 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
.