Как упорядочить мой фрейм данных лексикографически

У меня есть следующий фрейм данных

a = data.frame(a=c(1,2,3,4,5,6,7),b=c(1,2,3,10,12,21,4),c=c(1,2,10,11,"X","Y",3))
> a
  a  b  c
1 1  1  1
2 2  2  2
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3

Я хочу отсортировать весь фрейм данных в лексикографическом порядке, чтобы вывод (например, столбец "c") был похож на

> a[,"c"]
[1] 1  2  3 10 11  X  Y

Я пробовал, и я получаю другой ответ

indata <- a[do.call(order,a[,c("c","a","b")]),]
> indata[,"c"]
[1] 1  10 11 2  3  X  Y
Levels: 1 10 11 2 3 X Y

Я пробовал gtools, пакет mixorder и отлично работал в одном столбце:

> a[mixedorder(a$c),]
  a  b  c
1 1  1  1
2 2  2  2
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3

но это не сработает, если я включу несколько столбцов:

> a[with(a,order(mixedorder(c),mixedorder(b),mixedorder(a))),]
  a  b  c
1 1  1  1
2 2  2  2
4 4 10 11
5 5 12  X
6 6 21  Y
7 7  4  3
3 3  3 10

хотя я ожидаю:

  a  b  c
1 1  1  1
2 2  2  2
4 7  4  3
5 3  3 10
6 4 10 11
7 5 12  X
3 6 21  Y

person user1631306    schedule 09.10.2012    source источник
comment
Вы должны быть более четкими. Вы хотите отсортировать только столбец c или весь фрейм данных относительно столбцов c?   -  person joran    schedule 09.10.2012
comment
Я хочу отсортировать весь фрейм данных по c. Я дал [, c] для простоты понимания   -  person user1631306    schedule 09.10.2012
comment
Сообщение по теме: stackoverflow.com/q/19014531/680068   -  person zx8754    schedule 01.08.2019


Ответы (4)


Один из вариантов — использовать mixedorder() из пакета gtools.

library(gtools)
a[mixedorder(a$c),]
#   a  b  c
# 1 1  1  1
# 2 2  2  2
# 7 7  4  3
# 3 3  3 10
# 4 4 10 11
# 5 5 12  X
# 6 6 21  Y
person Josh O'Brien    schedule 09.10.2012
comment
Как бы я использовал несколько столбцов вместе для сортировки (сначала c, затем b, а затем a)? - person user1631306; 09.10.2012
comment
@ user1631306 Попробуйте arrange в пакете plyr. - person joran; 09.10.2012
comment
@user1631306 user1631306 -- В этом случае вы можете сделать это: a[with(a, order(mixedorder(c), b, a)),]. - person Josh O'Brien; 09.10.2012

Придерживаясь базы, вы можете сделать функцию самостоятельно:

a = data.frame(a=c(1,2,3,4,5,6,7),b=c(1,2,3,10,12,21,4),c=c(1,2,10,11,"X","Y",3))

SORTER_DEVICE <- function(x) {
    c(sort(as.numeric(na.omit(gsub("[a-zA-Z]", NA, x)))),
        sort(na.omit(gsub("[0-9]", NA, x))))
}
data.frame(apply(a, 2, SORTER_DEVICE))
person Tyler Rinker    schedule 09.10.2012

К сожалению, смешанная сортировка (пока) не поддерживает сортировку по нескольким столбцам. Итак, вам нужно реализовать это самостоятельно, например, так:

a[order(sub("[0-9]+", "", a$c),
        as.numeric(sub("[[:alpha:]]*([[:digit:]]*)", '\\1', a$c)),
        as.numeric(a$b),
        as.numeric(a$a)), ]

Во-первых, в алфавитно-цифровом порядке data.frame сортируется с помощью a$c, а для ситуаций связи (которые на самом деле не существуют в вашем data.frame 'a') используются a$b и a$a.

Выход:

  a  b  c
1 1  1  1
2 2  2  2
7 7  4  3
3 3  3 10
4 4 10 11
5 5 12  X
6 6 21  Y

PS: это было написано Дэвидом Винсемиусом в этом сообщении как ответ на аналогичный вопрос.

person gkcn    schedule 14.08.2013

Предположим, что это имена хромосом человека, chr1...chr22, chrX, chrY. Мы можем преобразовать их в числовые, а затем использовать порядок:

# convert to numeric
a$chromN <- as.integer(ifelse(a$c == "X", "23", ifelse(a$c == "Y", "24", a$c)))

# now sort as usual:
a[ order(a$chromN), ]

#   a  b  c chromN
# 1 1  1  1      1
# 3 3  3 10      2
# 4 4 10 11      3
# 2 2  2  2      4
# 7 7  4  3      5
# 5 5 12  X     23
# 6 6 21  Y     24
person zx8754    schedule 01.08.2019