炉石吐司做的网站,做任务挣钱的网站app,重大新闻事件2023,沙坪坝网站建设文章目录 一、groupby使用场景二、groupby基本原理三、groupby分组运算基础聚合操作#xff1a;只能选择一种聚合操作agg 聚合操作#xff1a;可以针对同列选择不同聚合方法transformapply 四、groupby分组后去重统计nunique()五、groupby分组后重命名列名rename()直接重新命… 文章目录 一、groupby使用场景二、groupby基本原理三、groupby分组运算基础聚合操作只能选择一种聚合操作agg 聚合操作可以针对同列选择不同聚合方法transformapply 四、groupby分组后去重统计nunique()五、groupby分组后重命名列名rename()直接重新命名列名重命名所有的列名add_prefix() /add_suffix() 一、groupby使用场景
在日常数据分析中经常需要将数据根据某个多个字段划分为不同群体group进行分析如电商领域将全国的总销售额根据省份进行划分分析各省销售额的变化情况社交领域将用户根据画像性别、年龄进行细分研究用户的使用情况和偏好如电信诈骗领域研究诈骗用户与非诈骗用户的语音通话行为等。在Pandas中上述的数据处理操作主要运用groupby完成这篇文章就介绍一下groupby的基本原理、对应的agg、transform和apply操作、groupby后的去重统计及重命名列名。
二、groupby基本原理
模拟的样本数据
import pandas as pd
import numpy as np
#主叫号码
calling_nbr[13389012374,13389012375,13389012376,13389012377,13389012379,13389012378,16758439532,16758439533,16758439534,16758439535,16758439536,16758439537]
#对端号码
called_nbr[14374397533,14374397533,14374397533,15926372438,15926372439]
#通话时间
start_date[20230404,20230406,20230408]
datapd.DataFrame({
calling_nbr:[calling_nbr[x] for x in np.random.randint(0,len(calling_nbr),20)],
called_nbr:[called_nbr[x] for x in np.random.randint(0,len(called_nbr),20)],
calling_duration:np.random.randint(10,120,20),
start_date:[start_date[x] for x in np.random.randint(0,len(start_date),20)]})data将上面的样本数据集按照start_date字段划分
groupdata.groupby([start_date])
group会得到一个DataFrameGroupBy对象
如何理解DataFrameGroupBy对data进行groupby后发生了什么ipython所返回的结果是其内存地址并不利于直观地理解为了看看group内部究竟是什么把group转为list的形式看看
list(group)转成列表的形式后可以看到列表由三个元组组成每个元组中第一元素是组别这里是按时start_date进行分组所以最后分为了20230404、20230406、20230408第二个元素的是对应组别下的DataFrame。
总结groupby的过程就是将原有的DataFrame按照groupby的字段这里是start_date划分为若干个分组DataFrame被分为多少个组就有多少个分组DataFrame。所以说在groupby之后的一系列操作如agg、apply等均是基于子DataFrame的操作。理解了这点也就基本摸清了Pandas中的groupby操作的主要原理。 三、groupby分组运算
聚合操作是groupby后非常常见的操作聚合操作可以用来求和、均值、最大值、最小值等下面的表格列出了Pandas中常见的聚合操作。
函数作用min最小值max最大值sum求和mean均值median中位数std标准差var方差count计数
基础聚合操作只能选择一种聚合操作
单列分组
1、单组其他所有列 按calling_nbr分组groupby获取数据表其他所列的统计值。因为called_nbr和start_date不是数字类型所以会自动忽略。
data.groupby(calling_nbr).mean()2、单组单列 按calling_nbr分组groupby仅获取calling_duration的平均值。
data.groupby(calling_nbr)[calling_duration].mean()3、单组多列 按calling_nbr分组groupby获取calling_duration和calling_fee列的平均值。
data.groupby(calling_nbr)[[calling_duration,calling_fee]].mean()多列分组 1、多组其他所有列 按calling_nbr和start_date分组groupby)获取数据表其他所列的统计值。只针对数字类型的列。
data.groupby([calling_nbr,start_date]).mean()2、多组单列 按calling_nbr和start_date分组groupby)仅获取calling_duration的平均值。
data.groupby([calling_nbr,start_date])[calling_duration].mean()3、多组多列 按calling_nbr和start_date分组groupby)获取calling_duration和calling_fee列的平均值。
data.groupby([calling_nbr,start_date])[[calling_duration,calling_fee]].mean()agg 聚合操作可以针对同列选择不同聚合方法
单列分组
1、单组单列
一种聚合方法多种写法
比如求主叫号码通话时长的平均值
data.groupby(calling_nbr).agg({calling_duration:mean})data.groupby(calling_nbr)[calling_duration].agg([mean])多种聚合方法多种写法
比如求主叫号码通话时长的平均值总和和标准差
data.groupby(calling_nbr).agg({calling_duration:[mean,sum,std]})
data.groupby(calling_nbr).agg({calling_duration:[mean,np.sum,std]})data.groupby(calling_nbr)[calling_duration].agg([np.mean,np.sum,np.std])
data.groupby(calling_nbr)[calling_duration].agg([np.mean,sum,np.std])2、单组多列
一种聚合方法多种写法
data.groupby(calling_nbr).agg({calling_duration:[mean],calling_fee:[sum]})data.groupby(calling_nbr)[[calling_duration,calling_fee]].agg([mean])多种聚合方法多种写法
data.groupby(calling_nbr).agg({calling_duration:[mean,sum,std],calling_fee:[mean,sum,std]})
data.groupby(calling_nbr).agg({calling_duration:[mean,np.sum,std],calling_fee:[mean,np.sum,std]})data.groupby(calling_nbr)[[calling_duration,calling_fee]].agg([np.mean,np.sum,np.std])
data.groupby(calling_nbr)[[calling_duration,calling_fee]].agg([np.mean,sum,np.std])多列分组
1、多组单列
一种聚合方法多种写法
比如求主叫号码当天通话时长总和
data.groupby([calling_nbr,start_date]).agg({calling_duration:sum})data.groupby([calling_nbr,start_date])[calling_duration].agg([sum])多种聚合方法多种写法
data.groupby([calling_nbr,start_date]).agg({calling_duration:sum,calling_duration:np.mean})data.groupby([calling_nbr,start_date])[calling_duration].agg([sum,np.mean])2、多组多列
一种聚合方法多种写法
data.groupby([calling_nbr,start_date]).agg({calling_fee:mean,calling_duration:mean})data.groupby([calling_nbr,start_date])[[calling_duration,calling_fee]].agg([mean])多种聚合方法多种写法
比如求主叫号码不同天的主叫次数和平均通话时长代码如下
data.groupby([calling_nbr,start_date]).agg({calling_fee:count,calling_duration:mean})比如求主叫号码不同天的主叫次数与通话时长的总和、标准差和平均值
data.groupby([calling_nbr,start_date]).agg({calling_fee:[sum,count,mean],calling_duration:[sum,count,mean]})data.groupby([calling_nbr,start_date])[[calling_duration,calling_fee]].agg([sum,count,mean])注意对于单组单列的分组来说基础聚合操作与agg聚合操作得到的对象有什么不同
基础聚合操作由于只选择一列数据所以生成的对象是Series数据结构。agg聚合操作后生成的对象是DataFrame数据结构。
adata.groupby(calling_nbr)[calling_duration].mean()
print(type(a))adata.groupby(calling_nbr)[calling_duration].agg([mean])
adata.groupby(calling_nbr).agg({calling_duration:mean})
print(type(a))transform
在agg 聚合中我们学会了如何求不同主叫号码同一天的平均通话时长agg 聚合操作形成的新DataFrame如果现在需要在原数据集中新增加一列avg_calling_duration代表主叫号码同一天的平均通话时长相同一天具有一样的平均通话时长。
如何实现
1、正常过程先求得主叫号码不同天的平均通话时长然后按照主叫号码和通话时间的对应关系填充到对应的位置
avg_calling_durationdata.groupby([calling_nbr,start_date])[calling_duration].mean().rename(avg_calling_duration).reset_index()data_1 data.merge(mean_calling_duration)
data_12、使用transform函数仅需要一行代码
data[avg_calling_duration]data.groupby([calling_nbr,start_date])[calling_duration].transform(mean)datatransform与agg对比
对agg而言会计算得到不同号码当天的通话时长的均值并直接返回。对transform而言则会对第每一条数据求得相应的结果同一组内的样本会有相同的值组内求完均值后会按照原索引的顺序返回结果。
可以看下图agg与transform过程图解 apply
对于groupby后的apply以分组后的子DataFrame作为参数传入指定函数的基本操作单位是DataFrame。
如果现在需要获取当天主叫与同一个被叫号码的通话次数top1的数据如何实现
#统计主叫与同一个被叫号码的通话次数
data[calling_called_max]data.groupby([calling_nbr,called_nbr,start_date])[calling_nbr].transform(count)#统计主叫与同一个被叫号码的通话次数top1
def get_max_calling_called_num(x):dfx.sort_values(bycalling_called_max,ascendingTrue)return df.iloc[-1:]get_max_calling_called_num_datadata.groupby([calling_nbr,called_nbr,start_date],as_indexFalse).apply(get_max_calling_called_num)注意关于apply的使用这里有个小建议虽然说apply拥有更大的灵活性但apply的运行效率会比agg和transform更慢。所以groupby之后能用agg和transform解决的问题还是优先使用这两个方法实在解决不了了才考虑使用apply进行操作。 四、groupby分组后去重统计nunique()
nunique()统计groupby()分组后组内不同值的个数比如适用于统计主叫号码拨打去重后的对端号码个数。
举例1 要求统计主叫号码拨打去重后的对端号码个数。
#方法二选一。
data.groupby(calling_nbr)[called_nbr].nunique()
data.groupby(calling_nbr).agg({ called_nbr: pd.Series.nunique})与unique()的区别unique()方法返回的是去重之后的不同值。
data.groupby(calling_nbr)[called_nbr].unique()五、groupby分组后重命名列名
groupby分组后对某列进行聚合计算需要对聚合计算后的新列进行重命名。
第一先观察数据类型要转变为DataFrame数据类型再重命名。第二查看groupby后DataFrame.columns是什么格式。第三再选择合适的方法进行重命名。
rename() rename()重命名reset_index()将DataFrame的索引转成DataFrame的列。 1、对单列进行重命名。
举例1
data_1data.groupby(calling_nbr).agg({calling_duration:mean})
print(type(data_1)) #查看数据类型
print(data_1.colunms #查看列名格式我们可以看到是DataFrame数据类型且DataFrame的列名格式是含单元素的列表可以直接使用rename重命名。
data_1.rename(columns{calling_duration:calling_duration_avg}).reset_index()举例2
data_1data.groupby(calling_nbr)[calling_duration].mean()
print(type(data_1)) #查看数据类型我们可以看到对单列进行聚合得到是Series数据类型因此先转换成DataFrame数据类型再重命名。
data_1.to_frame() #将Series数据类型转成DataFrame数据类型。data_1.rename(columns{calling_duration:calling_duration_avg}).reset_index()注意如果是对单列进行聚合得到是Series数据类型要先转换成DataFrame数据类型再重命名。
2、对多列进行重命名
举例1
#两种常用的聚合方法二选一。
data_1data.groupby(calling_nbr)[[calling_duration,calling_fee]].mean()
data_1data.groupby(calling_nbr).agg({calling_duration:mean,calling_fee:mean})使用这两种方法都可以对多列进行聚合计算groupby聚合计算后的数据情况如下。
print(type(data_1)) #查看数据类型都是DataFrame数据类型。
print(data_1.columns) #查看列名格式DataFrame的列名格式都是含单元素的列表。
我们可以看到是DataFrame数据类型且DataFrame的列名格式是含单元素的列表可以直接使用rename()重命名。
data_1.rename(columns{calling_duration:calling_duration_avg,calling_fee:calling_fee_avg})举例2
data_1data.groupby(calling_nbr)[[calling_duration,calling_fee]].agg([mean])
data_1print(type(data_1)) #查看数据类型是DataFrame数据类型。
print(data_1.columns) #查看列名格式查看dataframe的列名格式发现聚合后的列名是MultiIndex类型。此时必须通过元组的复合索引方式才能有效提取列的信息。
data_1.columns.values查看列名的元素我们可以看到每个列都是一个元组。通过下面两种方法都可以重命名
方法一通过遍历columns的方式将MultiIndex的一级和二级索引拼接在一起作为data的新列名。
data_1.columns[i[0] _ i[1] for i in data_1.columns]
data_1方法二只需要将元组拼接成字符串然后替换原来的列名就可以了。
data_1.columns [_.join(col).strip() for col in data_1.columns.values]
data_1直接重新命名列名 使用dataframe.columns[‘新列名’]或dataframe.columnspd.Series([‘新列名’]) 重命名。 1、要求对单列进行重命名。
举例1
#对单列进行聚合计算的两种方式二选一
data_1data.groupby(calling_nbr).agg({calling_duration:mean})data_1data.groupby(calling_nbr)[calling_duration].mean()
data_1.to_frame()#生成是Series数据类型因此使用to_frame()转换成DataFrame数据类型。#直接重命名的两种方法二选一。
data_1.columns pd.Series([calling_duration_avg])
data_1.columns [calling_duration_avg]#reset_index()将DataFrame的索引转成DataFrame的列。
data_1.reset_index(inplaceTrue) 2、要求对多列进行重命名。
举例1
#对多列进行聚合计算的两种方式二选一
data_1data.groupby(calling_nbr)[[calling_duration,calling_fee]].mean()
data_1data.groupby(calling_nbr).agg({calling_duration:mean,calling_fee:mean})#直接重命名的两种方法二选一。
data_1.columns pd.Series([calling_duration_avg,calling_fee_avg])
data_1.columns [calling_duration_avg,calling_fee_avg]#reset_index()将DataFrame的索引转成DataFrame的列。
data_1.reset_index(inplaceTrue) 举例2
data_1data.groupby(calling_nbr)[[calling_duration,calling_fee]].agg([mean])print(data_1.columns) #查看列名格式聚合后的列名是MultiIndex类型不能使用dataframe.columns[‘新列名’]或dataframe.columnspd.Series([‘新列名’]) 直接重命名。要多做一个步骤的处理可以通过遍历columns的方式先将MultiIndex的一级和二级索引拼接在一起作为data的新列名或者先将元组拼接成字符串再替换原来的列名就可以了。具体例子见rename()目录下“对多列进行重命名”的举例2
注意
对单列进行重命名注意基础聚合方法data_1data.groupby(‘calling_nbr’)[‘calling_duration’].mean()生成的是Series数据类型。对多列进行重命名注意agg聚合方法写法data_1data.groupby(‘calling_nbr’)[[‘calling_duration’,‘calling_fee’]].agg([‘mean’])生成的列名格式是MultiIndex类型不能直接使用rename方法和dataframe.columns[‘新列名’]或dataframe.columnspd.Series([‘新列名’]) 重命名。
重命名所有的列名add_prefix() /add_suffix()
在处理大量dataframe数据时我们可能对所有列名进行重命名操作。 pandas.DataFrame.add_prefix() 函数来修改列名的前缀 pandas.DataFrame.add_suffix() 函数来修改列名的后缀。 聚合后的列名是MultiIndex类型不能使用这种方法。 #三种方法达到效果是一致
data_1data.groupby(calling_nbr).agg({calling_duration:mean,calling_fee:mean}).add_prefix(new_)data_1data.groupby(calling_nbr)[[calling_duration,calling_fee]].mean().add_prefix(new_)data_1data.groupby(calling_nbr).mean().add_prefix(new_)参考文章
https://zhuanlan.zhihu.com/p/101284491 https://blog.csdn.net/qq_39657585/article/details/114789396 https://blog.csdn.net/yeshang_lady/article/details/105345653 https://blog.csdn.net/weixin_43609275/article/details/86220907 https://blog.csdn.net/weixin_39923556/article/details/123002620 https://blog.csdn.net/pz789as/article/details/106059610 https://zhuanlan.zhihu.com/p/358006128