按因子对数据框列进行排序

时间:2014-01-23 02:08:33

标签: r sorting r-factor

我有一个包含3列(nameysex)的数据框,其中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循环吗?

4 个答案:

答案 0 :(得分:20)

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

答案 1 :(得分:9)

以下是其他答案/评论中提到的所有方法的摘要(为未来的搜索者提供服务)。我添加了一个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),]

Here is Another question that deals with the same

答案 2 :(得分:3)

  

我认为必须有类似的功能才能应用于数据帧   并获取数据框作为返回

是的,有:

library(plyr)

ddply(score, c('y', 'sex'))

答案 3 :(得分:2)

听起来我觉得你试图按照男性和女性的分数进行排序,并返回已排序的男性和排序女性的组合数据框。

你是对的by(score, score$sex, function(x) x[order(x$y),])返回一个排序数据框列表,一个用于男性,一个用于女性。您可以将do.callrbind函数结合使用,将这些数据框合并为一个最终数据框:

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