数据排序:`sort_values` 与 `sort_index` 的灵活应用

数据排序:sort_valuessort_index 的灵活应用 – 程序员的优雅舞步 💃🕺

各位尊敬的程序员朋友们,大家好!我是你们的老朋友,一个在数据海洋里摸爬滚打多年的老水手。今天,我们要聊聊数据分析中的一项基本功,也是一项隐藏着无数优雅舞步的关键技巧:数据排序。具体来说,我们将深入探讨 Pandas 库中的两个明星函数:sort_valuessort_index

想象一下,你手里拿着一副扑克牌,乱七八糟地散落着。如果你想玩得溜,是不是得先整理整理,按照花色或者大小排个顺序?数据也是一样!未经排序的数据就像一盘散沙,让人摸不着头脑;而排序后的数据,则像一位训练有素的舞者,每一个动作都清晰流畅,每一个节奏都恰到好处。

那么,sort_valuessort_index 这两位舞者,究竟有何不同?又该如何在不同的场合下,邀请他们翩翩起舞呢? 别着急,让我们慢慢揭开这层神秘的面纱!

第一幕:sort_values – 优雅的数值排序大师 🎭

sort_values,顾名思义,就是根据 数值 来进行排序的。它就像一位经验丰富的选美评委,只关注选手的内在(数值),而忽略她们的外貌(索引)。

1. 基本用法:

最简单的用法,就是直接调用 sort_values() 函数。默认情况下,它会按照升序进行排列。

import pandas as pd

# 创建一个示例 DataFrame
data = {'姓名': ['张三', '李四', '王五', '赵六'],
        '成绩': [85, 92, 78, 95]}
df = pd.DataFrame(data)

print("原始 DataFrame:n", df)

# 按照成绩进行升序排序
df_sorted = df.sort_values(by='成绩')
print("n按照成绩升序排序后的 DataFrame:n", df_sorted)

输出结果:

原始 DataFrame:
   姓名  成绩
0  张三  85
1  李四  92
2  王五  78
3  赵六  95

按照成绩升序排序后的 DataFrame:
   姓名  成绩
2  王五  78
0  张三  85
1  李四  92
3  赵六  95

注意,sort_values(by='成绩') 中的 by 参数,指定了要按照哪一列进行排序。这里,我们指定了 ‘成绩’ 这一列。

2. 降序排列:

如果你想要按照降序排列,只需要设置 ascending=False 即可。

df_sorted_desc = df.sort_values(by='成绩', ascending=False)
print("n按照成绩降序排序后的 DataFrame:n", df_sorted_desc)

输出结果:

按照成绩降序排序后的 DataFrame:
   姓名  成绩
3  赵六  95
1  李四  92
0  张三  85
2  王五  78

3. 多列排序:

有时候,单凭一列数据可能无法区分出优先级,这时就需要多列排序。 想象一下,选美比赛不仅仅看颜值,还要看才艺、气质等等。sort_values 同样支持多列排序,只需要将 by 参数设置为一个列表即可。列表中的元素,按照优先级从高到低排列。

# 创建一个包含两列数值的 DataFrame
data = {'班级': ['一班', '一班', '二班', '二班'],
        '成绩': [85, 92, 78, 95],
        '排名': [3, 1, 4, 2]}
df = pd.DataFrame(data)

print("原始 DataFrame:n", df)

# 先按照班级升序排序,再按照成绩降序排序
df_sorted_multi = df.sort_values(by=['班级', '成绩'], ascending=[True, False])
print("n先按照班级升序,再按照成绩降序排序后的 DataFrame:n", df_sorted_multi)

输出结果:

原始 DataFrame:
   班级  成绩  排名
0  一班  85   3
1  一班  92   1
2  二班  78   4
3  二班  95   2

先按照班级升序,再按照成绩降序排序后的 DataFrame:
   班级  成绩  排名
1  一班  92   1
0  一班  85   3
3  二班  95   2
2  二班  78   4

注意,ascending 参数也需要是一个列表,与 by 参数一一对应。

4. 处理缺失值:

如果你的数据中包含缺失值(NaN),sort_values 默认会将缺失值放在最后面。你可以通过 na_position 参数来控制缺失值的位置。

  • na_position='first':将缺失值放在最前面。
  • na_position='last':将缺失值放在最后面 (默认值)。
import numpy as np

# 创建一个包含缺失值的 DataFrame
data = {'姓名': ['张三', '李四', '王五', '赵六'],
        '成绩': [85, np.nan, 78, 95]}
