1. 什么是排序?

排序就是按照某个变量的大小或顺序重新排列数据。

在R语言里,排序常见场景有:


2. 创建示例数据

student <- data.frame(
  id = 1:8,
  name = c("A", "B", "C", "D", "E", "F", "G", "H"),
  class = c("二班", "一班", "三班", "一班", "二班", "三班", "一班", "二班"),
  gender = c("女", "男", "男", "女", "男", "女", "男", "女"),
  score = c(85, 92, 78, 88, 95, 70, 82, 90),
  date = c("2024-03-01", "2024-01-15", "2024-02-20", "2024-01-10",
           "2024-03-05", "2024-02-01", "2024-01-25", "2024-03-10")
)

student
##   id name class gender score       date
## 1  1    A  二班     女    85 2024-03-01
## 2  2    B  一班     男    92 2024-01-15
## 3  3    C  三班     男    78 2024-02-20
## 4  4    D  一班     女    88 2024-01-10
## 5  5    E  二班     男    95 2024-03-05
## 6  6    F  三班     女    70 2024-02-01
## 7  7    G  一班     男    82 2024-01-25
## 8  8    H  二班     女    90 2024-03-10

查看数据结构:

str(student)
## 'data.frame':    8 obs. of  6 variables:
##  $ id    : int  1 2 3 4 5 6 7 8
##  $ name  : chr  "A" "B" "C" "D" ...
##  $ class : chr  "二班" "一班" "三班" "一班" ...
##  $ gender: chr  "女" "男" "男" "女" ...
##  $ score : num  85 92 78 88 95 70 82 90
##  $ date  : chr  "2024-03-01" "2024-01-15" "2024-02-20" "2024-01-10" ...

现在 date 还是字符型,我们先把它转成日期型:

student$date <- as.Date(student$date)

str(student)
## 'data.frame':    8 obs. of  6 variables:
##  $ id    : int  1 2 3 4 5 6 7 8
##  $ name  : chr  "A" "B" "C" "D" ...
##  $ class : chr  "二班" "一班" "三班" "一班" ...
##  $ gender: chr  "女" "男" "男" "女" ...
##  $ score : num  85 92 78 88 95 70 82 90
##  $ date  : Date, format: "2024-03-01" "2024-01-15" ...

3. 基础R排序:sort()

sort() 主要用于排序一个向量。

例如排序分数:

score <- c(85, 92, 78, 88, 95, 70, 82, 90)

sort(score)
## [1] 70 78 82 85 88 90 92 95

默认是从小到大,也就是升序。


4. 从大到小排序

使用参数:

decreasing = TRUE
sort(score, decreasing = TRUE)
## [1] 95 92 90 88 85 82 78 70

解释:

写法 含义
sort(score) 从小到大
sort(score, decreasing = TRUE) 从大到小

5. sort() 只能排序单个向量

例如:

sort(student$score)
## [1] 70 78 82 85 88 90 92 95

这样只能得到排序后的分数:

70 78 82 85 88 90 92 95

但是它不会把整个数据框的行一起移动。

如果我们要按照分数排序整个数据框,要用:

order()

6. 基础R排序数据框:order()

order() 返回的是排序后的位置编号。

先看一个简单例子:

student$score
## [1] 85 92 78 88 95 70 82 90
order(student$score)
## [1] 6 3 7 1 4 8 2 5

解释:

order(student$score) 不是直接返回排序后的分数,而是返回:

如果要把 score 从小到大排列,应该按照哪些行号取数据。


7. 按分数从低到高排序

student_by_score <- student[order(student$score), ]

student_by_score
##   id name class gender score       date
## 6  6    F  三班     女    70 2024-02-01
## 3  3    C  三班     男    78 2024-02-20
## 7  7    G  一班     男    82 2024-01-25
## 1  1    A  二班     女    85 2024-03-01
## 4  4    D  一班     女    88 2024-01-10
## 8  8    H  二班     女    90 2024-03-10
## 2  2    B  一班     男    92 2024-01-15
## 5  5    E  二班     男    95 2024-03-05

解释:

student[order(student$score), ]

含义是:

按照 score 从小到大的行顺序,重新排列整个 student 数据框。


