Pandas_分组与聚合
# 分组统计是数据分析中的重要环节:
# 1-数据分组:GroupBy的原理和使用方法;
# 2-聚合运算:学会分组数据的聚合运算方法和函数使用; 类似于 SQL思想
# 3-分组运算:重点 apply方法的使用
# 4-数据透视表:学会构建数据透视表和交叉表
# 一,GroupBy:
# 步骤:split-apply-combine
# 举例:小费 tips
import pandas as pd
import numpy as np
import seaborn as sns
from pandas import Series,DataFrame
# tips=sns.load_dataset('tips') # 从 github仓库里下载 https://github.com/mwaskom/seaborn-data
tips=pd.read_csv('tips.csv')
tips.head(20)
{ vertical-align: top }
.dataframe thead th { text-align: right }
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
5 | 25.29 | 4.71 | Male | No | Sun | Dinner | 4 |
6 | 8.77 | 2.00 | Male | No | Sun | Dinner | 2 |
7 | 26.88 | 3.12 | Male | No | Sun | Dinner | 4 |
8 | 15.04 | 1.96 | Male | No | Sun | Dinner | 2 |
9 | 14.78 | 3.23 | Male | No | Sun | Dinner | 2 |
10 | 10.27 | 1.71 | Male | No | Sun | Dinner | 2 |
11 | 35.26 | 5.00 | Female | No | Sun | Dinner | 4 |
12 | 15.42 | 1.57 | Male | No | Sun | Dinner | 2 |
13 | 18.43 | 3.00 | Male | No | Sun | Dinner | 4 |
14 | 14.83 | 3.02 | Female | No | Sun | Dinner | 2 |
15 | 21.58 | 3.92 | Male | No | Sun | Dinner | 2 |
16 | 10.33 | 1.67 | Female | No | Sun | Dinner | 3 |
17 | 16.29 | 3.71 | Male | No | Sun | Dinner | 3 |
18 | 16.97 | 3.50 | Female | No | Sun | Dinner | 3 |
19 | 20.65 | 3.35 | Male | No | Sat | Dinner | 3 |
# 将序列按照单个分组键分组,并聚合计算:
# 1,groupby()可以被 Series调用,也可以被 DataFrame调用。
grouped=tips['tip'].groupby(tips['sex']) # 对 tip Series,按照 sex序列的值进行分组
grouped=tips.groupby(tips['sex']) # 对 tips DataFrame,按照 sex序列的值进行分组
grouped # <pandas.core.groupby.generic.SeriesGroupBy object at 0x0000026FF174BC08> GroupBy对象 可迭代对象
grouped.mean() # 平均值 聚合运算
grouped.sum() # 求和
# 将序列按照多个分组键分组,并聚合计算:
data_mean=tips['tip'].groupby([tips['sex'],tips['time']]).mean()
data_mean # type(data_mean) # 多层索引的序列 pandas.core.series.Series
data_mean.plot(kind='barh') # 男性晚餐时候小费给的平均值高
# GroupBy对象是可迭代对象,其构造为一组二元元组:
for name,group in tips['tip'].groupby(tips['sex']):
print(name)
print(group)
# 可查看各分组的大小
tips.groupby(tips['sex']).size()
# 2,分组方式:
# 2-1)按序列分组:
grouped=tips['tip'].groupby(tips['sex']) # 对 tip Series,按照 sex序列的值进行分组
grouped=tips.groupby(tips['sex']) # 对 tips DataFrame,按照 sex序列的值进行分组
# 2-2)按列名分组:
smoker_mean=tips.groupby('smoker').mean()
smoker=tips.groupby('somker',group_keys=False)['tip']
smoker_mean=tips.groupby(['sex','smoker']).mean() # 按多个列名组合分组
smoker_mean=tips.groupby(['sex','smoker'],as_index=False).mean() # 按多个列名组合分组 as_index=False:不以分组键作为索引
size_mean1=tips.groupby('size')['tip'].mean() # 等效于:
size_mean2=tips['tip'].groupby(tips['size']).mean()
size_mean1==size_mean2 # 返回全是True的布尔数组
# 2-3) 按行索引分组:
df=DataFrame(np.arange(16).reshape(4,4),index=['a','b','a','b'])
df.groupby(df.index).mean()
# 2-4)按列表或元组分组: # 相当于先给索引按照列表重命名,然后按行索引分组。
df=DataFrame(np.arange(16).reshape(4,4))
list1=['a','b','a','b']
df.groupby(list1).mean()
# 2-5)按照字典分组: # 相当于先给dataframe的索引重命名,再按新索引分组。
# 当要分组的列或行索引的值不明确时,需要使用字典指定
df=DataFrame(np.arange(16).reshape(4,4),index=['a','b','A','B'])
dict1={
'a':'one',
'A':'one',
'b':'two',
'B':'two'
}
df.groupby(dict1).mean()
# 2-6)按函数分组:
# 原理类似于字典,通过映射关系进行分组,但更灵活。
df=DataFrame(np.random.randn(4,4))
df
df.groupby(df[3].map(lambda x:'a' if x>=0 else 'b')).sum() #看结果就明白了
# 2-7) 对于层次化索引,按 level级别进行分组:
df=DataFrame(np.arange(16).reshape(4,4),
index=[['one','one','two','two'],['a','b','a','b']],
columns=[['apple','apple','orange','orange'],['red','green','red','green']])
df
# df.groupby(level=1).sum()
# df.groupby(level=1,axis=1).sum()
# df.groupby(level=0).sum()
df.groupby(level=0,axis=1).sum()
# 3,聚合运算 注:空值不参与计算! 返回聚合后的序列
# 对分组后的数据进行计算,产生标量值的转换过程叫聚合运算,上面的 mean(),sum()都是。
# 3-1) 常用的聚合函数:
# count 计数
# sum 求和
# mean 求平均值
# median 求算术中位数
# std 求标准差
# var 求方差
# min,max 求最小值,最大值
# prod 求积
# first,last 求第一个值,求最后一个值
# quantile 分位数计算
max_tip=tips.groupby('sex')['tip'].max()
max_tip # 序列
max_tip.plot(kind='bar')
# 3-2) 自定义聚合函数: grouped.aggregate(f) 或 grouped.agg(f) aggregate--聚合
# se.agg(f)与 se.map(f)的不同点在于:agg是Grupby对象的聚合函数,而 map是Series的矢量化函数。
# 因而,agg里的函数 f一般也是由聚合函数组成的。
def get_range(x):
'''接收一个数字序列,或数字列表,得到数字的范围'''
return x.max()-x.min()
# tips_range=tips.groupby('sex')['tip'].agg(get_range)
tips_range=tips.groupby('sex')['tip'].agg(lambda x:x.max()-x.min())
tips_range
# 4,多函数应用:
# 4-1) 一列多函数 agg([f1,f2,f3...])
# get_range=lambda x:x.max()-x.min()
def get_range(x):
'''接收一个数字序列,或数字列表,得到数字的范围'''
return x.max()-x.min()
tips.groupby(['sex','smoker'])['tip'].agg(['mean','std',get_range]) #自定义的函数不能使用'', 默认列名为函数名
tips.groupby(['sex','smoker'])['tip'].agg([('tip_mean','mean'),('range',get_range)]) #指定列名
# 4-2) 多列多函数: 产生列的层次化索引
tips.groupby(['day','time'])['tip','total_bill'].agg([('tip_mean','mean'),('range',get_range)]) # 将来版本要用列表替代元组?
# 4-3) 不同列,不同函数: 使用字典映射
tips.groupby(['day','time'])['total_bill','tip'].agg({'total_bill':['sum','mean'],'tip':'mean'}) # 将要被废弃
# 5, 分组运算:
# 运行下面代码,体会 transform 和 apply的不同效果:
tips.groupby('sex').transform('mean')
tips.groupby('sex')['tip'].transform('mean')
tips.groupby('sex').apply(lambda x:x.mean())
tips.groupby('sex')['tip'].apply(lambda x:x.mean())
# 速记:
tips.groupby('sex').transform('mean') # 只计算可以计算的列,比如3个可计算列,并返回新的 由3个列组成的 DataFrame
tips.groupby('sex')['tip'].transform('mean') # 只计算 tip列,返回一个 Series.
df.groupby('sex').apply(lambda x:x.fillna(x.mean())) # 返回一个 对【所有数值列】缺失值填充后的 DataFrame
df.groupby('sex')['math'].apply(lambda x:x.fillna(x.mean())) # 返回一个 只对【Math】列缺失值填充后的Series
# grouped.perform(),grouped.apply(),都不改变原数据结构,如果想要做改变,可以赋值,比如:
tips['tip_mean_by_sex']=tips.groupby('sex')['tip'].transform('mean') # 增加一个新的列 tip_mean_by_sex
# 5-1) tips.groupby('sex')['tip'].transform('mean').transform()方法: 返回
# 对于小费数据集 tips,新建一列用于存放男性和女性小费的平均值。
# 1)常用方法是,先分组聚合运算,再 merge按 sex键合并,出现一个新的列。
tip_mean_by_sex=tips.groupby('sex')['tip'].mean()
tip_mean_by_sex
tip_mean_by_sex_df=DataFrame(tip_mean_by_sex) # 注意,参数是 tips.groupby('sex')['tip'].mean() 不是 tips.groupby('sex')['tip']
tip_mean_by_sex_df # 此时行索引的 name为 sex,行索引的值为[Female,Male]
new_tips=pd.merge(tips,tip_mean_by_sex_df,left_on='sex',right_index=True,suffixes=('','_mean_by_sex'),how='left') # 指定left,tips的索引顺序就不会改变
new_tips.head(10)
# 2) 使用 transform('mean')方法将参数里的函数运算结果分布到每一行,非聚合函数,dataframe的矢量化函数:
new_tips=tips.copy()
new_tips['tip_mean_by_sex']=tips.groupby('sex')['tip'].transform('mean') # 增加一个新的列 tip_mean_by_sex
new_tips.head(10)
# 5-2)df.groupby('sex').apply()方法: 返回DataFrame数据
# 更加强大:
# 计算根据性别分组后的小费金额前 5名的 DataFrame数据:默认结果以分组键作为行索引,可以用 groupby()里使用group_keys=False来改变:
tips.groupby('sex').apply(lambda x:x.sort_values(by='tip',ascending=False)[:5])
tips.groupby('sex',group_keys=False).apply(lambda x:x.sort_values(by='tip',ascending=False)[:5])
# groupby()的 group_keys=False 参数只有在调用 apply()的时候好使。
# 对缺失值的处理,前面数据处理那部分,有使用平均值进行填充缺失值的例子,如:
data={
'name':['张三','李四',np.nan,'王五','小明','马六'],
'sex':['female','female','male','male','male','female'],
'math':[67,77,np.nan,82,90,np.nan],
'English':[67,77,np.nan,82,90,np.nan]
}
df=DataFrame(data)
df.fillna(df['math'].mean()) # 使用 math列的平均值填充缺失值
df.fillna(df['English'].mean()) # 使用 English列的平均值填充缺失值
df.groupby('sex').apply(lambda x:x.fillna(x.mean())) # 根据性别计算每个性别的 math和 english的平均数,来填充不同性别对应的缺失值.
df.groupby('sex')['math'].apply(lambda x:x.fillna(x.mean())) # 根据性别计算每个性别的 math的平均数,来填充不同性别对应的缺失值.
# 6,数据透视表
# 关于 Excel数据透视表的使用教程,请见: https://www.zhihu.com/question/24341252
# df.pivot(values=要计算的列名, index=行名, columns=列名, aggfunc='sum', margins=True) # 由 df调用
# pd.cross_table(index=tips['day'],columns=tips['size']) # 由 pd调用,传入 df的两个整列作为行列索引
# 6-1)透视表:
# pandas里也有数据透视表功能,pivot_table 函数。
tips.pivot_table(values='tip',index='sex',columns='smoker') # 默认计算 mean()
tips.pivot_table(values='tip',index='sex',columns='smoker',aggfunc='sum') # 默认计算 mean(), aggfunc='sum' 指定计算 sum
tips.pivot_table(values='tip',index='sex',columns='smoker',aggfunc='sum',margins=True) # margins=True 对其他列做小计
# 用 groupby()来实现:
tips.groupby(['sex','smoker'])['tip'].mean().unstack() # 按多个列名组合分组 unstack()的默认参数为 1,表示操作内层行索引。
tips.groupby(['sex','smoker'])['tip'].sum().unstack() # sum
sex_smoker=tips.groupby(['sex','smoker'])['tip'].sum().unstack() # sum
sex_smoker['All']=sex_smoker['No']+sex_smoker['Yes'] #增加一列
sex_smoker=sex_smoker.append({'No':sex_smoker['No'].sum(),'Yes':sex_smoker['Yes'].sum()},ignore_index=True) # 增加一行
sex_smoker.index.name='Sex' # 恢复行索引名称
sex_smoker.index=['Female','Male','All'] # 恢复原来的行索引
sex_smoker
# 所以,使用透视表更简单些
# 6-1)交叉表:
# 用于计算分组频次与频率的特殊透视表
cross_table=pd.cross_table(index=tips['day'],columns=tips['size']) # 频次
cross_table
df=cross_table.div(cross_table.sum(axis=1),axis=0) # 频率 每行的和为1
df
# 频率频次堆积图:
df.plot(kind='bar',stacked=True)
Pandas_分组与聚合的更多相关文章
- mysql 分组和聚合函数
mysql 分组和聚合函数 Mysql 聚集函数有5个: 1.COUNT() 记录个数(count(1),count(*)统计表中行数,count(列名)统计列中非null数) 2.MAX() 最大值 ...
- MongoDB学习(使用分组、聚合和映射-归并)
使用分组.聚合和映射-归并 MongoDB的强大功能之一,是直接在服务器对文档的值进行复杂的操作,而不用先发文档发送到客户端在进行处理. 结果分组 对大型数据集进行查询操作时,通常会根据文档的字段值对 ...
- pd.qcut, pd.cut, df.groupby()等在分组和聚合方面的应用
pd.qcut, pd.cut, df.groupby()等在分组和聚合方面的应用 量化交易里, 需要进行大量的分组和统计, 以方便自己处优势的位置/机会. 比如对股价进行趋势分析, 波动性分析, 量 ...
- 70 多表查询的分组F 聚合 Q 查询
聚合查询和分组查询 聚合 aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典.键的名称是聚合值的标识符,值是计算出来的聚合值.键的名称是按照字段和聚合函 ...
- pandas分组和聚合
Pandas分组与聚合 分组 (groupby) 对数据集进行分组,然后对每组进行统计分析 SQL能够对数据进行过滤,分组聚合 pandas能利用groupby进行更加复杂的分组运算 分组运算过程:s ...
- FreeSql (二十三)分组、聚合
IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data ...
- 20-2 orm分组和聚合以及在项目中执行的一些方法
一 orm分组和聚合 参考:https://www.cnblogs.com/liwenzhou/p/8660826.html 1 表结构: # 第一张表 class Employee1(models ...
- FastReport分组与聚合
本来看上去都觉得简单顺便训练下,是想对Customer表中的Company字段以第1个开头的字母分组,结果自己因喜欢将那些东西都集中在一起进行训练,在那个Master-Slave上做例子,并且没用另外 ...
- pandas_分类与聚合
# 分组与聚合 import pandas as pd import numpy as np # 设置列对齐 pd.set_option("display.unicode.ambiguous ...
随机推荐
- RHSA-2017:2299-中危: NetworkManager 和 libnl3 安全和BUG修复更新(本地提权、代码执行)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...
- C# 生成chart图表的三种方式
.net中,微软给我们提供了画图类(system.drawing.imaging),在该类中画图的基本功能都有.比如:直线.折线.矩形.多边形.椭圆形.扇形.曲线等等,因此一般的图形都可以直接通过代码 ...
- Python+Appium自动化测试(5)-appium元素定位常用方法
对于Android而言,查找appUI界面元素属性的工具有三种:appium desktop,uiautomatorviewer.bat,weditor.之前已经介绍过了weditor的使用,这里我将 ...
- 多测师讲解自动化测试 _RF连接数据库_高级讲师肖sir
RF连接数据库:1.Connect To Database(连接数据库)2.Table Must Exist(表必须存在)3.Check If Exists In Database(查询某条件是否存在 ...
- 新手学习C语言/C++编程你所必须要了解的知识!从计算机原理开始!
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- lumen-ioc容器测试 (3)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- django—模型相关
配置数据库信息 1.settings配置 DATABASES = { "default": { "ENGINE": "djan ...
- dbvis 导出表结构 xls
1.dbvis 可以导出多种格式的文件,如SQL.XLS.TXT.HTML.JSON.CSV及XML. 需求场景(本场景是实际场景引申的场景,此处导出xls): 最近,遇到一个需求需要将表的结构数据导 ...
- Java编程思想 笔记
date: 2019-09-06 15:10:00 updated: 2019-09-24 08:30:00 Java编程思想 笔记 1. 四类访问权限修饰词 \ 类内部 本包 子类 其他包 publ ...
- 树和堆(julyedu网课整理)
date: 2018-12-05 16:59:15 updated: 2018-12-05 16:59:15 树和堆(julyedu网课整理) 1 定义 1.1 树的定义 它是由n(n>=1)个 ...