R:基于因子拆分数据,添加排名列并提取

时间:2015-06-29 14:49:32

标签: r

我仍然无法知道如何访问拆分数据的不同元素。这是我的问题: 我有一个数据集,我想根据列(State)进行拆分。我希望为每个子集的数据添加一个排名列。这是我写作的一部分。 我的数据集有2列,医院,州,结果。对于每个州,我想添加一个' Rank'根据结果​​对数据进行排名的列;最低结果将排名第1,最高结果将排在最后。

如何使用split,sapply / lapply来执行此操作?有没有更好的方法,比如使用"安排"? 我的主要问题是,当我使用这些方法中的任何一种时,我不知道如何访问拆分或排列数据的每个元素。 这是我的数据集的样子: 医院状况结果。行线在这里并不重要。

                           Hospital State Outcome 
 1 SOUTHEAST ALABAMA MEDICAL CENTER    AL    14.3
 2    MARSHALL MEDICAL CENTER SOUTH    AL    18.5
 3   ELIZA COFFEE MEMORIAL HOSPITAL    TX    18.1
 7                ST VINCENT'S EAST    TX    17.7
 8   DEKALB REGIONAL MEDICAL CENTER    AL    18.0
 9    SHELBY BAPTIST MEDICAL CENTER    AL    15.9

期望的结果将是

                           Hospital State Outcome Rank
 1 SOUTHEAST ALABAMA MEDICAL CENTER    AL    14.3    1
 2 SHELBY BAPTIST MEDICAL CENTER       AL    15.9    2
 3 DEKALB REGIONAL MEDICAL CENTER      AL    18.0    3               
 4 MARSHALL MEDICAL CENTER SOUTH       AL    18.5    4 
 5 ST VINCENT'S EAST                   TX    17.7    1 
 6 ELIZA COFFEE MEMORIAL HOSPITAL      TX    18.1    2 

提前致谢。

4 个答案:

答案 0 :(得分:3)

由于字符串变量中的所有空格,OP的示例很难读入R.

这是一个更简单的例子:

set.seed(1)
DF <- data.frame(id=rep(1:2,sample(5,2))); DF$v <- runif(nrow(DF))*100
#   id        v
# 1  A 57.28534
# 2  A 90.82078
# 3  B 20.16819
# 4  B 89.83897
# 5  B 94.46753
# 6  B 66.07978
# 7  B 62.91140

这是一个不使用任何软件包的解决方案:

DF$r <- ave(DF$v,DF$id,FUN=rank)
#   id        v r
# 1  A 57.28534 1
# 2  A 90.82078 2
# 3  B 20.16819 1
# 4  B 89.83897 4
# 5  B 94.46753 5
# 6  B 66.07978 3
# 7  B 62.91140 2

最后,按州内排名顺序排序:

DF[order(DF$id,DF$r),]
#   id        v r
# 1  A 57.28534 1
# 2  A 90.82078 2
# 3  B 20.16819 1
# 7  B 62.91140 2
# 6  B 66.07978 3
# 4  B 89.83897 4
# 5  B 94.46753 5

如果您在排名中有关联,请阅读rank的文档并确定您希望如何处理这些关系。 dplyrdata.table包(在其他答案中提到)也具有很好的处理关系的功能,例如“dense rank”的概念。

答案 1 :(得分:2)

你可以试试这个

library(data.table)
setDT(dat)[, myrank := rank(Outcome), by = State]
dat[,.SD[order(myrank)], by=State]

#      State                         Hospital Outcome myrank
#1:    AL SOUTHEAST ALABAMA MEDICAL CENTER    14.3      1
#2:    AL    SHELBY BAPTIST MEDICAL CENTER    15.9      2
#3:    AL   DEKALB REGIONAL MEDICAL CENTER    18.0      3
#4:    AL    MARSHALL MEDICAL CENTER SOUTH    18.5      4
#5:    TX                  ST VINCENT EAST    17.7      1
#6:    TX   ELIZA COFFEE MEMORIAL HOSPITAL    18.1      2

或使用ddply

library(plyr)
ddply(dat, .(State), function(x){x$myrank = rank(x$Outcome); x[order(x$myrank),]})

#                          Hospital State Outcome myrank
#1 SOUTHEAST ALABAMA MEDICAL CENTER    AL    14.3      1
#2    SHELBY BAPTIST MEDICAL CENTER    AL    15.9      2
#3   DEKALB REGIONAL MEDICAL CENTER    AL    18.0      3
#4    MARSHALL MEDICAL CENTER SOUTH    AL    18.5      4
#5                  ST VINCENT EAST    TX    17.7      1
#6   ELIZA COFFEE MEMORIAL HOSPITAL    TX    18.1      2

答案 2 :(得分:2)

dplyr包为这类问题提供了一个非常优雅的解决方案。我使用mtcars数据作为示例:

library(dplyr)

mtcars %>%
  group_by(cyl) %>%
  mutate(rank = row_number(mpg))

答案 3 :(得分:1)

您可以使用by

do.call(
    rbind, 
    by(d, list(State = d$State), function(x) { x$Rank <- order(x$Outcome); x[order(x$Rank), ] }))

其中d是您的原始数据。