8. 按分数从高到低排序

方法一:使用负号 -

student_by_score_desc <- student[order(-student$score), ]

student_by_score_desc
##   id name class gender score       date
## 5  5    E  二班     男    95 2024-03-05
## 2  2    B  一班     男    92 2024-01-15
## 8  8    H  二班     女    90 2024-03-10
## 4  4    D  一班     女    88 2024-01-10
## 1  1    A  二班     女    85 2024-03-01
## 7  7    G  一班     男    82 2024-01-25
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01

方法二:使用 decreasing = TRUE

student_by_score_desc2 <- student[order(student$score, decreasing = TRUE), ]

student_by_score_desc2
##   id name class gender score       date
## 5  5    E  二班     男    95 2024-03-05
## 2  2    B  一班     男    92 2024-01-15
## 8  8    H  二班     女    90 2024-03-10
## 4  4    D  一班     女    88 2024-01-10
## 1  1    A  二班     女    85 2024-03-01
## 7  7    G  一班     男    82 2024-01-25
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01

两种方法都可以。

常用写法:

student[order(-student$score), ]

9. 按日期排序

因为 date 已经是 Date 类型,所以可以直接排序。

9.1 日期从早到晚

student_by_date <- student[order(student$date), ]

student_by_date
##   id name class gender score       date
## 4  4    D  一班     女    88 2024-01-10
## 2  2    B  一班     男    92 2024-01-15
## 7  7    G  一班     男    82 2024-01-25
## 6  6    F  三班     女    70 2024-02-01
## 3  3    C  三班     男    78 2024-02-20
## 1  1    A  二班     女    85 2024-03-01
## 5  5    E  二班     男    95 2024-03-05
## 8  8    H  二班     女    90 2024-03-10

9.2 日期从晚到早

student_by_date_desc <- student[order(student$date, decreasing = TRUE), ]

student_by_date_desc
##   id name class gender score       date
## 8  8    H  二班     女    90 2024-03-10
## 5  5    E  二班     男    95 2024-03-05
## 1  1    A  二班     女    85 2024-03-01
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01
## 7  7    G  一班     男    82 2024-01-25
## 2  2    B  一班     男    92 2024-01-15
## 4  4    D  一班     女    88 2024-01-10

也可以写:

student_by_date_desc2 <- student[order(-as.numeric(student$date)), ]

student_by_date_desc2
##   id name class gender score       date
## 8  8    H  二班     女    90 2024-03-10
## 5  5    E  二班     男    95 2024-03-05
## 1  1    A  二班     女    85 2024-03-01
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01
## 7  7    G  一班     男    82 2024-01-25
## 2  2    B  一班     男    92 2024-01-15
## 4  4    D  一班     女    88 2024-01-10

但是日期排序更推荐:

order(student$date, decreasing = TRUE)

10. 按字符排序

例如按姓名排序:

student_by_name <- student[order(student$name), ]

student_by_name
##   id name class gender score       date
## 1  1    A  二班     女    85 2024-03-01
## 2  2    B  一班     男    92 2024-01-15
## 3  3    C  三班     男    78 2024-02-20
## 4  4    D  一班     女    88 2024-01-10
## 5  5    E  二班     男    95 2024-03-05
## 6  6    F  三班     女    70 2024-02-01
## 7  7    G  一班     男    82 2024-01-25
## 8  8    H  二班     女    90 2024-03-10

字符排序通常按照字母顺序或编码顺序。


11. 多变量排序

很多时候,我们不是只按一个变量排序,而是按多个变量排序。

比如:

先按班级排序,再按分数从高到低排序。

基础R写法:

student_by_class_score <- student[order(student$class, -student$score), ]

student_by_class_score
##   id name class gender score       date
## 5  5    E  二班     男    95 2024-03-05
## 8  8    H  二班     女    90 2024-03-10
## 1  1    A  二班     女    85 2024-03-01
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01
## 2  2    B  一班     男    92 2024-01-15
## 4  4    D  一班     女    88 2024-01-10
## 7  7    G  一班     男    82 2024-01-25

解释:

order(student$class, -student$score)

