本文目录导读:

我来详细讲解如何使用Pandas进行数据分组填充,包含多种常见场景的案例:
基础准备
import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
'group': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C'],
'value': [1, np.nan, 3, np.nan, 5, np.nan, np.nan, 8],
'date': ['2024-01-01', '2024-01-02', '2024-01-03',
'2024-01-01', '2024-01-02', '2024-01-03',
'2024-01-01', '2024-01-02']
})
print("原始数据:")
print(df)
按组填充缺失值
1 用组内均值填充
# 用每组的平均值填充
df['value_fill_mean'] = df.groupby('group')['value'].transform(lambda x: x.fillna(x.mean()))
print("用组内均值填充:")
print(df[['group', 'value', 'value_fill_mean']])
2 用组内中位数填充
# 用每组的中位数填充
df['value_fill_median'] = df.groupby('group')['value'].transform(lambda x: x.fillna(x.median()))
print("用组内中位数填充:")
print(df[['group', 'value', 'value_fill_median']])
3 用组内众数填充
# 用每组的众数填充
def fill_with_mode(x):
mode_val = x.mode()
if len(mode_val) > 0:
return x.fillna(mode_val[0])
return x
df['value_fill_mode'] = df.groupby('group')['value'].transform(fill_with_mode)
向前/向后填充(时间序列)
# 按组进行前向填充
df['value_ffill'] = df.groupby('group')['value'].transform(lambda x: x.fillna(method='ffill'))
# 按组进行后向填充
df['value_bfill'] = df.groupby('group')['value'].transform(lambda x: x.fillna(method='bfill'))
print("前后填充结果:")
print(df[['group', 'value', 'value_ffill', 'value_bfill']])
复杂填充场景
1 按组填充特定值
# 不同组使用不同填充值
fill_values = {'A': 0, 'B': 100, 'C': -1}
df['value_custom'] = df.groupby('group')['value'].transform(
lambda x: x.fillna(fill_values[x.name])
)
print("自定义填充:")
print(df[['group', 'value', 'value_custom']])
2 组合填充策略
def smart_fill(series):
"""智能填充:先用ffill,再用后向填充,最后用均值"""
# 首先前向填充
result = series.fillna(method='ffill')
# 然后后向填充
result = result.fillna(method='bfill')
# 最后用均值填充
result = result.fillna(series.mean())
return result
df['value_smart'] = df.groupby('group')['value'].transform(smart_fill)
实际应用案例
1 销售数据分组填充
# 创建销售数据
sales_data = pd.DataFrame({
'store': ['Store_A', 'Store_A', 'Store_A', 'Store_B', 'Store_B', 'Store_B'],
'month': ['Jan', 'Feb', 'Mar', 'Jan', 'Feb', 'Mar'],
'sales': [1000, np.nan, 1200, np.nan, 800, np.nan],
'target': [1100, 1200, 1300, 900, 1000, 1100]
})
print("原始销售数据:")
print(sales_data)
# 按门店填充:用相邻月份的平均值填充
def fill_sales(group):
# 先用线性插值
group['sales_interpolated'] = group['sales'].interpolate(method='linear')
# 如果还有缺失,用目标的80%填充
group['sales_final'] = group['sales_interpolated'].fillna(group['target'] * 0.8)
return group
sales_data = sales_data.groupby('store').apply(fill_sales)
print("\n填充后的销售数据:")
print(sales_data)
2 学生成绩分组填充
# 创建学生成绩数据
grades_data = pd.DataFrame({
'class': ['Class_A']*4 + ['Class_B']*4,
'student': ['Tom', 'Jerry', 'Alice', 'Bob', 'Emma', 'Jack', 'Lily', 'Mike'],
'score': [85, np.nan, 92, 78, np.nan, 88, np.nan, 95]
})
print("原始成绩数据:")
print(grades_data)
# 按班级填充策略
def fill_grades(group):
# 计算班级统计信息
class_stats = {
'mean': group['score'].mean(),
'median': group['score'].median(),
'std': group['score'].std()
}
# 对不同成绩段设置不同填充策略
for idx in group[group['score'].isna()].index:
# 可以基于其他特征设置填充值
# 这里简单用中位数填充
group.loc[idx, 'score_filled'] = class_stats['median']
group['score_filled'] = group['score'].fillna(group['score_filled'])
return group
grades_data = grades_data.groupby('class').apply(fill_grades)
print("\n填充后的成绩数据:")
print(grades_data)
高级技巧
1 条件分组填充
# 根据条件选择填充方式
def conditional_fill(group):
if group['value'].isna().sum() > len(group) * 0.5: # 缺失超过50%
# 用中位数填充
return group.fillna(group.median())
else:
# 用插值法填充
return group.interpolate()
df['value_conditional'] = df.groupby('group')['value'].transform(conditional_fill)
2 滚动窗口填充
# 使用滚动窗口均值填充
def rolling_fill(series, window=2):
# 计算滚动均值
rolling_mean = series.rolling(window=window, min_periods=1).mean()
# 填充缺失值
return series.fillna(rolling_mean)
df['value_rolling'] = df.groupby('group')['value'].transform(lambda x: rolling_fill(x))
性能优化建议
# 大数据集优化
def fast_group_fill(df, group_col, value_col, method='mean'):
"""高效的组内填充函数"""
if method == 'mean':
fill_values = df.groupby(group_col)[value_col].transform('mean')
elif method == 'median':
fill_values = df.groupby(group_col)[value_col].transform('median')
elif method == 'ffill':
fill_values = df.groupby(group_col)[value_col].transform(lambda x: x.ffill())
return df[value_col].fillna(fill_values)
# 使用示例
df['value_fast'] = fast_group_fill(df, 'group', 'value', 'mean')
完整示例代码
import pandas as pd
import numpy as np
# 完整的填充示例
def complete_group_fill_example():
# 创建测试数据
df = pd.DataFrame({
'group': np.repeat(['A', 'B', 'C'], 5),
'time': np.tile(range(5), 3),
'value': [1, np.nan, 3, np.nan, 5,
np.nan, 7, np.nan, 9, 10,
11, 12, np.nan, np.nan, 15]
})
print("原始数据:")
print(df)
# 1. 简单填充
df['fill_mean'] = df.groupby('group')['value'].transform(lambda x: x.fillna(x.mean()))
df['fill_median'] = df.groupby('group')['value'].transform(lambda x: x.fillna(x.median()))
# 2. 插值填充(考虑时间顺序)
df['fill_interpolate'] = df.groupby('group')['value'].transform(
lambda x: x.interpolate(method='linear')
)
# 3. 前向填充
df['fill_ffill'] = df.groupby('group')['value'].transform(lambda x: x.ffill())
# 4. 链式填充(多重策略)
def chain_fill(series):
# 先向前填充,再向后填充,最后用均值
return series.fillna(method='ffill').fillna(method='bfill').fillna(series.mean())
df['fill_chain'] = df.groupby('group')['value'].transform(chain_fill)
print("\n所有填充结果:")
print(df[['group', 'time', 'value', 'fill_mean', 'fill_median',
'fill_interpolate', 'fill_ffill', 'fill_chain']])
return df
# 运行示例
result_df = complete_group_fill_example()
这些方法覆盖了大部分分组填充的场景,你可以根据实际需求选择合适的方法,建议在处理真实数据时,先了解数据的特点和缺失值的分布,再选择合适的填充策略。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播