【零基础玩转Python】Day42:数据排序与排名 – sort_values, rank,让数据有序竞争
大家好,我是[知识充电宝的灵感日记]。
在数据分析中,我们经常需要按照某个指标给数据排序(比如按成绩排序、按销售额排序),或者计算排名(比如第1名、第2名,处理并列情况)。今天我们就来学习 Pandas 中的排序和排名操作。
今天的目标:
难度:⭐⭐(语法简单,但排名方法的区别需要理解)
一、排序:sort_values()
1. 基本用法
import pandas as pd
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六'],
'成绩': [85, 92, 78, 88],
'年龄': [18, 20, 19, 22]
})
# 按成绩升序排序(默认 ascending=True)
df_sorted = df.sort_values('成绩')
print(df_sorted)
姓名 成绩 年龄
2 王五 78 19
0 张三 85 18
3 赵六 88 22
1 李四 92 20
2. 降序排序
df_sorted_desc = df.sort_values('成绩', ascending=False)
print(df_sorted_desc)
姓名 成绩 年龄
1 李四 92 20
3 赵六 88 22
0 张三 85 18
2 王五 78 19
3. 按多列排序
先按一列排序,相同时按第二列排序。
df = pd.DataFrame({
'班级': ['A', 'A', 'B', 'B'],
'成绩': [85, 92, 88, 85],
'姓名': ['张三', '李四', '王五', '赵六']
})
# 先按班级升序,再按成绩降序
df_sorted = df.sort_values(['班级', '成绩'], ascending=[True, False])
print(df_sorted)
班级 成绩 姓名
1 A 92 李四
0 A 85 张三
2 B 88 王五
3 B 85 赵六
4. 重置索引
排序后索引还是原来的值,可以重置索引:
df_sorted = df.sort_values('成绩', ignore_index=True)
# 或 df_sorted = df.sort_values('成绩').reset_index(drop=True)
5. 原地排序
df.sort_values('成绩', inplace=True)
二、排名:rank()
rank() 为数据分配排名,可以处理并列情况和不同的排名策略。
1. 基本排名(默认 method='average')
并列时取平均排名。
s = pd.Series([100, 90, 90, 80])
print(s.rank())
0 4.0
1 2.5
2 2.5
3 1.0
dtype: float64
解释:90分有两个,占据第2和第3位,平均排名为 (2+3)/2 = 2.5。
2. 不同排名方法(method 参数)
print(s.rank(method='min')) # [4,2,2,1]
print(s.rank(method='dense')) # [3,2,2,1]
0 4.0
1 2.0
2 2.0
3 1.0
dtype: float64
0 3.0
1 2.0
2 2.0
3 1.0
dtype: float64
3. 升序与降序排名
默认 ascending=True(值越小排名越靠前)。降序排名:
# 分数越高排名越前(第一名是最高分)
print(s.rank(ascending=False)) # [1,2.5,2.5,4]
0 1.0
1 2.5
2 2.5
3 4.0
dtype: float64
4. 按列排名
对 DataFrame 的每一列单独排名。
df = pd.DataFrame({'A': [100, 90, 90, 80], 'B': [50, 60, 50, 70]})
print(df.rank())
A B
0 4.0 1.5
1 2.5 3.0
2 2.5 1.5
3 1.0 4.0
5. 指定轴排名(行方向)
# 对每行数据进行排名(axis=1)
df = pd.DataFrame({'语文': [85, 92], '数学': [90, 88], '英语': [88, 94]})
print(df.rank(axis=1, ascending=False))
语文 数学 英语
0 3.0 1.0 2.0
1 2.0 3.0 1.0
三、实战小案例
案例1:学生成绩排名(处理并列)
scores = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', '小明'],
'成绩': [92, 88, 92, 85, 88]
})
# 按成绩降序排序
scores_sorted = scores.sort_values('成绩', ascending=False).reset_index(drop=True)
# 添加排名列(密集排名,不跳号)
scores_sorted['排名'] = scores_sorted['成绩'].rank(method='dense', ascending=False).astype(int)
print(scores_sorted)
姓名 成绩 排名
0 张三 92 1
1 王五 92 1
2 李四 88 2
3 小明 88 2
4 赵六 85 3
案例2:销售业绩排序与排名
sales = pd.DataFrame({
'销售员': ['小王', '小李', '小张', '小赵', '小周'],
'销售额': [12000, 15000, 12000, 9000, 15000]
})
# 先排序再添加排名
sales_sorted = sales.sort_values('销售额', ascending=False)
sales_sorted['排名'] = sales_sorted['销售额'].rank(method='min', ascending=False).astype(int)
print(sales_sorted)
销售员 销售额 排名
1 小李 15000 1
4 小周 15000 1
0 小王 12000 3
2 小张 12000 3
3 小赵 9000 5
案例3:按总分排名(多科成绩)
df = pd.DataFrame({
'学生': ['A', 'B', 'C', 'D'],
'数学': [85, 90, 85, 88],
'语文': [92, 88, 85, 90]
})
df['总分'] = df['数学'] + df['语文']
df['总分排名'] = df['总分'].rank(ascending=False, method='dense').astype(int)
df_sorted = df.sort_values('总分', ascending=False)
print(df_sorted)
学生 数学 语文 总分 总分排名
1 B 90 88 178 1
3 D 88 90 178 1
0 A 85 92 177 2
2 C 85 85 170 3
四、今日练习
- a) 按销量降序排序
- b) 添加一列排名,使用 method='dense',并转为整数
df = pd.DataFrame({
'姓名': ['张一', '李二', '王三', '赵四', '周五'],
'成绩1': [88, 92, 88, 85, 92],
'成绩2': [90, 87, 90, 86, 89]
})
- 计算每个人的总分
- 按总分降序排序
- 添加平均排名(method='average')和密集排名(method='dense')两列,观察区别
- 按多列排序:先按 '部门' 升序,再按 '工资' 降序排序数据:
employees = pd.DataFrame({
'部门': ['销售', '技术', '销售', '技术', '市场'],
'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
'工资': [5000, 8000, 5500, 7500, 6000]
})
- (挑战)从泰坦尼克数据集中,按 'Age' 列排序,对缺失年龄的行放到最后(提示:
na_position='last'),然后按年龄降序添加排名列(忽略缺失值)。
五、常见错误与提示
sort_values的 ascending参数:可传入布尔值,多列排序时也可传入对应列表。rank默认按升序排名:数值越小排名越靠前;若希望高分排名更靠前,需设置 ascending=False。- 排名结果默认为浮点型:如需转为整型,可使用
.astype(int),转换前需保证数据无缺失值。 - 缺失值处理:
sort_values默认将 NaN置于数据末尾(na_position='last');rank会为 NaN依旧返回 NaN。 rank搭配 method='first':按照数据原始出现顺序分配排名,先出现的数据排名更小,排名结果唯一。
六、明日预告
Day43:分组聚合 – groupby + agg / transform
我们将学习 Pandas 中的分组操作,这是数据分析最强大的功能之一,用法类似 SQL 的 GROUP BY。