表示:

  1. 先按 class 排序;
  2. 如果 class 相同,再按 score 从高到低排序。

12. 多变量排序:一个升序,一个降序

例如:

先按性别排序,再按分数从高到低排序。

student_by_gender_score <- student[order(student$gender, -student$score), ]

student_by_gender_score
##   id name class gender score       date
## 5  5    E  二班     男    95 2024-03-05
## 2  2    B  一班     男    92 2024-01-15
## 7  7    G  一班     男    82 2024-01-25
## 3  3    C  三班     男    78 2024-02-20
## 8  8    H  二班     女    90 2024-03-10
## 4  4    D  一班     女    88 2024-01-10
## 1  1    A  二班     女    85 2024-03-01
## 6  6    F  三班     女    70 2024-02-01

13. 注意:中文班级排序可能不是我们想要的

现在班级是:

一班,二班,三班

但是如果直接:

sort(unique(student$class))
## [1] "二班" "三班" "一班"

R的排序可能不一定是我们想要的逻辑顺序。

如果我们希望顺序固定为:

一班 < 二班 < 三班

可以使用因子 factor。


14. 用 factor 控制排序顺序

student$class_factor <- factor(
  student$class,
  levels = c("一班", "二班", "三班"),
  ordered = TRUE
)

student
##   id name class gender score       date class_factor
## 1  1    A  二班     女    85 2024-03-01         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 3  3    C  三班     男    78 2024-02-20         三班
## 4  4    D  一班     女    88 2024-01-10         一班
## 5  5    E  二班     男    95 2024-03-05         二班
## 6  6    F  三班     女    70 2024-02-01         三班
## 7  7    G  一班     男    82 2024-01-25         一班
## 8  8    H  二班     女    90 2024-03-10         二班

查看水平:

levels(student$class_factor)
## [1] "一班" "二班" "三班"

按班级因子排序:

student_by_class_factor <- student[order(student$class_factor), ]

student_by_class_factor
##   id name class gender score       date class_factor
## 2  2    B  一班     男    92 2024-01-15         一班
## 4  4    D  一班     女    88 2024-01-10         一班
## 7  7    G  一班     男    82 2024-01-25         一班
## 1  1    A  二班     女    85 2024-03-01         二班
## 5  5    E  二班     男    95 2024-03-05         二班
## 8  8    H  二班     女    90 2024-03-10         二班
## 3  3    C  三班     男    78 2024-02-20         三班
## 6  6    F  三班     女    70 2024-02-01         三班

这时排序会按照:

一班,二班,三班

15. 因子排序 + 分数排序

例如:

先按班级:一班、二班、三班;
每个班内部按分数从高到低。

student_by_class_score2 <- student[order(student$class_factor, -student$score), ]

student_by_class_score2
##   id name class gender score       date class_factor
## 2  2    B  一班     男    92 2024-01-15         一班
## 4  4    D  一班     女    88 2024-01-10         一班
## 7  7    G  一班     男    82 2024-01-25         一班
## 5  5    E  二班     男    95 2024-03-05         二班
## 8  8    H  二班     女    90 2024-03-10         二班
## 1  1    A  二班     女    85 2024-03-01         二班
## 3  3    C  三班     男    78 2024-02-20         三班
## 6  6    F  三班     女    70 2024-02-01         三班

这是考试和作业里很常见的排序方式。


16. 排序后重置行号

排序后,原来的行号会保留。

例如:

student_by_score_desc
##   id name class gender score       date
## 5  5    E  二班     男    95 2024-03-05
## 2  2    B  一班     男    92 2024-01-15
## 8  8    H  二班     女    90 2024-03-10
## 4  4    D  一班     女    88 2024-01-10
## 1  1    A  二班     女    85 2024-03-01
## 7  7    G  一班     男    82 2024-01-25
## 3  3    C  三班     男    78 2024-02-20
## 6  6    F  三班     女    70 2024-02-01

如果想重新生成从 1 开始的行号:

student_by_score_desc_reset <- student_by_score_desc

rownames(student_by_score_desc_reset) <- NULL

