🏠 首页 攻略 Pandas 数据分析实战:10 个提升效率的实用技巧

Pandas 数据分析实战:10 个提升效率的实用技巧

Pandas 是 Python 数据分析的核心工具。本文整理了 10 个实用技巧,从性能优化到高级操作,涵盖日常数据分析中最常遇到的场景,附完整代码示例。

数据分析这事儿,Pandas 几乎是绕不开的。

无论你是做电商报表、用户行为分析,还是简单的 Excel 替代方案,Pandas 都能搞定。但很多人用了半年,还停留在 read_csv()groupby() 的基础用法。

今天分享 10 个真正能提升效率的技巧。每个都有代码示例,看完就能用。

技巧 1:用 .pipe() 链式操作

很多初学者写数据分析代码像这样:

df = pd.read_csv('data.csv')
df = df.dropna()
df = df[df['age'] > 18]
df = df.groupby('city').mean()

这段代码的问题是每个中间变量都是临时副本,内存占用翻倍。

.pipe() 可以写成链式:

result = (pd.read_csv('data.csv')
    .pipe(lambda x: x.dropna())
    .pipe(lambda x: x[x['age'] > 18])
    .pipe(lambda x: x.groupby('city').mean()))

更优雅的做法是定义函数:

def clean_data(df):
    return df.dropna().query('age > 18')

def aggregate_by_city(df):
    return df.groupby('city').mean()

result = (pd.read_csv('data.csv')
    .pipe(clean_data)
    .pipe(aggregate_by_city))

技巧 2:用 .loc 代替 .ix

.ix 已经被废弃了。现在统一用 .loc(标签索引)和 .iloc(位置索引)。

# 错误写法
df.ix[0:10, 'name']

# 正确写法
df.loc[0:10, 'name']  # 包含第 10 行
df.iloc[0:10, 1]       # 不包含第 10 行

记住一个原则:.loc 闭区间,.iloc 左闭右开。

技巧 3:处理缺失值的正确姿势

dropna() 是最粗暴的方式。很多时候你应该填充而不是删除。

# 数值列用中位数填充
df['salary'] = df['salary'].fillna(df['salary'].median())

# 分类列用众数填充
df['city'] = df['city'].fillna(df['city'].mode()[0])

# 时间序列用前向填充
df['value'] = df['value'].ffill()

fillna() 还支持字典映射,不同列用不同策略:

df.fillna({
    'age': df['age'].median(),
    'city': '未知',
    'salary': 0
})

技巧 4:用 categorical 类型节省内存

处理大表时,字符串列特别吃内存。转成 categorical 类型能大幅减少占用。

# 原始数据
df = pd.read_csv('large_dataset.csv')
print(df.memory_usage(deep=True).sum() / 1024**2)
# 输出:~500 MB

# 转换后
df['category'] = df['category'].astype('category')
df['status'] = df['status'].astype('category')
print(df.memory_usage(deep=True).sum() / 1024**2)
# 输出:~120 MB

内存减少了 76%。这对处理超过 1GB 的数据集特别有用。

技巧 5:高效的多表合并

merge() 是最常用的合并方式,但很多人不知道它可以一次合并多个表。

# 传统做法
df1 = pd.merge(sales, products, on='product_id')
df2 = pd.merge(df1, customers, on='customer_id')
result = pd.merge(df2, regions, on='region_id')

# 链式做法
result = (sales
    .merge(products, on='product_id')
    .merge(customers, on='customer_id')
    .merge(regions, on='region_id'))

如果两个表的连接键名称不同:

sales.merge(products, left_on='prod_id', right_on='id', how='left')

技巧 6:用 query() 替代布尔索引

当过滤条件比较复杂时,query() 比布尔索引更易读。

# 传统写法
df[(df['age'] > 18) & (df['city'] == '北京') & (df['score'] >= 60)]

# query 写法
df.query('age > 18 and city == "北京" and score >= 60')

还可以引用外部变量:

min_score = 60
df.query('score >= @min_score')

技巧 7:快速时间序列重采样

时间序列分析中,按天/周/月聚合数据是常见需求。

df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')

# 按周聚合
weekly = df.resample('W').agg({
    'revenue': 'sum',
    'orders': 'count',
    'avg_value': 'mean'
})

# 按月滚动窗口
monthly = df['revenue'].rolling('30D').mean()

常用频率缩写:

  • D = 天
  • W = 周
  • M = 月末
  • Q = 季度末
  • H = 小时

技巧 8:透视表和交叉表

pivot_table() 是 Excel 透视表的 Python 等价物。

pivot = pd.pivot_table(
    df,
    values='revenue',
    index='city',
    columns='month',
    aggfunc='sum',
    fill_value=0
)

crosstab() 适合做分类变量的交叉分析:

ct = pd.crosstab(df['gender'], df['purchase_status'], margins=True)

技巧 9:避免循环,善用向量化操作

apply() 比循环快,但向量化操作更快。

# 慢:apply
df['discount'] = df['price'].apply(lambda x: x * 0.9 if x > 100 else x)

# 更快:np.where
import numpy as np
df['discount'] = np.where(df['price'] > 100, df['price'] * 0.9, df['price'])

# 最快:向量化运算
mask = df['price'] > 100
df.loc[mask, 'discount'] = df.loc[mask, 'price'] * 0.9
df.loc[~mask, 'discount'] = df.loc[~mask, 'price']

数据量超过 10 万行时,这个差距会非常明显。

技巧 10:用 profile_report 做快速数据探索

遇到新数据集,先用 ydata-profiling 生成一份完整的分析报告。

pip install ydata-profiling
from ydata_profiling import ProfileReport

df = pd.read_csv('data.csv')
report = ProfileReport(df, title='数据探索报告')
report.to_file('report.html')

生成的 HTML 报告会告诉你:

  • 每个字段的数据类型和缺失率
  • 数值字段的分布直方图
  • 字段之间的相关性热力图
  • 异常值检测

10 秒钟就能了解一个数据集的全貌,比手动写 20 行探索代码快得多。

总结

这 10 个技巧覆盖了数据分析中最常见的场景。不用全部记住,挑几个对你最有用的先用起来就好。

你平时用 Pandas 最常遇到的问题是什么?评论区聊聊。