Сортировка столбца данных по каждому столбцу
Предположим, у меня есть фрейм данных с 3 столбцами (name
, y
, sex
), где name
- это символ, y
- это числовое значение, а sex
- это фактор.
sex<-c("M","M","F","M","F","M","M","M","F")
x<-c("MARK","TOM","SUSAN","LARRY","EMMA","LEONARD","TIM","MATT","VIOLET")
name<-as.character(x)
y<-rnorm(9,8,1)
score<-data.frame(x,y,sex)
score
name y sex
1 MARK 6.767086 M
2 TOM 7.613928 M
3 SUSAN 7.447405 F
4 LARRY 8.040069 M
5 EMMA 8.306875 F
6 LEONARD 8.697268 M
7 TIM 10.385221 M
8 MATT 7.497702 M
9 VIOLET 10.177969 F
Если бы я хотел заказать его y
я бы использовал:
score[order(score$y),]
x y sex
1 MARK 6.767086 M
3 SUSAN 7.447405 F
8 MATT 7.497702 M
2 TOM 7.613928 M
4 LARRY 8.040069 M
5 EMMA 8.306875 F
6 LEONARD 8.697268 M
9 VIOLET 10.177969 F
7 TIM 10.385221 M
Пока все хорошо... Имена держат правильную оценку, НО как я могу изменить порядок, чтобы уровни M и F не смешивались. Мне нужно заказать и в то же время держать уровни факторов отдельно.
Наконец, я хотел бы сделать шаг вперед, чтобы задействовать символ, пример не помогает, но что, если бы были связаны значения y
и мне пришлось бы сделать заказ снова в пределах фактора (например, TIM и TOM получили 8,4, и мне нужно назначить алфавитный порядок).
Я думал о функции, но она создает список и на самом деле не помогает. Я думаю, что должна быть какая-то функция, подобная этой, для применения к фреймам данных и получения фреймов данных в качестве возврата.
ЧТОБЫ ОЧИСТИТЬ ТОЧКУ:
sep<-split(score,score$sex)
sep$M<-sep$M[order(sep$M[,2]),]
sep$M
x y sex
1 MARK 6.767086 M
8 MATT 7.497702 M
2 TOM 7.613928 M
4 LARRY 8.040069 M
6 LEONARD 8.697268 M
7 TIM 10.385221 M
sep$F<-sep$F[order(sep$F[,2]),]
sep$F
x y sex
3 SUSAN 7.447405 F
5 EMMA 8.306875 F
9 VIOLET 10.177969 F
merged<-rbind(sep$M,sep$F)
merged
x y sex
1 MARK 6.767086 M
8 MATT 7.497702 M
2 TOM 7.613928 M
4 LARRY 8.040069 M
6 LEONARD 8.697268 M
7 TIM 10.385221 M
3 SUSAN 7.447405 F
5 EMMA 8.306875 F
9 VIOLET 10.177969 F
Я знаю, как это сделать, если у меня есть 2 или 3 фактора. Но что, если бы у меня были серьезные уровни факторов, скажем, 20, я должен написать цикл for
?
Ответы
Ответ 1
order
принимает несколько аргументов и делает именно то, что вы хотите:
with(score, score[order(sex, y, x),])
## x y sex
## 3 SUSAN 6.636370 F
## 5 EMMA 6.873445 F
## 9 VIOLET 8.539329 F
## 6 LEONARD 6.082038 M
## 2 TOM 7.812380 M
## 8 MATT 8.248374 M
## 4 LARRY 8.424665 M
## 7 TIM 8.754023 M
## 1 MARK 8.956372 M
Ответ 2
Вот краткое изложение всех методов, упомянутых в других ответах/комментариях (для обслуживания будущих поисковиков). Я добавил метод сортировки data.table.
# Base R
do.call(rbind, by(score, score$sex, function(x) x[order(x$y),]))
with(score, score[order(sex, y, x),])
score[order(score$sex,score$x),]
# Using plyr
arrange(score, sex,y)
ddply(score, c('sex', 'y'))
# Using `data.table`
library("data.table")
score_dt <- setDT(score)
# setting a key works just fine
setkey(score_dt,sex,x)
print(score_dt)
# Explicitly ordering using i
score_dt[i=order(sex,x),]
Вот еще один вопрос, который касается того же
Ответ 3
Я думаю, что должна быть какая-то функция, например, для применения в кадрах данных и получить данные в качестве возврата
Да, есть:
library(plyr)
ddply(score, c('y', 'sex'))
Ответ 4
Мне кажется, что вы пытаетесь сделать заказ по партитуре среди самцов и женщин и вернуть объединенный фрейм данных отсортированных самцов и отсортированных женщин.
Вы правы, что by(score, score$sex, function(x) x[order(x$y),])
возвращает список отсортированных кадров данных, один для мужчин и один для женщин. Вы можете использовать do.call
с помощью функции rbind
для объединения этих кадров данных в один конечный кадр данных:
do.call(rbind, by(score, score$sex, function(x) x[order(x$y),]))
# x y sex
# F.5 EMMA 7.526866 F
# F.9 VIOLET 8.182407 F
# F.3 SUSAN 9.677511 F
# M.4 LARRY 6.929395 M
# M.8 MATT 7.970015 M
# M.7 TIM 8.297137 M
# M.6 LEONARD 8.845588 M
# M.2 TOM 9.035948 M
# M.1 MARK 10.082314 M