如何在R中按组对列进行排序

14

我有一个数据框(假设为"df"),看起来像下面这样:

Hospital.Name | State | Mortality.Rate
'hospital_1'   | 'AA'  | 0.2
'hospital_2'   | 'AA'   | 0.3
'hospital_3'   | 'BB'  | 0.3
'hospital_4'   | 'CC'  | 0.5

(医院名称是唯一的)

现在我想按“州”对“死亡率”分组排序,即对某个州内的比率进行排序。如果比率相同,则使用“医院名称”来解决并列。

我想到了“order()”和“tapply()”函数。我编写的代码如下:

tapply(df$Mortality.Rate, df$State, order, df$Hospital.Name, na.last=NA)

然而,出现了一个错误“argument length differ”。当将“Rate”切片应用于“order”函数时,order的第二个参数(即df $Hospital.Name)没有被切片。

我该如何将第二个参数(用于解决排序中的平局)传递给tapply()或是否有其他方法?

6个回答

16

在基础R中,您可以向order()提供多个参数,并使用后续参数来打破较早变量中的平局,例如:

df[order(df$State,df$Mortality.Rate,df$Hospital.Name),]

1
不需要在 Mortality.Rate 周围加引号。 - Konrad Rudolph
Hospital.Name 部分在哪里?” - David Arenburg
@Jthorpe 没错,但这是一种“货物崇拜编程”(cargo cult programming)的形式。 - Konrad Rudolph
@KonradRudolph 我只是懒得去掉我从 OP 复制/粘贴的引号,而不是试图解决引号问题... - Jthorpe
我花了一些时间才明白。这是一个不错且清晰的解决方案。谢谢。 - Zelong

10

你可以在 dplyr 中完成它:

df %>% group_by(State) %>% arrange(Mortality.Rate, Hospital.Name) 

非常感谢。但是在找到解决方案时,我需要坚持使用基本的R语言(很抱歉在我的问题中没有提到这一点)。我会看一下这个包。谢谢。 - Zelong

4

您可以使用dplyr来完成此操作。首先,提供一些示例数据:

library("dplyr")
hospital_name <- sample(c("hospital_1", "hospital_2", "hospital_3"), 10,
                        replace = TRUE)
state <- sample(letters[1:3], 10, replace = TRUE)
mortality_rate <- runif(10)

df <- data_frame(hospital_name, state, mortality_rate)

按州分组,然后按列排列。

df %>% 
  group_by(state) %>% 
  arrange(mortality_rate, hospital_name)

生成这样的结果,其中各州被分组,每个州内的死亡率被排序。
## Source: local data frame [10 x 3]
## Groups: state
## 
##    hospital_name state mortality_rate
## 1     hospital_1     b     0.15293591
## 2     hospital_1     b     0.37417167
## 3     hospital_1     b     0.54561856
## 4     hospital_3     c     0.02487033
## 5     hospital_1     c     0.09937557
## 6     hospital_1     c     0.35666087
## 7     hospital_3     c     0.39663460
## 8     hospital_2     c     0.53064144
## 9     hospital_3     c     0.76015632
## 10    hospital_3     c     0.76801890

如果没有 group_by(),你只会得到从最小到最大的死亡率:

df %>%
  arrange(mortality_rate)

## Source: local data frame [10 x 3]
## 
##    hospital_name state mortality_rate
## 1     hospital_3     c     0.02487033
## 2     hospital_1     c     0.09937557
## 3     hospital_1     b     0.15293591
## 4     hospital_1     c     0.35666087
## 5     hospital_1     b     0.37417167
## 6     hospital_3     c     0.39663460
## 7     hospital_2     c     0.53064144
## 8     hospital_1     b     0.54561856
## 9     hospital_3     c     0.76015632
## 10    hospital_3     c     0.76801890

2
这里的答案与@jalapic类似。我不知道是否需要group_by,arrange(df, State, Hospital.Name, Mortality.Rate) - akrun
是的,需要使用 group_by 来在各个状态内进行排序,而不是整个数据框中进行排序。请参阅 ?dplyr::group_by - Lincoln Mullen
1
你能展示一些例子来说明这个会有不同吗?我尝试了你的一个例子,使用了 set.seed(24)。使用或不使用 groupby 得到了相同的输出。 - akrun
根据您的建议编辑了答案。 - Lincoln Mullen
1
我认为如果操作者只需要排序,仅使用“arrange”会更快。 - akrun
显示剩余2条评论

3
如果我们已经在加载指定操作的包,这里有一个(data.table)包,可以通过使用setordersetkey函数,按引用对数据进行排序(而无需复制它并使用<-)。
library(data.table)
setorder(setDT(df), State, Mortality.Rate, Hospital.Name)

虽然你可以模仿基本的R语法,在创建副本时对数据进行排序(但速度会更快,因为 data.table在幕后调用了其forder函数)。

setDT(df)[order(State, Mortality.Rate, Hospital.Name)]

如何在订购时以组列作为参考? - Paulo E. Cardoso

1

1
这不是和@Jthorpe的答案类似吗? - akrun
就像akrun所说的那样,还有Hospital.Name部分在哪里? - David Arenburg

0

给变量"result"赋值。同时假设您想找到每个州的平均死亡率

result <- df %<%
                 arrange(Mortality.Rate) %<%
                 order_by(State) %<%
                 summarize(mean(Mortality.Rate)
view(result)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接