df = pd.DataFrame(data)

print("原始 DataFrame:n", df)

# 将缺失值放在最前面
df_sorted_na_first = df.sort_values(by='成绩', na_position='first')
print("n将缺失值放在最前面排序后的 DataFrame:n", df_sorted_na_first)

# 将缺失值放在最后面 (默认值)
df_sorted_na_last = df.sort_values(by='成绩', na_position='last')
print("n将缺失值放在最后面排序后的 DataFrame:n", df_sorted_na_last)

输出结果:

原始 DataFrame:
   姓名    成绩
0  张三  85.0
1  李四   NaN
2  王五  78.0
3  赵六  95.0

将缺失值放在最前面排序后的 DataFrame:
   姓名    成绩
1  李四   NaN
2  王五  78.0
0  张三  85.0
3  赵六  95.0

将缺失值放在最后面排序后的 DataFrame:
   姓名    成绩
2  王五  78.0
0  张三  85.0
3  赵六  95.0
1  李四   NaN

总结一下,sort_values 的常用参数:

参数 描述
by 指定要排序的列名(可以是单个列名,也可以是列名列表,用于多列排序)
axis 指定排序的轴,0 表示按行排序(默认),1 表示按列排序(不常用)
ascending 指定排序方式,True 表示升序(默认),False 表示降序(可以是单个布尔值,也可以是布尔值列表,用于多列排序)
inplace 是否在原始 DataFrame 上进行修改,True 表示直接修改原始 DataFrame,False 表示返回一个新的 DataFrame(默认)
kind 指定排序算法,’quicksort’(快速排序,默认)、’mergesort’(归并排序)、’heapsort’(堆排序)
na_position 指定缺失值的位置,’first’ 表示放在最前面,’last’ 表示放在最后面(默认)
ignore_index 是否重置索引,True 表示重置索引,False 表示保留原始索引(默认),如果 inplace=True,则该参数无效,索引始终会被重置,从 0 开始。

第二幕:sort_index – 索引排序的魔法师 🧙‍♂️

sort_index,顾名思义,就是根据 索引 来进行排序的。它就像一位图书馆管理员,只关心图书的编号(索引),而忽略图书的内容(数值)。

1. 基本用法:

同样,最简单的用法就是直接调用 sort_index() 函数。默认情况下,它会按照升序进行排列。

# 创建一个索引不规则的 DataFrame
data = {'姓名': ['张三', '李四', '王五', '赵六'],
        '成绩': [85, 92, 78, 95]}
df = pd.DataFrame(data, index=[3, 1, 0, 2])

print("原始 DataFrame:n", df)

# 按照索引进行升序排序
df_sorted_index = df.sort_index()
print("n按照索引升序排序后的 DataFrame:n", df_sorted_index)

输出结果:

原始 DataFrame:
   姓名  成绩
3  张三  85
1  李四  92
0  王五  78
2  赵六  95

按照索引升序排序后的 DataFrame:
   姓名  成绩
0  王五  78
1  李四  92
2  赵六  95
3  张三  85

2. 降序排列:

sort_values 类似,设置 ascending=False 可以进行降序排列。

df_sorted_index_desc = df.sort_index(ascending=False)
print("n按照索引降序排序后的 DataFrame:n", df_sorted_index_desc)

输出结果:

按照索引降序排序后的 DataFrame:
   姓名  成绩
3  张三  85
2  赵六  95
1  李四  92
0  王五  78

3. 处理多层索引:

sort_index 同样支持多层索引(MultiIndex)的排序。 你可以指定按照哪一层索引进行排序。

# 创建一个包含多层索引的 DataFrame
index = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), ('B', 1), ('B', 2)], names=['字母', '数字'])
data = {'值': [10, 20, 30, 40]}
df = pd.DataFrame(data, index=index)

print("原始 DataFrame:n", df)

# 按照第一层索引(字母)进行排序
df_sorted_level0 = df.sort_index(level=0)
print("n按照第一层索引(字母)排序后的 DataFrame:n", df_sorted_level0)

# 按照第二层索引(数字)进行排序
df_sorted_level1 = df.sort_index(level=1)
print("n按照第二层索引(数字)排序后的 DataFrame:n", df_sorted_level1)

输出结果:

原始 DataFrame:
        值
字母 数字    
A   1  10
    2  20
B   1  30
    2  40

按照第一层索引(字母)排序后的 DataFrame:
        值