student_by_score_desc_reset
##   id name class gender score       date
## 1  5    E  二班     男    95 2024-03-05
## 2  2    B  一班     男    92 2024-01-15
## 3  8    H  二班     女    90 2024-03-10
## 4  4    D  一班     女    88 2024-01-10
## 5  1    A  二班     女    85 2024-03-01
## 6  7    G  一班     男    82 2024-01-25
## 7  3    C  三班     男    78 2024-02-20
## 8  6    F  三班     女    70 2024-02-01

常用写法:

rownames(df) <- NULL

17. 处理缺失值 NA 的排序

创建一个带缺失值的数据:

score_na <- c(85, NA, 78, 92, NA, 70)

score_na
## [1] 85 NA 78 92 NA 70

直接排序:

sort(score_na)
## [1] 70 78 85 92

默认情况下,sort() 会把 NA 去掉。

如果想保留 NA:

sort(score_na, na.last = TRUE)
## [1] 70 78 85 92 NA NA

把 NA 放最后:

sort(score_na, na.last = TRUE)
## [1] 70 78 85 92 NA NA

把 NA 放最前:

sort(score_na, na.last = FALSE)
## [1] NA NA 70 78 85 92

18. 数据框中 NA 排序

创建带 NA 的数据框:

student_na <- data.frame(
  name = c("A", "B", "C", "D", "E"),
  score = c(85, NA, 78, 92, NA)
)

student_na
##   name score
## 1    A    85
## 2    B    NA
## 3    C    78
## 4    D    92
## 5    E    NA

按分数排序,NA 放最后:

student_na_ordered <- student_na[order(student_na$score, na.last = TRUE), ]

student_na_ordered
##   name score
## 3    C    78
## 1    A    85
## 4    D    92
## 2    B    NA
## 5    E    NA

按分数排序,NA 放最前:

student_na_ordered2 <- student_na[order(student_na$score, na.last = FALSE), ]

student_na_ordered2
##   name score
## 2    B    NA
## 5    E    NA
## 3    C    78
## 1    A    85
## 4    D    92

19. 使用 dplyr 排序:arrange()

如果你的课程讲过 dplyr,排序可以用 arrange()

如果没有安装,先运行:

install.packages("dplyr")

加载包:

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

20. dplyr:升序排序

按分数从低到高:

student %>%
  arrange(score)
##   id name class gender score       date class_factor
## 1  6    F  三班     女    70 2024-02-01         三班
## 2  3    C  三班     男    78 2024-02-20         三班
## 3  7    G  一班     男    82 2024-01-25         一班
## 4  1    A  二班     女    85 2024-03-01         二班
## 5  4    D  一班     女    88 2024-01-10         一班
## 6  8    H  二班     女    90 2024-03-10         二班
## 7  2    B  一班     男    92 2024-01-15         一班
## 8  5    E  二班     男    95 2024-03-05         二班

arrange(score) 默认是升序。


21. dplyr:降序排序

按分数从高到低:

student %>%
  arrange(desc(score))
##   id name class gender score       date class_factor
## 1  5    E  二班     男    95 2024-03-05         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 3  8    H  二班     女    90 2024-03-10         二班
## 4  4    D  一班     女    88 2024-01-10         一班
## 5  1    A  二班     女    85 2024-03-01         二班
## 6  7    G  一班     男    82 2024-01-25         一班
## 7  3    C  三班     男    78 2024-02-20         三班
## 8  6    F  三班     女    70 2024-02-01         三班

其中:

desc(score)

表示降序。


22. dplyr:按日期排序

日期从早到晚:

student %>%
  arrange(date)
##   id name class gender score       date class_factor
## 1  4    D  一班     女    88 2024-01-10         一班
## 2  2    B  一班     男    92 2024-01-15         一班
## 3  7    G  一班     男    82 2024-01-25         一班
## 4  6    F  三班     女    70 2024-02-01         三班
## 5  3    C  三班     男    78 2024-02-20         三班
## 6  1    A  二班     女    85 2024-03-01         二班
## 7  5    E  二班     男    95 2024-03-05         二班
## 8  8    H  二班     女    90 2024-03-10         二班

日期从晚到早:

student %>%
  arrange(desc(date))
