Superpandas 教程:让 Pandas 更优雅
什么是 Superpandas?
superpandas 的核心思想是增强 pandas 对象(主要是 DataFrame 和 Series),让你可以直接在对象本身上进行链式操作,而不是不断地创建中间变量或使用 df['column'] 这种略显冗长的语法。

它深受 R 语言 dplyr 和 Python 自身 pandas 的启发,旨在提供一种更“函数式”和“声明式”的数据处理体验。
核心优势:
- 链式调用:将多个操作像链条一样连接起来,代码清晰易懂,逻辑一目了然。
- 减少中间变量:无需为每一步的中间结果创建新的变量,使代码更简洁。
- 更直观的 API:提供了一些
pandas原生没有,但非常实用的方法。
安装
你需要安装 superpandas,它依赖于 pandas。
pip install superpandas
核心概念:链式调用
superpandas 的魔力在于链式调用,假设我们有一个 DataFrame df,在 superpandas 中,我们可以这样写:

# 传统 Pandas 写法
df_filtered = df[df['age'] > 30]
df_sorted = df_filtered.sort_values('name')
df_final = df_sorted[['name', 'city']]
# Superpandas 链式写法
df_final = df.super.query('age > 30').super.sort('name').super.select(['name', 'city'])
对比一下,你会发现 superpandas 的版本更像在描述一个数据处理流程:“从 df 中,查询出年龄大于 30 的记录,然后按 name 排序,最后只选择 name 和 city 这两列。”
Superpandas 的核心方法详解
superpandas 通过 .super 属性暴露其所有方法,让我们通过一个示例数据集来逐一讲解。
准备示例数据:
import pandas as pd
import superpandas
# 创建一个示例 DataFrame
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'],
'age': [25, 45, 35, 28, 32, 50],
'city': ['New York', 'Los Angeles', 'Chicago', 'New York', 'Chicago', 'Houston'],
'salary': [70000, 80000, 120000, 65000, 90000, 110000]
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)
输出:

