Pandas中数据分组进阶以及数据透视表
一、数据分组步骤
1.用groupby进行分组
2.对分组数据进行聚合、转换和过滤
3.应用自定义函数处理分组之后的数据
二、分组基础
概念
类似于SQL中的GROUP BY 的操作,按照字段进行分组,对每组数据进行进一步处理并返回单个值的操作称为聚合。
示例
# 加载数据
df = pd.read_csv('data/gapminder.tsv', sep='\t')
# 按year分组,计算lifeExp的平均值
df.groupby('year').lifeExp.mean()
上述操作等价于手动筛选每一年的数据并计算平均值,groupby自动完成这一重复过程并整合结果。
三:聚合
1.内置聚合方法:
说明 | Pandas 方法 | Numpy 函数 |
---|---|---|
频率统计(不含 NaN) | count | np.count_nonzero |
频率统计(含 NaN) | size | - |
求平均值 | mean | np.mean |
标准差 | std | np.std |
最小值 | min | np.min |
分位数 | quantile() | np.percentile() |
最大值 | max | np.max |
求和 | sum | np.sum |
方差 | var | np.var |
综合统计 | describe | - |
返回第一行 | first | - |
返回最后一行 | last | - |
返回第 N 行 | nth | - |
示例:df.groupby('continent').lifeExp.describe()返回各州寿命的多项统计量
2.聚合函数使用
可使用agg或者aggregate(两者效果一致)调用函数,支持numpy函数、自定义函数。
自定义函数实例:
def my_mean(values):n = len(values)sum = 0for value in values:sum += valuereturn sum / n
# 调用
df.groupby('year').lifeExp.agg(my_mean)
自定义多参数函数实例(计算与全局平均值的差值):
def my_mean_diff(values, diff_value):n = len(values)sum = 0for value in values:sum += valuemean = sum / nreturn mean - diff_value
global_mean = df.lifeExp.mean()
df.groupby('year').lifeExp.agg(my_mean_diff, diff_value=global_mean)
3.多函数与多字段聚合:
传入函数列表同时计算多个聚合结果:
result = df.groupby('year')['lifeExp'].agg(['count', 'mean', 'std'])
传入字典对不同字段使用不同聚合方式:
print(df.groupby('year').agg({'lifeExp':'mean','pop':'max','gdpPercap':'max'
}).rename(columns={'pop':'pop_max','gdpPercap':'gdp_percap_max','life':'life_max'}).reset_index())
四、转换操作
1.特点
将数据传递给函数进行转换,不减少数据量(与聚合返回单个值不同)。
2.自定义函数替换示例:
def my_zscore(x):return (x - x.mean()) / x.std()
# 按年分组计算z分数
df.groupby('year').lifeExp.transform(my_zscore)
3.分组来填充缺失值:
# 构建含缺失值的数据
tips_10 = pd.read_csv('data/tips.csv').sample(10, random_state=42)
tips_10.loc[np.random.permutation(tips_10.index)[:4], 'total_bill'] = np.NaN
# 定义填充函数
def fill_na_mean(x):avg = x.mean()return x.fillna(avg)
# 按性别分组填充
total_bill_group_mean = tips_10.groupby('sex').total_bill.transform(fill_na_mean)
五、过滤操作
通过filter方法传入返回布尔值的函数,过滤返回False的数据。
示例(过滤用餐人数较少的组):
tips = pd.read_csv('data/tips.csv')
# 过滤掉人数计数≤30的组
tips_filtered = tips.groupby('size').filter(lambda x: x['size'].count() > 30)
六、DataFrameGroupBy对象
1.创建与属性
在调用groupby后得到DataFrameGroupby对象,如grouped = tips_10.groupby('sex')。
通过groups属性查看分组的索引信息,grouped.groups返回各组对应的原始数据行索引。
2.分组计算与选择
直接在对象上进行聚合、转换等操作,如grouped.mean(numeric_only = True)计算数值列平均值。
通过get_group选择特定分组,如female = grouped.get_group('Female')。
3.遍历分组
可通过for循坏遍历分组,每个分组为元组(包含组名和对应DataFrame):
for sex_group in grouped:print(sex_group[0]) # 组名(如'Female')print(sex_group[1]) # 组数据(DataFrame)
4.多字段分组:
传入多个字段进行分组,如group_avg = tips_10.groupby(['sex','time']).mean(),返回MultiIndex结果。
可通过reset_index()或as_index = False将结果转为普通DataDrame:
group_avg.reset_index()
# 或分组时设置
tips_10.groupby(['sex', 'time'], as_index=False).mean()
七、分组总结
1.分组是数据分析的重要操作,可从不同角度观察数据。
2.分组后得到的DataFrameGroupBy
对象支持聚合、转换、过滤操作。
3.处理分组数据可使用内置函数或自定义函数,支持单字段和多字段分组,多字段分组结果可转为普通 DataFrame。
八、数据透视表
1.概念
数据透视表是一种交互式的数据汇总工具,能够对数据进行灵活的分组、聚合和分析。它的核心特点是可以动态调整数据的展示结构,通过重新排列行、列和统计指标,从多个维度挖掘数据规律。
通俗理解:类似与“数据魔方”,可以根据需求自由旋转(调整行 / 列维度),快速切换分析视角,无需重复编写复杂的分组代码。
与普通表格的区别:普通表格是数据的原始呈现,而透视表是对原始数据的汇总计算结果(如求和、平均值等),且结构可动态调整。
2.核心作用
1.多维度汇总
将复杂数据按多个维度(如时间、类别、地区等)拆分并汇总,清晰展示各维度交叉下的统计结果。
2.灵活分析
无需修改原始数据,通过拖拽或参数调整即可切换分析维度(如从 “按地区统计” 改为 “按地区 + 时间统计”)。
3.高效计算
内置多种聚合函数(求和、均值、计数等),自动完成批量计算,避免手动编写分组聚合代码。
4.动态更新
当原始数据发生变化时,可一键更新透视表结果,保证分析的时效性。
3.核心函数(pivot_table函数)
核心参数如下:
参数名 | 作用说明 | 示例 |
---|---|---|
data | 输入的原始 DataFrame(仅pandas.pivot_table 需要,DataFrame.pivot_table 无需) | data=df |
index | 作为行索引的字段(分组的行维度) | index='category' (按类别分行) |
columns | 作为列索引的字段(分组的列维度) | columns='year' (按年份分列) |
values | 需要聚合计算的字段(被统计的指标) | values='sales' (统计销售额) |
aggfunc | 聚合函数(默认是mean ,可自定义) | aggfunc='sum' (求和) |
4.基本使用示例
1.数据显示
import pandas as pd
data = {'地区': ['华东', '华东', '华北', '华北', '华东', '华北'],'年份': [2022, 2023, 2022, 2023, 2023, 2022],'销售额': [100, 120, 80, 90, 130, 70],'利润': [20, 25, 15, 18, 28, 14]
}
df = pd.DataFrame(data)
2.基本透视表:按照地区和年份统计销售额总和
# 行索引为地区,列索引为年份,统计销售额的总和
pivot = df.pivot_table(index='地区', # 行维度:按地区分组columns='年份', # 列维度:按年份分组values='销售额', # 统计指标:销售额aggfunc='sum' # 聚合方式:求和
)
print(pivot)
年份 2022 2023
地区
华东 100 250 # 华东2023年销售额=120+130
华北 150 90 # 华北2022年销售额=80+70
3.多指标与多聚合函数
# 同时统计销售额和利润,分别计算总和与平均值
pivot = df.pivot_table(index='地区',columns='年份',values=['销售额', '利润'], # 多个指标aggfunc={'销售额': 'sum', '利润': 'mean'} # 不同指标用不同聚合函数
)
这里通过字典来指定aggfunc实现对不同字段的差异化计算。
4.处理缺失值
可通过fill_value参数填充
pivot = df.pivot_table(index='地区',columns='年份',values='销售额',aggfunc='sum',fill_value=0 # 用0填充缺失值
)
5.取消索引层级(转为普通DataFrame)
可通过margins和reset_index调整:
pivot = df.pivot_table(index='地区',columns='年份',values='销售额',aggfunc='sum',margins=True, # 添加总计行/列margins_name='总计' # 总计的名称
).reset_index() # 将行索引转为普通列
6.应用场景
1.业务数据分析:如按地区、时间、产品类别分析销量 / 利润,快速定位高贡献区域或产品。
2.用户行为分析:按用户群体、行为类型、时间统计活跃度,识别核心用户特征。
3.实验数据汇总:按实验组、变量类型统计实验结果的均值 / 标准差,对比不同实验条件的效果。
4.报表自动化:生成动态可调整的汇总报表,替代重复的groupby
代码。
7.其他
1.聚合函数的选择:根据数据类型选择合适的函数(数值型用sum
/mean
,类别型用count
)。
2.维度控制:维度过多(行 / 列字段过多)会导致透视表臃肿,建议优先保留核心分析维度。
3.与groupby的区别:groupby适合固定维度的分组计算,而透视表更擅长动态调整维度和可视化展示,两者可结合使用(如先用groupby预处理数据,再用透视表汇总)。