##   id name class gender score       date class_factor
## 1  8    H  二班     女    90 2024-03-10         二班
## 2  5    E  二班     男    95 2024-03-05         二班
## 3  1    A  二班     女    85 2024-03-01         二班
## 4  3    C  三班     男    78 2024-02-20         三班
## 5  6    F  三班     女    70 2024-02-01         三班
## 6  7    G  一班     男    82 2024-01-25         一班
## 7  2    B  一班     男    92 2024-01-15         一班
## 8  4    D  一班     女    88 2024-01-10         一班

23. dplyr:多变量排序

先按班级,再按分数从高到低:

student %>%
  arrange(class_factor, desc(score))
##   id name class gender score       date class_factor
## 1  2    B  一班     男    92 2024-01-15         一班
## 2  4    D  一班     女    88 2024-01-10         一班
## 3  7    G  一班     男    82 2024-01-25         一班
## 4  5    E  二班     男    95 2024-03-05         二班
## 5  8    H  二班     女    90 2024-03-10         二班
## 6  1    A  二班     女    85 2024-03-01         二班
## 7  3    C  三班     男    78 2024-02-20         三班
## 8  6    F  三班     女    70 2024-02-01         三班

解释:

arrange(class_factor, desc(score))

表示:

  1. 先按 class_factor 升序;
  2. 同一个班内按 score 降序。

24. dplyr:排序后保存结果

如果只是运行:

student %>% arrange(desc(score))

不会改变原来的 student

如果要保存排序后的结果,要赋值:

student_sorted <- student %>%
  arrange(desc(score))

student_sorted
##   id name class gender score       date class_factor
## 1  5    E  二班     男    95 2024-03-05         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 3  8    H  二班     女    90 2024-03-10         二班
## 4  4    D  一班     女    88 2024-01-10         一班
## 5  1    A  二班     女    85 2024-03-01         二班
## 6  7    G  一班     男    82 2024-01-25         一班
## 7  3    C  三班     男    78 2024-02-20         三班
## 8  6    F  三班     女    70 2024-02-01         三班

25. base R 和 dplyr 排序对比

任务 基础R dplyr
分数升序 df[order(df$score), ] df %>% arrange(score)
分数降序 df[order(-df$score), ] df %>% arrange(desc(score))
日期升序 df[order(df$date), ] df %>% arrange(date)
日期降序 df[order(df$date, decreasing=TRUE), ] df %>% arrange(desc(date))
多变量排序 df[order(df$class, -df$score), ] df %>% arrange(class, desc(score))

26. 排序常见错误

错误1:只用了 sort(),没有排序整个数据框

错误示例:

sort(student$score)
## [1] 70 78 82 85 88 90 92 95

这只会得到排序后的分数,不会把其他列一起排序。

正确写法:

student[order(student$score), ]
##   id name class gender score       date class_factor
## 6  6    F  三班     女    70 2024-02-01         三班
## 3  3    C  三班     男    78 2024-02-20         三班
## 7  7    G  一班     男    82 2024-01-25         一班
## 1  1    A  二班     女    85 2024-03-01         二班
## 4  4    D  一班     女    88 2024-01-10         一班
## 8  8    H  二班     女    90 2024-03-10         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 5  5    E  二班     男    95 2024-03-05         二班

或者:

student %>%
  arrange(score)
##   id name class gender score       date class_factor
## 1  6    F  三班     女    70 2024-02-01         三班
## 2  3    C  三班     男    78 2024-02-20         三班
## 3  7    G  一班     男    82 2024-01-25         一班
## 4  1    A  二班     女    85 2024-03-01         二班
## 5  4    D  一班     女    88 2024-01-10         一班
## 6  8    H  二班     女    90 2024-03-10         二班
## 7  2    B  一班     男    92 2024-01-15         一班
## 8  5    E  二班     男    95 2024-03-05         二班

错误2:日期没有转换成 Date 类型

如果日期是字符:

date_char <- c("2024-1-5", "2024-10-1", "2024-2-1")

sort(date_char)
## [1] "2024-1-5"  "2024-10-1" "2024-2-1"

你可能会得到不符合真实日期先后的顺序。

正确做法是先转日期:

date_real <- as.Date(date_char)

sort(date_real)
## [1] "2024-01-05" "2024-02-01" "2024-10-01"

