最佳实践 #
编码规范 #
命名约定 #
python
import pandas as pd
import numpy as np
# DataFrame 命名:使用有意义的名称
df_sales = pd.DataFrame() # 好
df = pd.DataFrame() # 不推荐
# Series 命名:使用单数形式
series_price = pd.Series() # 好
prices = pd.Series() # 也可以
# 列名:使用小写和下划线
df['unit_price'] = 100 # 好
df['UnitPrice'] = 100 # 不推荐
# 避免使用保留字
# df['class'] = 'A' # 不推荐
df['category'] = 'A' # 好
代码组织 #
python
# 导入顺序
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 常量定义
DATA_PATH = 'data/'
OUTPUT_PATH = 'output/'
# 函数定义
def load_data(filepath):
return pd.read_csv(filepath)
def process_data(df):
return df.drop_duplicates()
# 主程序
if __name__ == '__main__':
df = load_data(DATA_PATH + 'sales.csv')
df = process_data(df)
常见陷阱 #
链式索引 #
python
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 陷阱:链式索引
# df[df['A'] > 1]['B'] = 10 # SettingWithCopyWarning
# 解决方案:使用 loc
df.loc[df['A'] > 1, 'B'] = 10
原地修改 #
python
# 陷阱:原地修改可能不按预期工作
# df.drop('A', axis=1, inplace=True) # 有时会有问题
# 解决方案:重新赋值
df = df.drop('A', axis=1)
索引重置 #
python
# 陷阱:过滤后索引不连续
df_filtered = df[df['A'] > 1]
# print(df_filtered.loc[0]) # 可能报错
# 解决方案:重置索引
df_filtered = df_filtered.reset_index(drop=True)
副本与视图 #
python
# 陷阱:意外修改原数据
subset = df[df['A'] > 1]
subset['B'] = 10 # SettingWithCopyWarning
# 解决方案:显式复制
subset = df[df['A'] > 1].copy()
subset['B'] = 10
类型推断 #
python
# 陷阱:混合类型列
df = pd.DataFrame({'col': [1, 2, 'three']})
# df['col'].sum() # 可能不是预期结果
# 解决方案:明确类型
df['col'] = pd.to_numeric(df['col'], errors='coerce')
性能技巧 #
向量化操作 #
python
import numpy as np
df = pd.DataFrame({'value': np.random.rand(100000)})
# 慢:循环
def slow_method():
result = []
for i in range(len(df)):
result.append(df.iloc[i]['value'] * 2)
return result
# 快:向量化
def fast_method():
return df['value'] * 2
类型优化 #
python
# 优化前
df = pd.DataFrame({
'small_int': np.random.randint(0, 100, 100000),
'category': np.random.choice(['A', 'B', 'C'], 100000)
})
print(df.memory_usage(deep=True))
# 优化后
df['small_int'] = df['small_int'].astype('int8')
df['category'] = df['category'].astype('category')
print(df.memory_usage(deep=True))
避免重复计算 #
python
# 不推荐:重复计算
result1 = df[df['category'] == 'A']['value'].mean()
result2 = df[df['category'] == 'A']['value'].sum()
result3 = df[df['category'] == 'A']['value'].std()
# 推荐:一次计算
grouped = df[df['category'] == 'A']['value']
result1 = grouped.mean()
result2 = grouped.sum()
result3 = grouped.std()
# 或使用 agg
results = df[df['category'] == 'A']['value'].agg(['mean', 'sum', 'std'])
数据处理技巧 #
使用 query #
python
# 复杂条件使用 query
result = df.query('category == "A" and value > 100 and region in ["North", "South"]')
# 比
# result = df[(df['category'] == 'A') & (df['value'] > 100) & df['region'].isin(['North', 'South'])]
使用 isin #
python
# 多值匹配使用 isin
result = df[df['category'].isin(['A', 'B', 'C'])]
# 比
# result = df[(df['category'] == 'A') | (df['category'] == 'B') | (df['category'] == 'C')]
使用 np.where #
python
import numpy as np
# 条件赋值
df['level'] = np.where(df['value'] > 100, 'high', 'low')
# 比
# df['level'] = df['value'].apply(lambda x: 'high' if x > 100 else 'low')
使用 np.select #
python
# 多条件赋值
conditions = [
df['value'] > 100,
df['value'] > 50,
df['value'] > 0
]
choices = ['high', 'medium', 'low']
df['level'] = np.select(conditions, choices, default='zero')
调试技巧 #
查看数据 #
python
# 查看基本信息
print(df.info())
print(df.describe())
print(df.head())
print(df.tail())
# 查看缺失值
print(df.isna().sum())
# 查看唯一值
print(df['category'].nunique())
print(df['category'].unique())
检查数据类型 #
python
# 查看数据类型
print(df.dtypes)
# 检查特定列类型
print(df['value'].dtype)
# 类型推断
print(df.infer_objects().dtypes)
逐步调试 #
python
def process_data(df):
print(f"Step 1 - Input shape: {df.shape}")
df = df.drop_duplicates()
print(f"Step 2 - After drop_duplicates: {df.shape}")
df = df.dropna()
print(f"Step 3 - After dropna: {df.shape}")
df['total'] = df['quantity'] * df['price']
print(f"Step 4 - After adding column: {df.shape}")
return df
代码质量 #
函数文档 #
python
def calculate_metrics(df, group_column, value_column):
"""
计算分组指标
Parameters
----------
df : pd.DataFrame
输入数据
group_column : str
分组列名
value_column : str
数值列名
Returns
-------
pd.DataFrame
分组统计结果
"""
return df.groupby(group_column)[value_column].agg(['mean', 'std', 'count'])
类型提示 #
python
from typing import Union, List
def filter_data(
df: pd.DataFrame,
column: str,
values: Union[List, str]
) -> pd.DataFrame:
return df[df[column].isin(values)]
单元测试 #
python
import unittest
class TestDataProcessing(unittest.TestCase):
def setUp(self):
self.df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
def test_add_column(self):
result = self.df.assign(C=self.df['A'] + self.df['B'])
self.assertIn('C', result.columns)
self.assertEqual(result['C'].iloc[0], 5)
if __name__ == '__main__':
unittest.main()
最佳实践清单 #
text
┌─────────────────────────────────────────────────────────────┐
│ 最佳实践清单 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 编码规范 │
│ □ 使用有意义的变量名 │
│ □ 遵循 PEP 8 风格 │
│ □ 添加必要的注释和文档 │
│ │
│ 数据处理 │
│ □ 使用 loc 替代链式索引 │
│ □ 使用 copy() 避免意外修改 │
│ □ 处理后重置索引 │
│ │
│ 性能优化 │
│ □ 使用向量化操作 │
│ □ 选择合适的数据类型 │
│ □ 避免重复计算 │
│ │
│ 错误处理 │
│ □ 验证输入数据 │
│ □ 处理缺失值和异常值 │
│ □ 添加适当的错误处理 │
│ │
│ 代码质量 │
│ □ 编写可复用的函数 │
│ □ 添加单元测试 │
│ □ 进行代码审查 │
│ │
└─────────────────────────────────────────────────────────────┘
总结 #
恭喜你完成了 Pandas 完全指南的学习!你已经掌握了:
- 基础入门:Pandas 简介、安装配置
- 核心数据结构:Series、DataFrame、数据类型、索引
- 数据处理:数据读写、选择、过滤、清洗
- 数据分析:统计分析、分组聚合、合并连接、数据重塑
- 高级主题:时间序列、可视化、性能优化、高级操作
- 实战应用:数据分析实战、数据管道、最佳实践
继续练习和实践,你将成为 Pandas 专家!
最后更新:2026-04-04