字母 数字    
A   1  10
    2  20
B   1  30
    2  40

按照第二层索引(数字)排序后的 DataFrame:
        值
字母 数字    
A   1  10
B   1  30
A   2  20
B   2  40

总结一下,sort_index 的常用参数:

参数 描述
axis 指定排序的轴,0 表示按行索引排序(默认),1 表示按列索引排序
level 指定排序的层级,用于多层索引排序
ascending 指定排序方式,True 表示升序(默认),False 表示降序
inplace 是否在原始 DataFrame 上进行修改,True 表示直接修改原始 DataFrame,False 表示返回一个新的 DataFrame(默认)
sort_remaining 是否对剩余层级进行排序,True 表示进行排序(默认),False 表示不进行排序,仅对指定的 level 进行排序。
na_position 指定缺失值的位置,’first’ 表示放在最前面,’last’ 表示放在最后面(默认),仅当索引包含缺失值时有效。
ignore_index 是否重置索引,True 表示重置索引,False 表示保留原始索引(默认),如果 inplace=True,则该参数无效,索引始终会被重置,从 0 开始。

第三幕:sort_valuessort_index 的爱恨情仇 💔❤️

现在,我们已经分别认识了 sort_valuessort_index 这两位舞者。那么,在实际应用中,我们应该如何选择呢?

简单来说:

  • 如果你想根据 数值 进行排序,就选择 sort_values
  • 如果你想根据 索引 进行排序,就选择 sort_index

但是,事情并没有那么简单!有时候,这两位舞者可以互相配合,共同完成更加复杂的任务。

案例分析:

假设你有一个存储用户信息的 DataFrame,其中索引是用户的 ID,数据包含用户的姓名、年龄和消费金额。

import numpy as np

# 创建一个示例 DataFrame
data = {'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
        '年龄': [25, 30, 28, 22, np.nan],
        '消费金额': [100, 200, 150, 250, 180]}
df = pd.DataFrame(data, index=[3, 1, 0, 2, 4])

print("原始 DataFrame:n", df)

需求 1: 按照消费金额进行排序,并重置索引。

# 使用 sort_values 按照消费金额排序,并使用 ignore_index 重置索引
df_sorted_reset = df.sort_values(by='消费金额', ignore_index=True)
print("n按照消费金额排序并重置索引后的 DataFrame:n", df_sorted_reset)

这个需求很简单,直接使用 sort_values 就可以搞定。ignore_index=True 可以重置索引,使索引从 0 开始。

需求 2: 按照索引进行排序,然后按照年龄进行排序。

# 先按照索引排序
df_sorted_index = df.sort_index()
print("n按照索引排序后的 DataFrame:n", df_sorted_index)

# 再按照年龄排序
df_sorted_age = df_sorted_index.sort_values(by='年龄')
print("n按照索引排序后再按照年龄排序后的 DataFrame:n", df_sorted_age)

这个需求需要先使用 sort_index 按照索引排序,然后再使用 sort_values 按照年龄排序。

需求 3: 按照消费金额进行排序,但是要保留原始索引的顺序。

这个需求比较 tricky!我们需要先保存原始索引,然后按照消费金额排序,最后再按照原始索引排序。

# 1. 保存原始索引
original_index = df.index

# 2. 按照消费金额排序
df_sorted_value = df.sort_values(by='消费金额')

# 3. 按照原始索引排序
df_sorted_final = df_sorted_value.loc[original_index] #这里如果原始index有重复值,会报错,需要额外处理
print("n按照消费金额排序但保留原始索引顺序的 DataFrame:n", df_sorted_final)

注意事项:

  • inplace=True 会直接修改原始 DataFrame,因此需要谨慎使用。
  • 如果你的数据量非常大,选择合适的排序算法(kind 参数)可以提高效率。
  • 处理多层索引时,要仔细考虑层级的顺序和排序方式。

结语: 数据排序的艺术 🎨

数据排序不仅仅是一种技术,更是一种艺术。 通过灵活运用 sort_valuessort_index,我们可以将杂乱无章的数据变成井然有序的信息,从而更好地理解数据背后的故事。

希望今天的分享能帮助大家更好地掌握数据排序的技巧,在数据分析的道路上越走越远! 🚀

记住,代码的世界也需要优雅!让我们一起用优雅的舞步,征服数据海洋吧! 🌊

最后,送给大家一句程序员的座右铭: Bug 是代码的灵魂,排序是数据的生命! 😉

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注