所以排序日期前,要确认:

class(student$date)
## [1] "Date"

应该是:

Date

错误3:没有保存排序结果

student[order(student$score), ]
##   id name class gender score       date class_factor
## 6  6    F  三班     女    70 2024-02-01         三班
## 3  3    C  三班     男    78 2024-02-20         三班
## 7  7    G  一班     男    82 2024-01-25         一班
## 1  1    A  二班     女    85 2024-03-01         二班
## 4  4    D  一班     女    88 2024-01-10         一班
## 8  8    H  二班     女    90 2024-03-10         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 5  5    E  二班     男    95 2024-03-05         二班

这只是在屏幕上显示排序结果,不会改变原数据。

如果想保存:

student_sorted <- student[order(student$score), ]

student_sorted
##   id name class gender score       date class_factor
## 6  6    F  三班     女    70 2024-02-01         三班
## 3  3    C  三班     男    78 2024-02-20         三班
## 7  7    G  一班     男    82 2024-01-25         一班
## 1  1    A  二班     女    85 2024-03-01         二班
## 4  4    D  一班     女    88 2024-01-10         一班
## 8  8    H  二班     女    90 2024-03-10         二班
## 2  2    B  一班     男    92 2024-01-15         一班
## 5  5    E  二班     男    95 2024-03-05         二班

错误4:想要自定义顺序但没有用 factor

例如等级变量:

level_df <- data.frame(
  level = c("中", "高", "低", "中", "高"),
  value = c(2, 3, 1, 2, 3)
)

level_df
##   level value
## 1    中     2
## 2    高     3
## 3    低     1
## 4    中     2
## 5    高     3

直接排序:

level_df[order(level_df$level), ]
##   level value
## 3    低     1
## 2    高     3
## 5    高     3
## 1    中     2
## 4    中     2

结果可能不是:

低 中 高

正确做法:

level_df$level_f <- factor(
  level_df$level,
  levels = c("低", "中", "高"),
  ordered = TRUE
)

level_df[order(level_df$level_f), ]
##   level value level_f
## 3    低     1      低
## 1    中     2      中
## 4    中     2      中
## 2    高     3      高
## 5    高     3      高

27. 小练习

下面有一个订单数据:

orders <- data.frame(
  order_id = 1:8,
  customer = c("A", "B", "C", "D", "E", "F", "G", "H"),
  region = c("华东", "华北", "华南", "华东", "华北", "华南", "华东", "华北"),
  level = c("普通", "高级", "普通", "VIP", "高级", "VIP", "普通", "VIP"),
  order_date = c("2024-02-01", "2024-01-15", "2024-03-10", "2024-01-20",
                 "2024-02-18", "2024-03-01", "2024-01-05", "2024-02-25"),
  amount = c(300, 500, 200, 800, 600, 900, 150, 1000)
)

orders$order_date <- as.Date(orders$order_date)

orders
##   order_id customer region level order_date amount
## 1        1        A   华东  普通 2024-02-01    300
## 2        2        B   华北  高级 2024-01-15    500
## 3        3        C   华南  普通 2024-03-10    200
## 4        4        D   华东   VIP 2024-01-20    800
## 5        5        E   华北  高级 2024-02-18    600
## 6        6        F   华南   VIP 2024-03-01    900
## 7        7        G   华东  普通 2024-01-05    150
## 8        8        H   华北   VIP 2024-02-25   1000

要求:

  1. 按金额 amount 从小到大排序;
  2. 按金额 amount 从大到小排序;
  3. 按订单日期 order_date 从早到晚排序;
  4. 按地区 region 排序,同地区内部按金额从大到小排序;
  5. 把客户等级 level 设置为有序因子,顺序为:普通 < 高级 < VIP;
  6. 按客户等级排序,同等级内部按金额从大到小排序。

28. 小练习参考答案:基础R写法

28.1 金额从小到大

orders_amount_asc <- orders[order(orders$amount), ]

