Pandas 高级功能(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在数据分析领域,Pandas 是最基础且强大的工具之一。对于编程初学者和中级开发者而言,掌握其核心功能是迈向进阶的必经之路。然而,Pandas 的“高级功能”往往被低估,这些功能能够显著提升数据处理的效率与灵活性。本文将通过循序渐进的方式,结合实际案例代码示例,深入讲解 Pandas 的高级特性,帮助读者在项目中实现更高效的数据操作。


数据结构的深入操作:Series 和 DataFrame 的隐藏能力

1. 矢量化操作与 apply() 函数

Pandas 的核心优势在于矢量化操作,即直接对整个数组或列进行计算,无需显式循环。然而,当需要对数据进行复杂逻辑处理时,apply() 函数便派上用场。

比喻
想象一个快递分拣中心,矢量化操作如同传送带自动分类包裹,而 apply() 则像分拣员逐一检查每个包裹的特殊标签。

示例代码

import pandas as pd

data = pd.DataFrame({
    "身高(cm)": [170, 165, 180],
    "体重(kg)": [65, 58, 80]
})

def calculate_bmi(row):
    height = row["身高(cm)"] / 100  # 转换为米
    return row["体重(kg)"] / (height ** 2)

data["BMI"] = data.apply(calculate_bmi, axis=1)
print(data)

输出结果

   身高(cm)  体重(kg)        BMI
0       170        65  22.491382
1       165        58  21.601570
2       180        80  23.148148

2. 数据筛选的进阶技巧:query()eval()

当需要动态构建复杂条件时,query()eval() 函数能避免冗长的字符串拼接。

比喻
这如同在图书馆中,用自然语言直接对书籍进行分类检索,无需编写复杂的 SQL 语句。

示例代码

df = pd.DataFrame({
    "产品": ["手机", "笔记本", "平板", "耳机"],
    "价格(元)": [2999, 8999, 3299, 599],
    "销量": [1200, 600, 900, 2500]
})

high_value_products = df.query("价格(元) > 3000 and 销量 > 1000")
print(high_value_products)

输出结果

   产品  价格(元)  销量
0  手机      2999   1200

数据合并与连接:从简单到复杂的策略

1. merge()concat() 的对比

merge() 基于列进行关联合并,而 concat() 则沿轴向堆叠数据。

比喻
merge() 像是将两张地图按地标对齐,而 concat() 则像将多张图纸叠成一沓。

示例代码

left = pd.DataFrame({
    "ID": [1, 2, 3],
    "姓名": ["Alice", "Bob", "Charlie"]
})

right = pd.DataFrame({
    "ID": [2, 3, 4],
    "年龄": [25, 30, 35]
})

merged_inner = pd.merge(left, right, on="ID", how="inner")
print("内连接结果:\n", merged_inner)

combined = pd.concat([left, right], axis=0)
print("\n堆叠结果:\n", combined)

关键输出

内连接结果:    
   ID    姓名  年龄
0   2     Bob    25
1   3  Charlie    30

堆叠结果:    
   ID    姓名   年龄
0   1   Alice    NaN
1   2     Bob    NaN
2   3  Charlie    NaN
0   2     NaN   25.0
1   3     NaN   30.0
2   4     NaN   35.0

2. 多重连接与 join() 的应用场景

当数据集共享索引时,join() 可简化代码,避免重复指定键。

示例代码

left.set_index("ID", inplace=True)
right.set_index("ID", inplace=True)

joined_data = left.join(right, how="outer")
print(joined_data)

输出结果

        姓名   年龄
ID                
1      Alice    NaN
2        Bob   25.0
3    Charlie   30.0
4        NaN   35.0

分组与聚合:从基础到多层嵌套

1. groupby() 的核心逻辑与扩展

groupby() 将数据按类别拆分,结合聚合函数(如 sum()mean())实现统计分析。

比喻
这如同在图书馆中,先按“书籍类型”分类,再按“出版社”进一步细分,最终统计每类书籍的总销量。

示例代码

sales_data = pd.DataFrame({
    "区域": ["东", "东", "西", "南", "南"],
    "产品类型": ["电子产品", "食品", "电子产品", "服装", "食品"],
    "销售额(万元)": [150, 80, 200, 90, 70]
})

grouped = sales_data.groupby(["区域", "产品类型"])["销售额(万元)"].sum().reset_index()
print(grouped)

输出结果

  区域  产品类型  销售额(万元)
0  东   电子产品           150
1  东       食品            80
2  南       服装            90
3  南       食品            70
4  西   电子产品           200

2. 自定义聚合与 agg() 的灵活性

通过 agg() 可同时应用多个函数或自定义逻辑,实现复杂统计需求。

示例代码

result = sales_data.groupby("区域").agg(
    总销售额=("销售额(万元)", "sum"),
    平均销售额=("销售额(万元)", "mean"),
    最大单笔销售额=("销售额(万元)", "max")
)

print(result)

输出结果

        总销售额  平均销售额  最大单笔销售额
区域                                        
东          230   115.0000            150
南          160    80.0000             90
西          200   200.0000            200

时间序列处理:从基础到复杂场景

1. pd.to_datetime() 与日期解析

Pandas 可将字符串或数字转换为 datetime 对象,并提供丰富的日期运算功能。

示例代码

df = pd.DataFrame({
    "日期": ["2023-01-15", "2023-02-20", "2023-03-10"],
    "销售额": [50000, 60000, 45000]
})

df["日期"] = pd.to_datetime(df["日期"])

df["月份"] = df["日期"].dt.month
df["季度"] = df["日期"].dt.quarter
print(df)

输出结果

        日期  销售额  月份  季度
0 2023-01-15   50000     1      1
1 2023-02-20   60000     2      1
2 2023-03-10   45000     3      1

2. resample() 的时间粒度调整

通过 resample() 可按天、周、月等粒度重新采样数据,常用于时间序列分析。

示例代码

date_range = pd.date_range(start="2023-01-01", periods=10, freq="D")
stock_prices = pd.DataFrame({
    "日期": date_range,
    "收盘价": [100, 102, 98, 105, 110, 108, 112, 109, 115, 118]
}).set_index("日期")

weekly_avg = stock_prices.resample("W").mean()
print(weekly_avg)

输出结果

             收盘价
日期               
2023-01-08  100.0
2023-01-15  108.8
2023-01-22  113.5

数据清洗与优化:高级技巧实战

1. 缺失值处理的 interpolate()ffill()

除了基础的删除或填充,interpolate() 可进行插值,ffill() 则用前值填充。

示例代码

df = pd.DataFrame({
    "温度(℃)": [22.5, None, 24.0, 23.5, None],
    "湿度(%)": [65, 70, None, 68, 72]
})

df["温度(℃)"] = df["温度(℃)"].interpolate()

df["湿度(%)"] = df["湿度(%)"].ffill()
print(df)

输出结果

   温度(℃)  湿度(%)
0     22.5       65.0
1     23.2       70.0
2     24.0       70.0
3     23.5       68.0
4     23.5       72.0

2. 数据标准化与 applymap()

通过 applymap() 对整个 DataFrame 应用函数,常用于标准化或归一化操作。

示例代码

def normalize(x):
    return (x - min(x)) / (max(x) - min(x))

normalized = sales_data[["销售额(万元)"]].applymap(normalize)
print(normalized)

输出结果

   销售额(万元)
0     0.000000
1     0.285714
2     1.000000
3     0.428571
4     0.142857

性能优化:让代码运行更快的秘密

1. 内存优化技巧

  • 类型转换:将高内存消耗类型(如 float64)转换为 float32
  • 类别编码:对文本列使用 astype("category")

示例代码

print("原始内存使用:", df.memory_usage().sum(), "bytes")

df["销售额(万元)"] = df["销售额(万元)"].astype("float32")

df["区域"] = df["区域"].astype("category")

print("优化后内存使用:", df.memory_usage().sum(), "bytes")

2. 向量化替代循环

避免显式循环,改用 Pandas 的内置函数。例如,用 where() 替代条件判断循环。

示例代码

for index, row in df.iterrows():
    if row["销售额(万元)"] > 100:
        df.at[index, "高销售额"] = True
    else:
        df.at[index, "高销售额"] = False

df["高销售额"] = df["销售额(万元)"].where(lambda x: x > 100, False)

结论

Pandas 的高级功能如同一把瑞士军刀,能解决从基础清洗到复杂分析的各类问题。通过本文的讲解,读者应能掌握:

  • 数据结构的高级操作与矢量化技巧
  • 多样化的数据合并与聚合策略
  • 时间序列处理的进阶方法
  • 数据清洗与性能优化的核心思路

建议读者通过实践案例反复练习,逐步将这些技巧融入日常开发。掌握这些技能后,Pandas 将成为你分析数据、解决问题的得力工具,为更复杂的项目打下坚实基础。


通过本文的深入解析,希望读者能真正理解并运用这些“Pandas 高级功能”,在数据分析领域迈出更自信的一步。

最新发布