pandas 数据处理groupby apply针对的是所有列

近期碰到一个需求,需要对数据分组然后 分组后的数据还要进行处理
首先创建一个简单的dataframe

df=pd.DataFrame({'a':[1,3,3,3,4],'b':[1,3,3,3,40]})
print(df)

然后我们进行分组完整代码如下:

df=pd.DataFrame({'a':[1,3,3,3,4],'b':[1,3,3,3,40]})
print(df)
df2=df.groupby(by=[df['a'],df['b']]).count()
print(df2)

result:
在这里插入图片描述
居然是一个空列表,这样只有索引了,别的数据没有,所以这种方式行不通
对代码进行更新下:

df=pd.DataFrame({'a':[1,3,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[2,5,2,4,100]})
df2=df['c'].groupby(by=[df['a'],df['b']]).count().apply(lambda x:x+1)
df2=df2.reset_index()
print(df2)

执行结果:
在这里插入图片描述
注意这个里面是针对的C列数据进行了全部行处理,如果写多列那么多列都这样处理,groupby之后的count() 得到的结果是<class ‘pandas.core.frame.DataFrame’>类型
修改下代码在验证我们上面的结论

df=pd.DataFrame({'a':[1,3,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[2,5,41,3,100]})
df2=df[['c','d']].groupby(by=[df['a'],df['b']]).count().apply(lambda x:x+1001)
df2=df2.reset_index()
print(df2)

result:
在这里插入图片描述
c列和D列不一样,但是count数据都是针对非空数据,如果是np.NAN的话,会算作0,这一点和我们Oracle数据库得出的结果一致,非空列不统计在内
验证方式也很简单粗暴

df=pd.DataFrame({'a':[1,3,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[np.NAN,np.NAN,np.NAN,3,100]})
df2=df[['c','d']].groupby(by=[df['a'],df['b']]).count().apply(lambda x:x+1001)
df2=df2.reset_index()
print(df2)

result:
在这里插入图片描述

apply可以对整个dataframe进行处理,每一行每一列都这么干,但是前提要确保类型一致才行,apply和applymap这样效果均可以产生
对于分组之后的数据,没有进行count或者sum或者mean之类聚合操作的,我们可以使用apply来实现这些功能
完整代码如下:

import  pandas as pd
import  numpy as np
def get_price(df):
    result=df[pd.notna(df['d'])].shape[0]
    allcnt = df[['d']].shape[0]
    return result/allcnt
df=pd.DataFrame({'a':[1,1,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[np.NAN,np.NAN,np.NAN,3,100]})
print(type(df.groupby(by=[df['a'],df['b']])))
df2=df.groupby(by=[df['a'],df['b']]).apply(get_price)
print(df2)
df2=df2.reset_index(name='新增加列')
print(df2)
df2=df2.applymap(lambda x:int(x))
print(df2)

result:
在这里插入图片描述
注意到上面groupby之后其实没有列名的,我们这是使用了reset_index(name=?)重新赋值
在上一个更完整的

import  pandas as pd
import  numpy as np
def get_price(df):
    result=df[pd.notna(df['d'])].shape[0]
    allcnt = df[['d']].shape[0]
    return result,allcnt,result/allcnt
df=pd.DataFrame({'a':[1,1,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[np.NAN,np.NAN,np.NAN,3,100]})
print(type(df.groupby(by=[df['a'],df['b']])))
df2=df.groupby(by=[df['a'],df['b']]).apply(get_price)
print(df2)
df2=df2.reset_index(name='新增加列')
print(df2)
df2['分组d列不为空数据行数']=df2['新增加列'].apply(lambda x:x[0])
df2['分组d列总数据行数']=df2['新增加列'].apply(lambda x:x[1])
df2['百分数']=df2['新增加列'].apply(lambda x:x[2])
df2.drop(columns=['新增加列'],inplace=True)
print(df2)

result:

<class 'pandas.core.groupby.generic.DataFrameGroupBy'>
a  b 
1  1     (0, 1, 0.0)
   3     (0, 1, 0.0)
3  3     (1, 2, 0.5)
4  40    (1, 1, 1.0)
dtype: object
   a   b         新增加列
0  1   1  (0, 1, 0.0)
1  1   3  (0, 1, 0.0)
2  3   3  (1, 2, 0.5)
3  4  40  (1, 1, 1.0)
   a   b  分组d列不为空数据行数  分组d列总数据行数  百分数
0  1   1            0          1  0.0
1  1   3            0          1  0.0
2  3   3            1          2  0.5
3  4  40            1          1  1.0

Process finished with exit code 0

可以看到函数

def get_price(df):
    result=df[pd.notna(df['d'])].shape[0]
    allcnt = df[['d']].shape[0]
    return result,allcnt,result/allcnt

这个里面的df针对的分组之后每一组,apply应用的也是针对这个组的数据,本例获取的是空值和不为空的值
如果不能使用sum ,mean,max,min,count这类的聚合函数,我们可以使用这种
当然这里我们也可以对每一组分组之后的数据进行排序
伪代码如下

def sort(x):
    return x.sort_values('columnname',ascending=False)
df.groupby(by=[coluns1,columns..]).apply(sort)

这样就可以对每组数据进行分组

关于pandas 聚合函数几种使用方式

```python
import  pandas as pd
import  numpy as np
def get_price(df):
    result=df[pd.notna(df['d'])].shape[0]
    allcnt = df[['d']].shape[0]
    return result,allcnt,result/allcnt
df=pd.DataFrame({'a':[1,1,3,3,4],'b':[1,3,3,3,40],'c':[2,5,2,4,100],'d':[np.NAN,np.NAN,np.NAN,3,100]})
df2=df.groupby(by=[df['a'],df['b']]).count()
print(df2)
df2=df.groupby(by=[df['a'],df['b']]).agg({'c':'count','d':'count'})
df2=df2.reset_index()
print(df2)
df2=df.groupby(by=[df['a'],df['b']]).agg(ccount2=('c','count'),dcount2=('d','count'))
print(df2)

result:

   c  d
a b       
1 1   1  0
  3   1  0
3 3   2  1
4 40  1  1
   a   b  c  d
0  1   1  1  0
1  1   3  1  0
2  3   3  2  1
3  4  40  1  1
      ccount2  dcount2
a b                   
1 1         1        0
  3         1        0
3 3         2        1
4 40        1        1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值