orders_amount_asc
##   order_id customer region level order_date amount
## 7        7        G   华东  普通 2024-01-05    150
## 3        3        C   华南  普通 2024-03-10    200
## 1        1        A   华东  普通 2024-02-01    300
## 2        2        B   华北  高级 2024-01-15    500
## 5        5        E   华北  高级 2024-02-18    600
## 4        4        D   华东   VIP 2024-01-20    800
## 6        6        F   华南   VIP 2024-03-01    900
## 8        8        H   华北   VIP 2024-02-25   1000

28.2 金额从大到小

orders_amount_desc <- orders[order(-orders$amount), ]

orders_amount_desc
##   order_id customer region level order_date amount
## 8        8        H   华北   VIP 2024-02-25   1000
## 6        6        F   华南   VIP 2024-03-01    900
## 4        4        D   华东   VIP 2024-01-20    800
## 5        5        E   华北  高级 2024-02-18    600
## 2        2        B   华北  高级 2024-01-15    500
## 1        1        A   华东  普通 2024-02-01    300
## 3        3        C   华南  普通 2024-03-10    200
## 7        7        G   华东  普通 2024-01-05    150

28.3 日期从早到晚

orders_date_asc <- orders[order(orders$order_date), ]

orders_date_asc
##   order_id customer region level order_date amount
## 7        7        G   华东  普通 2024-01-05    150
## 2        2        B   华北  高级 2024-01-15    500
## 4        4        D   华东   VIP 2024-01-20    800
## 1        1        A   华东  普通 2024-02-01    300
## 5        5        E   华北  高级 2024-02-18    600
## 8        8        H   华北   VIP 2024-02-25   1000
## 6        6        F   华南   VIP 2024-03-01    900
## 3        3        C   华南  普通 2024-03-10    200

28.4 地区排序,同地区内部金额降序

orders_region_amount <- orders[order(orders$region, -orders$amount), ]

orders_region_amount
##   order_id customer region level order_date amount
## 8        8        H   华北   VIP 2024-02-25   1000
## 5        5        E   华北  高级 2024-02-18    600
## 2        2        B   华北  高级 2024-01-15    500
## 4        4        D   华东   VIP 2024-01-20    800
## 1        1        A   华东  普通 2024-02-01    300
## 7        7        G   华东  普通 2024-01-05    150
## 6        6        F   华南   VIP 2024-03-01    900
## 3        3        C   华南  普通 2024-03-10    200

28.5 设置客户等级为有序因子

orders$level_f <- factor(
  orders$level,
  levels = c("普通", "高级", "VIP"),
  ordered = TRUE
)

orders
##   order_id customer region level order_date amount level_f
## 1        1        A   华东  普通 2024-02-01    300    普通
## 2        2        B   华北  高级 2024-01-15    500    高级
## 3        3        C   华南  普通 2024-03-10    200    普通
## 4        4        D   华东   VIP 2024-01-20    800     VIP
## 5        5        E   华北  高级 2024-02-18    600    高级
## 6        6        F   华南   VIP 2024-03-01    900     VIP
## 7        7        G   华东  普通 2024-01-05    150    普通
## 8        8        H   华北   VIP 2024-02-25   1000     VIP

28.6 按客户等级排序,同等级内部金额降序

orders_level_amount <- orders[order(orders$level_f, -orders$amount), ]

orders_level_amount
##   order_id customer region level order_date amount level_f
## 1        1        A   华东  普通 2024-02-01    300    普通
## 3        3        C   华南  普通 2024-03-10    200    普通
## 7        7        G   华东  普通 2024-01-05    150    普通
## 5        5        E   华北  高级 2024-02-18    600    高级
## 2        2        B   华北  高级 2024-01-15    500    高级
## 8        8        H   华北   VIP 2024-02-25   1000     VIP
## 6        6        F   华南   VIP 2024-03-01    900     VIP
## 4        4        D   华东   VIP 2024-01-20    800     VIP

29. 小练习参考答案:dplyr写法

library(dplyr)

29.1 金额从小到大

orders %>%
  arrange(amount)