原始 DataFrame:
name age city salary
0 Alice 25 New York 70000
1 Bob 45 Los Angeles 80000
2 Charlie 35 Chicago 120000
3 David 28 New York 65000
4 Eve 32 Chicago 90000
5 Frank 50 Houston 110000
.super.query(condition) - 查询/筛选
这相当于 df[condition] 或 df.query(condition),但更易于链式调用。
# 筛选年龄大于 30 的人
adults = df.super.query('age > 30')
print(adults)
输出:
name age city salary
1 Bob 45 Los Angeles 80000
2 Charlie 35 Chicago 120000
4 Eve 32 Chicago 90000
5 Frank 50 Houston 110000
.super.sort(by_column) - 排序
这相当于 df.sort_values(by_column)。
# 按 'age' 列升序排序
sorted_by_age = df.super.sort('age')
print(sorted_by_age)
输出:
name age city salary
0 Alice 25 New York 70000
3 David 28 New York 65000
4 Eve 32 Chicago 90000
2 Charlie 35 Chicago 120000
1 Bob 45 Los Angeles 80000
5 Frank 50 Houston 110000
.super.select(columns) - 选择列
这相当于 df[columns]。
# 只选择 'name' 和 'city' 列 selected_cols = df.super.select(['name', 'city']) print(selected_cols)
输出:
name city
0 Alice New York
1 Bob Los Angeles
2 Charlie Chicago
3 David New York
4 Eve Chicago
5 Frank Houston
.super.rename(columns_dict) - 重命名列
这相当于 df.rename(columns=columns_dict)。
# 将 'name' 重命名为 'full_name'
renamed_df = df.super.rename({'name': 'full_name'})
print(renamed_df)
输出:
full_name age city salary
0 Alice 25 New York 70000
1 Bob 45 Los Angeles 80000
2 Charlie 35 Chicago 120000
3 David 28 New York 65000
4 Eve 32 Chicago 90000
5 Frank 50 Houston 110000
`.super.assign(kwargs)` - 添加新列**
这相当于 df.assign(**kwargs) 或 df['new_col'] = ...,但链式调用更方便。
# 添加一个 'age_group' 列
df_with_group = df.super.assign(
age_group=lambda d: pd.cut(d['age'], bins=[0, 30, 40, 100], labels=['Young', 'Middle', 'Senior'])
)
print(df_with_group)
输出:
name age city salary age_group
0 Alice 25 New York 70000 Young
1 Bob 45 Los Angeles 80000 Senior
2 Charlie 35 Chicago 120000 Middle
3 David 28 New York 65000 Young
4 Eve 32 Chicago 90000 Middle
5 Frank 50 Houston 110000 Senior
.super.groupby(by).agg(agg_dict) - 分组聚合
这是 superpandas 的一个亮点,它让 groupby 操作也变得非常流畅。
# 按 'city' 分组,计算平均薪资和人数
city_stats = df.super.groupby('city').agg(
avg_salary=('salary', 'mean'),
person_count=('name', 'count')
).super.sort('avg_salary', ascending=False)
print(city_stats)
输出:
avg_salary person_count
city
Chicago 105000.0000 2
Houston 110000.0000 1
New York 67500.0000 2
Los Angeles 80000.0000 1
*`.super.pipe(func, args, kwargs)` - 管道操作
这是一个非常强大的通用工具,允许你将一个 DataFrame 作为参数传递给一个自定义函数,这让你可以轻松地将自己的复杂逻辑也融入到链式调用中。
定义一个自定义函数:
def get_high_earners(df, salary_threshold):
"""一个自定义函数,用于筛选高薪人士"""
return df[df['salary'] > salary_threshold].super.select(['name', 'salary'])
使用 .pipe() 调用:
# 筛选薪资高于 100,000 的人 high_earners = df.super.pipe(get_high_earners, salary_threshold=100000) print(high_earners)
输出:
name salary
2 Charlie 120000
5 Frank 110000
完整实例:一个端到端的数据处理流程
让我们将所有方法组合起来,完成一个完整的数据分析任务。
任务:
- 从原始数据中,筛选出在 "Chicago" 或 "New York" 的人。
- 他们的年龄必须在 30 岁以上。
- 按他们的 薪资 从高到低排序。
- 只保留他们的 姓名、城市 和 薪资。
- 给薪资列重命名为 'annual_income'。
传统 Pandas 写法:
result_traditional = df[
(df['city'].isin(['Chicago', 'New York'])) & (df['age'] > 30)
].sort_values('salary', ascending=False)[['name', 'city', 'salary']].rename(
columns={'salary': 'annual_income'}
)
Superpandas 链式写法:
result_super = df.super.query("city.isin(['Chicago', 'New York']) and age > 30") \
.super.sort('salary', ascending=False) \
.super.select(['name', 'city', 'salary']) \
.super.rename({'salary': 'annual_income'})
print("Superpandas 结果:")
print(result_super)
输出 (两种方法结果一致):
Superpandas 结果:
name city annual_income
2 Charlie Chicago 120000
4 Eve Chicago 90000
0 Alice New York 70000
3 David New York 65000
(注意:排序结果中 Alice 和 David 的顺序取决于 pandas 的稳定排序实现,但逻辑是正确的。)
总结与对比
| 特性 | 传统 Pandas | Superpandas |
|---|---|---|
| 代码风格 | 命令式,一步一步操作 | 声明式,描述数据处理流程 |
| 可读性 | 中等,变量名可能冗长 | 高,链式调用逻辑清晰 |
| 中间变量 | 容易产生多个中间变量 | 少,代码更简洁 |
| 学习曲线 | Pandas 本身学习曲线较陡 | 在 Pandas 基础上增加新方法,易于上手 |
| 适用场景 | 所有场景,是基础 | 数据清洗、转换、分析的工作流 |
什么时候应该使用 Superpandas?
- 当你进行多步骤的数据清洗和转换时,
superpandas能让你的代码变得非常优雅。 - 当你希望代码的可读性和可维护性更高时。
- 当你喜欢函数式编程风格时。
什么时候应该坚持使用原生 Pandas?
- 当你只需要执行单个、简单的操作时,原生 Pandas 可能更直接。
- 当你进行高度优化的、性能敏感的计算时,直接使用
pandas的底层 C 实现可能更可靠。 - 当你与不熟悉
superpandas的团队成员协作时。
superpandas 是一个强大的工具,它不是要取代 pandas,而是作为 pandas 的一个“语法糖”层,让你能以一种更愉悦、更高效的方式处理数据,强烈推荐所有希望提升 Pandas 编码体验的开发者尝试使用。
