)
分组分组聚合 groupby aggdf.groupby([‘分组字段1’,“分组字段2’…]).agg({‘列名1’:“聚合两数名’, 列名2”:聚合函数名…})importpandasaspd dfpd.DataFrame([(1,上海,2021-03-01,80),(2,上海,2022-05-01,59),(3,上海,2022-07-01,80),(4,上海,2022-08-01,59),(5,郑州,2021-10-01,50),(6,郑州,2021-10-01,80),(7,郑州,2022-10-01,30),(8,郑州,2022-10-01,20)],columns(id,city,date,score))# 添加一列df[year]pd.DatetimeIndex(df[date]).year df[date].dt.days# 分组列单个可以传字符串groupsdf.groupby(city)# 多个使用数组groupdf.groupby([city,year]).get_group((上海,2022))group.first()# 获取分组第一条数据group.last()# 获取分组最后一条数据# 通用# 返回DataFrame对象df.groupby([city,year]).agg({socre:sum})# 返回Series对象df.groupby([city,year]).socre.sum()df.groupby([city,year])[socre].sum()# 返回Series对象df.groupby([city,year])[[socre]].sum()# 返回DataFrame对象#不把分组字段当做索引行df.groupby([city,year],as_indexFalse).socre.sum()df.groupby([city,year]).agg({socre:sum,year:mean})sumgroups[score].sum()countgroups[id].count()pd2pd.DataFrame({sum:sum,count:count})print(pd2)#思路3:最大或者最小的n个df.nlargest(1,score)#最大的n个参1:n个参2:排序字段df.nsmallest(1,score)# 最小的n个分组聚合 groupby filterdf.groupby([列名1,...]).filter(lambdax:returnboolvalue)df.groupby(city).filter(lambdax:x[score].mean()50)df.groupby(city).score.filter(lambdax:x.mean()50)df.groupby(city).filter(lambdax:x[score].mean()50).city.unique()交叉表data{性别:[男女男女男女女男]购买:[是否是!是否否是否]}dfpd.DataFrame(data)#创建交叉表crosstabpd.crosstab(df[性别],df[购买])print(crosstab)透视表分组求和透视表是用来简化分组的和分组的效果差不多只是外观展示不太一样。importpandasaspdimportnumpyasnp dfpd.DataFrame([(1,上海,2021-03-01,80),(2,上海,2022-05-01,59),(3,上海,2022-07-01,80),(4,上海,2022-08-01,59),(5,郑州,2021-10-01,50),(6,郑州,2021-10-01,80),(7,郑州,2022-10-01,30),(8,郑州,2022-10-01,20)],columns(id,city,date,score))# 添加一列df[year]pd.DatetimeIndex(df[date]).year tabledf.pivot_table(columnsyear,valuesscore,aggfuncnp.sum,indexcity)print(table)data{性别:[男女男女男女]购买:[是否是是否否]金额:[100,150,200,130,160,120]}dfpd.DataFrame(data)df.pivot_table(index性别,columns购买,values金额,aggfuncmean)排序importpandasaspd dfpd.DataFrame([(1,10,0.1),(2,20,0.2),(3,15,0.15)],columns(id,price,discount))df.set_index(id,inplaceTrue)# 按照索引排序df.sort_index(ascendingTrue)# inplaceTrue表示影响原来的df的值, ascendingTrue表示升续# df.sort_values(byprice, inplaceTrue, ascendingTrue)# 多个值排序price asc, discount descdf.sort_values(by[price,discount],inplaceTrue,ascending[True,False]).head(1)print(df)value_countsvalue_counts() 是 Series / DataFrame 的方法作用统计一列 / 多列中每个不同值的出现次数返回带计数的序列。⚠️ 不能直接 pd.value_counts()只能作用于列 / 数据集。默认降序排列出现最多的值放最上面默认自动忽略 NaN 空值(dropnaTrue)设置为False表示统计空值importpandasaspd spd.Series([2,2,3,5,3,2,None]) 2.0 3 3.0 2 5.0 1 Name: count, dtype: int64 print(s.value_counts())dropnaFalse 统计空值normalizeTrue 返回占比频率总和为1乘以100可以转化百分比ascendingTrue 升序数量从小到大sortFalse 不排序按原始唯一值顺序输出importpandasaspd spd.Series([2,2,3,5,3,2,None])print(s.value_counts(dropnaFalse,normalizeTrue)) 2.0 0.428571 3.0 0.285714 5.0 0.142857 NaN 0.142857 importpandasaspd dfpd.DataFrame({gender:[男,女,男,男,女]})resdf[gender].value_counts().reset_index() gender count 0 男 3 1 女 2 print(res)importpandasaspd dfpd.DataFrame({fruit:[苹果,香蕉,苹果,橙子,苹果,None,香蕉]})# 1. 基础计数忽略空值 fruit 苹果 3 香蕉 2 橙子 1 Name: count, dtype: int64 print(df[fruit].value_counts())# 2. 包含空值输出占比 fruit 苹果 0.428571 香蕉 0.285714 橙子 0.142857 NaN 0.142857 Name: proportion, dtype: float64 # print(df[fruit].value_counts(dropnaFalse, normalizeTrue))# 3. 转为百分比perdf[fruit].value_counts(normalizeTrue,dropnaFalse)*100 苹果 42.9 香蕉 28.6 橙子 14.3 NaN 14.3 Name: proportion, dtype: float64 print(per.round(1))切分 cutpd.cut() 是 Pandas 中用于将连续数值数据离散化分箱的核心函数。简单说就是根据你设定的区间把一串连续的数字划分到不同的类别里去。它特别适合以下场景将年龄划分为“少年、青年、中年、老年”等年龄段将考试成绩分为“优秀、良好、及格、不及格”将连续的收入数据转为“低收入、中等收入、高收入”等层级语法pd.cut(x,# 要分箱的一维数组或Seriesbins,# 分箱规则整数或区间边界列表rightTrue,# 区间是否包含右端点默认包含labelsNone,# 分箱后的类别标签retbinsFalse,# 是否返回分箱边界include_lowestFalse# 是否包含最左端点)按数量等分指定整数 binsimportpandasaspdimportnumpyasnp# 生成10个0-100的随机数datanp.random.randint(0,100,size10)# [ 6 41 12 96 12 33 37 54 62 89]print(原始数据,data)resultpd.cut(data,bins4) data中的每个数据所对应的区间范围result是个列表列表中的每个元素是一个区间小括号表示开区间中括号表示闭区间 [(5.91, 28.5], (28.5, 51.0], (5.91, 28.5], (73.5, 96.0], (5.91, 28.5], (28.5, 51.0], (28.5, 51.0], (51.0, 73.5], (51.0, 73.5], (73.5, 96.0]] 将0-100范围的数据等分为4个区间 Categories (4, interval[float64, right]): [(5.91, 28.5] (28.5, 51.0] (51.0, 73.5] (73.5, 96.0]] print(分箱结果,result)print(\n各箱计数\n,result.value_counts())自定义区间边界指定列表importpandasaspd ages[1,3,6,7,8,9,10]# 自定义分箱边界0-6, 6-8, 8-9, 9-10bins[0,6,8,9,10]age_groupspd.cut(ages,binsbins)# [Interval(0, 6, closedright), Interval(0, 6, closedright), Interval(0, 6, closedright), Interval(6, 8, closedright), Interval(6, 8, closedright), Interval(8, 9, closedright), Interval(9, 10, closedright)]print(年龄分组:,age_groups.tolist()) 每个范围的数量 (0, 6] 3 (6, 8] 2 (8, 9] 1 (9, 10] 1 print(age_groups.value_counts())添加自定义标签importpandasaspd ages[1,3,6,7,8,9,10]# 自定义分箱边界0-6, 6-8, 8-9, 9-10bins[0,6,8,9,10]labels[不及格,中等,良好,优秀]age_groupspd.cut(ages,binsbins,labelslabels)# [不及格, 不及格, 不及格, 中等, 中等, 良好, 优秀]print(年龄分组:,age_groups.tolist())控制区间开闭importpandasaspd ages[1,3,6,7,8,9,10]bins[0,6,8,9,10]labels[不及格,中等,良好,优秀]# rightTrue默认左开右闭如 (0, 6]# rightFalse左闭右开如 [0, 6)age_groupspd.cut(ages,binsbins,labelslabels,rightFalse)print(age_groups)# [0, 6) 、[6, 8) 、[8, 9) 、[9, 10)print(年龄分组:,age_groups.tolist()) [不及格, 不及格, 中等, 中等, 良好, 优秀, NaN] Categories (4, str): [不及格 中等 良好 优秀] 实际案例根据范围分组为每个组打个标签label再求每个组进行统计。传统的groupby只能根据某些固定值进行分组而cut() 可以先将某个范围的值固定到某个组中。importpandasaspd# 创建用户数据dfpd.DataFrame({user_id:range(1,11),age:[25,32,19,45,51,38,22,60,29,42],spending:[100,250,80,400,350,300,150,500,200,450]})# 年龄分层(根据年龄范围为每个用户打上对应的分组表情)age_bins[0,25,35,50,100]age_labels[青年,中青年,中年,老年]df[age_group]pd.cut(df[age],binsage_bins,labelsage_labels)# 按年龄层统计消费均值 age_group 青年 110.000000 中青年 225.000000 中年 383.333333 老年 425.000000 Name: spending, dtype: float64 print(df.groupby(age_group)[spending].mean())排名 rankmin排名不连续排名相同取 排名数字最小值 2max排名不连续排名相同取 排名数字最大值 3average排名不连续排名相同取 排名相同的平均值 2.5 默认值average排名连续排名相同按照顺序来排2,3dense排名顺序连续相同排名取最小值dfpd.DataFrame({姓名:[小明,小美,小强,小兰],成绩:[100,90,90,80]})df[成绩min]df[成绩].rank(methodmin,ascendingFalse)df[成绩max]df[成绩].rank(methodmax,ascendingFalse)df[成绩average]df[成绩].rank(methodaverage,ascendingFalse)df[成绩first]df[成绩].rank(methodfirst,ascendingFalse)df[成绩dense]df[成绩].rank(methoddense,ascendingFalse)df[成绩默认]df[成绩].rank(ascendingFalse)print(df)姓名 成绩 成绩min成绩max成绩average 成绩first 成绩dense 成绩默认0小明1001.01.01.01.01.01.01小美902.03.02.52.02.02.52小强902.03.02.53.02.02.53小兰804.04.04.04.03.04.0旋转 T行列转换importpandasaspd pd.options.display.max_columns999dfpd.DataFrame([(1,张三,90),(2,李四,70),(3,张三,90)],columns(id,name,chinese))df.set_index(id,inplaceTrue)transposedf.transpose()print(transpose)print(df.T)