##   order_id customer region level order_date amount level_f
## 1        7        G   华东  普通 2024-01-05    150    普通
## 2        3        C   华南  普通 2024-03-10    200    普通
## 3        1        A   华东  普通 2024-02-01    300    普通
## 4        2        B   华北  高级 2024-01-15    500    高级
## 5        5        E   华北  高级 2024-02-18    600    高级
## 6        4        D   华东   VIP 2024-01-20    800     VIP
## 7        6        F   华南   VIP 2024-03-01    900     VIP
## 8        8        H   华北   VIP 2024-02-25   1000     VIP

29.2 金额从大到小

orders %>%
  arrange(desc(amount))
##   order_id customer region level order_date amount level_f
## 1        8        H   华北   VIP 2024-02-25   1000     VIP
## 2        6        F   华南   VIP 2024-03-01    900     VIP
## 3        4        D   华东   VIP 2024-01-20    800     VIP
## 4        5        E   华北  高级 2024-02-18    600    高级
## 5        2        B   华北  高级 2024-01-15    500    高级
## 6        1        A   华东  普通 2024-02-01    300    普通
## 7        3        C   华南  普通 2024-03-10    200    普通
## 8        7        G   华东  普通 2024-01-05    150    普通

29.3 日期从早到晚

orders %>%
  arrange(order_date)
##   order_id customer region level order_date amount level_f
## 1        7        G   华东  普通 2024-01-05    150    普通
## 2        2        B   华北  高级 2024-01-15    500    高级
## 3        4        D   华东   VIP 2024-01-20    800     VIP
## 4        1        A   华东  普通 2024-02-01    300    普通
## 5        5        E   华北  高级 2024-02-18    600    高级
## 6        8        H   华北   VIP 2024-02-25   1000     VIP
## 7        6        F   华南   VIP 2024-03-01    900     VIP
## 8        3        C   华南  普通 2024-03-10    200    普通

29.4 地区排序,同地区内部金额降序

orders %>%
  arrange(region, desc(amount))
##   order_id customer region level order_date amount level_f
## 1        4        D   华东   VIP 2024-01-20    800     VIP
## 2        1        A   华东  普通 2024-02-01    300    普通
## 3        7        G   华东  普通 2024-01-05    150    普通
## 4        8        H   华北   VIP 2024-02-25   1000     VIP
## 5        5        E   华北  高级 2024-02-18    600    高级
## 6        2        B   华北  高级 2024-01-15    500    高级
## 7        6        F   华南   VIP 2024-03-01    900     VIP
## 8        3        C   华南  普通 2024-03-10    200    普通

29.5 按客户等级排序,同等级内部金额降序

orders %>%
  arrange(level_f, desc(amount))
##   order_id customer region level order_date amount level_f
## 1        1        A   华东  普通 2024-02-01    300    普通
## 2        3        C   华南  普通 2024-03-10    200    普通
## 3        7        G   华东  普通 2024-01-05    150    普通
## 4        5        E   华北  高级 2024-02-18    600    高级
## 5        2        B   华北  高级 2024-01-15    500    高级
## 6        8        H   华北   VIP 2024-02-25   1000     VIP
## 7        6        F   华南   VIP 2024-03-01    900     VIP
## 8        4        D   华东   VIP 2024-01-20    800     VIP

30. 本节核心代码总结

# 向量升序
sort(x)

# 向量降序
sort(x, decreasing = TRUE)

# 数据框按某列升序
df[order(df$变量), ]

# 数据框按某列降序
df[order(-df$变量), ]

# 日期降序
df[order(df$date, decreasing = TRUE), ]

# 多变量排序:先A升序,再B降序
df[order(df$A, -df$B), ]

# 排序后重置行号
rownames(df_sorted) <- NULL

# 使用因子控制自定义顺序
df$level_f <- factor(
  df$level,
  levels = c("低", "中", "高"),
  ordered = TRUE
)

df[order(df$level_f), ]

# dplyr升序
df %>% arrange(变量)

# dplyr降序
df %>% arrange(desc(变量))

# dplyr多变量排序
df %>% arrange(A, desc(B))

31. 一句话总结

排序最重要的区别是:

sort()

用于排序一个向量。

order()

用于排序整个数据框。

arrange()

dplyr 里面更直观的数据框排序函数。

考试重点记住:

df[order(df$score), ]
df[order(-df$score), ]
df[order(df$class, -df$score), ]
df %>% arrange(class, desc(score))