1. Pandas速查笔记:数据分析师的高效生存指南
第一次接触Pandas时,我被它复杂的API搞得晕头转向。直到某次项目Deadline前夜,我才意识到建立自己的速查体系有多重要——这份笔记就是从那时开始积累的实战精华。不同于官方文档的全面性,这里只保留你80%时间会用到的20%核心功能,每个技巧都经过真实业务场景验证。
2. 基础操作:从混乱到有序的数据处理
2.1 数据结构认知革命
DataFrame不是简单的"Excel表格",而是带有索引的二维标签化数据结构。理解这点能避免后续90%的报错:
import pandas as pd df = pd.DataFrame({ 'A': [1, 2, None], # 自动识别为float64类型 'B': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03']), 'C': pd.Categorical(['男', '女', '男']) })警告:混合类型的列会被强制转换为object类型,严重影响性能。建议用
df.dtypes确认类型,必要时用astype()强制转换。
2.2 数据清洗实战套路
缺失值处理不要只会fillna(),根据业务场景选择策略:
- 时间序列:
df.interpolate(method='time')按时间插值 - 分类数据:
df['C'].fillna(df['C'].mode()[0])用众数填充 - 连续变量:
df['A'].fillna(df.groupby('C')['A'].transform('median'))按分组中位数填充
去重的高级玩法:
# 保留某列值最大的行 df.loc[df.groupby('去重依据列')['排序列'].idxmax()]3. 数据查询:像SQL一样思考但更快
3.1 索引查询的三种范式
- 位置索引:
df.iloc[0:5, [1,3]](第0-4行,第1&3列) - 标签索引:
df.loc[df.index[0:5], ['A','C']] - 布尔索引:
df[(df.A > 1) & ~df.B.isnull()]
踩坑记录:
df[df.A > 1 and df.B.notna()]会报错,必须用&替代and,不同条件要加括号
3.2 高性能查询技巧
对于千万级数据,这些优化可提升10倍速度:
# 将常用查询列设为索引 df.set_index('日期').sort_index() # 先排序才能用快速查询 df.loc['2023-01':'2023-02'] # 区间查询比布尔索引快100倍 # 使用query方法(语法更简洁) df.query('A > 1 and C == "男"')4. 高级应用:GroupBy的本质是拆分-应用-组合
4.1 分组聚合的完整流程
# 定义聚合规则 agg_rules = { 'A': ['sum', lambda x: x.max() - x.min()], # 内置函数+自定义 'B': 'count' } result = ( df.groupby('C', as_index=False) # 不将分组列作为索引 .agg(agg_rules) .rename(columns={'<lambda>': 'range'}) # 重命名自定义函数列 )4.2 分组后处理技巧
- 过滤:
df.groupby('C').filter(lambda x: x['A'].mean() > 1) - 转换:
df['A_rank'] = df.groupby('C')['A'].rank() - 应用:
df.groupby('C').apply(lambda x: x.sort_values('B').head(1))
5. 时间序列处理:Pandas的杀手锏
5.1 重采样与滚动计算
# 将日数据转为周数据(周一到周日) weekly = ( df.set_index('B') .resample('W-MON') # 周起始日可调 .agg({'A': 'mean', 'C': 'last'}) ) # 7天滚动平均值(中心窗口) df['7d_avg'] = df['A'].rolling(7, center=True).mean()5.2 时区处理最佳实践
# 本地时间转UTC df['utc_time'] = ( pd.to_datetime(df['local_time']) .dt.tz_localize('Asia/Shanghai') .dt.tz_convert('UTC') ) # 处理夏令时跳跃点 df = df[~df['utc_time'].dt.floor('D').duplicated(keep='first')]6. 性能优化:从分钟级到秒级的蜕变
6.1 类型优化检查清单
- 将
object类型转为category(分类数据) - 将
float64降级为float32(精度允许时) - 用
pd.to_numeric()处理数字字符串 - 用
parse_dates参数在读取时直接转换日期
6.2 内存压缩技巧
def reduce_mem_usage(df): for col in df.columns: col_type = df[col].dtype if col_type != object: c_min = df[col].min() c_max = df[col].max() if str(col_type)[:3] == 'int': if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max: df[col] = df[col].astype(np.int8) # 类似处理int16/int32... else: # 处理float类型 else: # 尝试转为category return df7. 常见报错解决方案速查表
| 错误信息 | 原因分析 | 解决方案 |
|---|---|---|
| SettingWithCopyWarning | 链式赋值导致的视图问题 | 改用df.loc[row_indexer,col_indexer]显式索引 |
| KeyError: "[列名]" not in index | 列名拼写错误或包含空格 | df.columns = df.columns.str.strip() |
| ValueError: cannot reindex on an axis with duplicate labels | 索引重复 | df = df[~df.index.duplicated(keep='first')] |
| MemoryError | 数据量超过内存限制 | 使用dask库或分块处理 |
8. 效率工具链推荐
- 数据探查:
df.profile_report()(pandas-profiling库) - 交互查询:
qgrid.show_grid(df)(qgrid库) - 可视化:
df.plot()背后调用matplotlib,但建议直接使用plotly express:import plotly.express as px px.scatter(df, x='A', y='B', color='C', trendline='ols')
9. 从1到100的进阶路线
当基础操作熟练后,建议深入研究:
- 自定义扩展类型(ExtensionArray)
- 通过
eval()实现表达式优化 - 与PyArrow的深度集成
- 在JIT环境下使用(numba加速)
最后分享一个冷知识:在Jupyter中,df.T比df.transpose()输入更快——这正体现了Pandas哲学:为实际工作流程优化,而非理论完美性。