Pandas是Python数据分析的核心库,掌握一些实用技巧能极大提升数据处理效率。以下是三大核心技巧:
链式操作可以避免创建过多中间变量,使代码更简洁易读。
import pandas as pd
import numpy as np
# 创建示例数据
data = {
'姓名': ['张三', '李四', '王五', '赵六', '钱七'],
'年龄': [25, 30, 35, 28, 32],
'城市': ['北京', '上海', '北京', '广州', '深圳'],
'薪资': [8000, 12000, 9500, 8500, 11000],
'入职年份': [2018, 2015, 2019, 2017, 2016]
}
df = pd.DataFrame(data)
# 传统方式(创建多个中间变量)
df_filtered = df[df['年龄'] > 28]
df_sorted = df_filtered.sort_values('薪资', ascending=False)
df_result = df_sorted[['姓名', '城市', '薪资']]
print("传统方式:")
print(df_result)
# 链式操作方式
result = (df[df['年龄'] > 28] # 筛选年龄大于28
.sort_values('薪资', ascending=False) # 按薪资降序
.loc[:, ['姓名', '城市', '薪资']] # 选择特定列
.reset_index(drop=True)) # 重置索引
print("\n链式操作方式:")
print(result)
# 更复杂的链式操作示例
result2 = (df
.assign(工龄=lambda x: 2023 - x['入职年份'], # 添加新列
薪资级别=lambda x: np.where(x['薪资'] > 10000, '高', '中'))
.query('工龄 >= 4') # 使用query筛选
.groupby('城市')
.agg({'薪资': ['mean', 'max'], '年龄': 'mean'})
.round(2))
print("\n复杂链式操作(添加列、筛选、分组聚合):")
print(result2)
# 创建含缺失值的数据
df_nan = pd.DataFrame({
'A': [1, 2, np.nan, 4, 5],
'B': [np.nan, 2, 3, np.nan, 5],
'C': [1, 2, 3, 4, 5],
'分组': ['X', 'X', 'Y', 'Y', 'X']
})
print("原始数据:")
print(df_nan)
# 技巧1:向前/向后填充(特别适合时间序列)
print("\n向前填充:")
print(df_nan.fillna(method='ffill'))
print("\n向后填充:")
print(df_nan.fillna(method='bfill'))
# 技巧2:分组填充(按组别使用组内均值填充)
print("\n按分组用组内均值填充:")
df_nan['A'] = df_nan.groupby('分组')['A'].transform(
lambda x: x.fillna(x.mean())
)
print(df_nan)
# 技巧3:插值法(适合有序数据)
df_time = pd.DataFrame({
'日期': pd.date_range('2023-01-01', periods=10, freq='D'),
'数值': [1, np.nan, np.nan, np.nan, 5, 6, np.nan, 8, np.nan, 10]
})
df_time.set_index('日期', inplace=True)
print("\n插值法填充:")
print(df_time.interpolate(method='time')) # 考虑时间间隔的插值
# 技巧4:多重填充策略
print("\n不同列使用不同填充策略:")
print(df_nan.fillna({
'A': df_nan['A'].mean(), # A列用均值填充
'B': df_nan['B'].median(), # B列用中位数填充
'C': 0 # C列用0填充
}))
# 创建销售数据示例
sales_data = pd.DataFrame({
'日期': pd.date_range('2023-01-01', periods=30, freq='D').tolist() * 2,
'产品': ['A'] * 30 + ['B'] * 30,
'地区': np.random.choice(['北京', '上海', '广州'], 60),
'销售员': np.random.choice(['张三', '李四', '王五'], 60),
'销售额': np.random.randint(100, 1000, 60),
'数量': np.random.randint(1, 20, 60)
})
sales_data['月份'] = sales_data['日期'].dt.month
print("原始销售数据(前10行):")
print(sales_data.head(10))
# 基础数据透视
print("\n1. 基础透视 - 各地区各产品的总销售额:")
pivot1 = pd.pivot_table(
sales_data,
values='销售额',
index='地区',
columns='产品',
aggfunc='sum',
fill_value=0
)
print(pivot1)
# 多维度聚合
print("\n2. 多维度聚合 - 各地区各产品的销售额均值和总量:")
pivot2 = pd.pivot_table(
sales_data,
values=['销售额', '数量'],
index=['地区', '月份'],
columns='产品',
aggfunc={'销售额': ['mean', 'sum'], '数量': 'sum'},
fill_value=0,
margins=True, # 添加总计
margins_name='总计'
)
print(pivot2)
# 多重索引处理
print("\n3. 扁平化多重索引列:")
pivot_flat = pivot2.copy()
# 将多层列索引合并为单层
pivot_flat.columns = ['_'.join(col).strip() for col in pivot_flat.columns.values]
print(pivot_flat.head())
# 交叉表crosstab(用于频率统计)
print("\n4. 使用crosstab统计各地区销售员出现的频率:")
cross_tab = pd.crosstab(
index=sales_data['地区'],
columns=sales_data['销售员'],
values=sales_data['销售额'],
aggfunc='count',
normalize='index' # 按行标准化,显示比例
)
print(cross_tab.round(2))
# 综合示例:从原始数据到分析报告
# 1. 数据读取与清洗
df = pd.DataFrame({
'订单号': range(1001, 1021),
'客户ID': np.random.choice(['C001', 'C002', 'C003', 'C004', 'C005'], 20),
'产品类别': np.random.choice(['电子产品', '服装', '食品', '书籍'], 20),
'销售额': np.random.uniform(50, 500, 20).round(2),
'订单日期': pd.date_range('2023-01-01', periods=20, freq='D'),
'评分': np.random.choice([1, 2, 3, 4, 5, np.nan], 20, p=[0.05, 0.1, 0.15, 0.3, 0.35, 0.05])
})
# 2. 使用链式操作进行完整处理
analysis_report = (
df
# 数据清洗
.assign(订单日期=lambda x: pd.to_datetime(x['订单日期']),
月份=lambda x: x['订单日期'].dt.month)
.fillna({'评分': df['评分'].median()}) # 用中位数填充评分缺失值
# 添加衍生指标
.assign(销售额区间=lambda x: pd.cut(x['销售额'],
bins=[0, 100, 300, 500],
labels=['低', '中', '高']))
# 数据筛选
.query('销售额 > 100')
# 数据透视分析
.pivot_table(
values='销售额',
index=['月份', '产品类别'],
columns='销售额区间',
aggfunc=['count', 'sum', 'mean'],
fill_value=0,
margins=True
)
# 结果格式化
.round(2)
.sort_values(by=('count', '高'), ascending=False)
)
print("数据分析报告:")
print(analysis_report)
# 3. 结果导出
analysis_report.to_excel('销售分析报告.xlsx')
print("\n分析报告已保存为 '销售分析报告.xlsx'")
这些技巧能显著提升数据处理效率和代码可维护性。建议在实际工作中多练习,根据具体场景灵活应用。