Python - Pandas系列 - 最强pandas.DataFrame.agg解释

官方网址:https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.aggregate.html

目的

该篇文章主要线路为探索agg的基本用法,以及对应有哪些适用场景,最后做一个简单探索源代码层。

1、介绍agg的参数及使用demo

2、GroupBy的agg用法案例

3、通过查看底层推演agg的路线原理

1、介绍agg的参数及使用demo

aggaggregate的别名

DataFrame.aggregate(func=None, axis=0, args,kwargs)

参数名解释传参格式例如
func用于汇总数据的功能。如果是函数,则必须在传递DataFrame或传递给DataFrame.apply时起作用。函数,str,列表或字典[np.sum, ‘mean’]
axis如果为0或’index’:将函数应用于每一列。如果为1或“列”:将函数应用于每一行。{0或’index’,1或’columns’},默认01

它会return的数据类型一般为:标量(值)、Series、DataFrame三种。

对应可以使用

标量:使用单个函数调用Series.agg

Series:使用单个函数调用DataFrame.agg

DaFrame:使用多个函数调用DataFrame.agg

返回例子

标量

s_df = pd.Series([1,2,3])
print(s_df)
print(s_df.agg(sum))
---------return----------
0    1
1    2
2    3
dtype: int64

6

Seires

df = pd.DataFrame([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9],
                   [np.nan, np.nan, np.nan]],
                  columns=['A', 'B', 'C'])

print(df)
-----return------
     A    B    C
0  1.0  2.0  3.0
1  4.0  5.0  6.0
2  7.0  8.0  9.0
3  NaN  NaN  NaN

print(df.agg(sum))
----return------
A    12.0
B    15.0
C    18.0
dtype: float64

DataFrame

# 在行上汇总这些功能
print(df.agg(['sum', 'min'])
----return----
      A     B     C
sum  12.0  15.0  18.0
min   1.0   2.0   3.0
      
# 每列不同的聚合
print(df.agg({'A' : ['sum', 'min'], 'B' : ['min', 'max']}))
----return----
        A    B
sum  12.0  NaN
min   1.0  2.0
max   NaN  8.0

# 在列上聚合不同的函数,然后重命名结果DataFrame的索引
print(df.agg(x=('A', max), y=('B', 'min'), z=('C', np.mean)))
----return----
     A    B    C
x  7.0  NaN  NaN
y  NaN  2.0  NaN
z  NaN  NaN  6.0

2、GroupBy的agg用法案例

数据构造

import pandas as pd
 
df = pd.DataFrame({'Country':['China','China', 'India', 'India', 'America', 'Japan', 'China', 'India'], 
                   'Income':[10000, 10000, 5000, 5002, 40000, 50000, 8000, 5000],
                    'Age':[5000, 4321, 1234, 4010, 250, 250, 4500, 4321]})

----return----
 Age  Country  Income
0  5000    China   10000
1  4321    China   10000
2  1234    India    5000
3  4010    India    5002
4   250  America   40000
5   250    Japan   50000
6  4500    China    8000
7  4321    India    5000

接下来会按照城市分组,用print()方法给认知groupby的分组逻辑

df.groupby(['Country']).apply(lambda x: print(x,type(x)))

----print----
   Country  Income  Age
4  America   40000  250 <class 'pandas.core.frame.DataFrame'>
  Country  Income   Age
0   China   10000  5000
1   China   10000  4321
6   China    8000  4500 <class 'pandas.core.frame.DataFrame'>
  Country  Income   Age
2   India    5000  1234
3   India    5002  4010
7   India    5000  4321 <class 'pandas.core.frame.DataFrame'>
  Country  Income  Age
5   Japan   50000  250 <class 'pandas.core.frame.DataFrame'>

这儿其实就很清晰了,分组里面的结果就是一个个分组后的DataFrame。所以针对Groupby后agg的用法,就是DataFrame.agg的用法,不用额外说什么,照样是 列表、字典 形式传入。

列表传参

df_agg = df.groupby('Country').agg(['min', 'mean', 'max'])
print(df_agg)

----print----
        Income                        Age                   
           min          mean    max   min         mean   max
Country                                                     
America  40000  40000.000000  40000   250   250.000000   250
China     8000   9333.333333  10000  4321  4607.000000  5000
India     5000   5000.666667   5002  1234  3188.333333  4321
Japan    50000  50000.000000  50000   250   250.000000   250

字典传参

print(df.groupby('Country').agg({'Age':['min', 'mean', 'max'], 'Income':['min', 'max']}))

---print---
      Age                    Income       
          min         mean   max    min    max
Country                                       
America   250   250.000000   250  40000  40000
China    4321  4607.000000  5000   8000  10000
India    1234  3188.333333  4321   5000   5002
Japan     250   250.000000   250  50000  50000

==总结:==首先了解agg能传什么形式的func,再清晰groupby的形式,就知道groupy+agg结合起来的用法。

3、通过查看底层推演agg的路线原理

为什么要查看这个底层呢?主要是对传func时候,遇到的这几种传参产生好奇,想要知道为什么能这样子传,追根朔源。

这几种传参指的是:

df = pd.DataFrame([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9],
                   [np.nan, np.nan, np.nan]],
                  columns=['A', 'B', 'C'])

print(df.agg([sum, 'sum', np.sum]))
------print-----
        A     B     C
sum  12.0  15.0  18.0
sum  12.0  15.0  18.0
sum  12.0  15.0  18.0

sum"sum"np.sum的作用效果一样,它们的表达形式不同。

开始查阅底层代码

1、agg = aggregate , agg是aggregate的别名,因为一开始底层代码就有这条赋值语句。

在这里插入图片描述

2、agg其实就是调用apply函数,也就是apply函数能用的它也能用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rKIX6aC-1620532935051)(pandas.assets/image-20210430232044882.png)]

  • 做个测试看看,返回的结果是一样的。

  •   print(df.apply([sum, 'sum', np.sum]))
      ----return----
              A     B     C
      sum  12.0  15.0  18.0
      sum  12.0  15.0  18.0
      sum  12.0  15.0  18.0
    

3、所以sum、‘sum’、np.sum 重点是 func 传参解析的作用,而不是函数本身作用。

找一下有关func的注释

func : function
            Function to apply to each column or row.
# 解释 函数能用于行或列而已

 If you are just applying a NumPy reduction function this will
              achieve much better performance.
# 这儿就说如果用numpy的函数,能有更好表现,可以说明np.sum 与 sum 是调用不同模块的函数

找了半天,虽然猜测是 ‘sum’转为sum使用了,但是仍没找到,所以尝试一下这样子。

4、_try_aggregate_string_function 找到转化的原因!

print(df.apply([sum, 'sum', np.sum,'np.sum']))
----error----
...
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\series.py", line 3688, in aggregate
    result, how = self._aggregate(func, *args, **kwargs)
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\base.py", line 477, in _aggregate
    return self._aggregate_multiple_funcs(arg, _axis=_axis), None
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\base.py", line 507, in _aggregate_multiple_funcs
    new_res = colg.aggregate(a)
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\series.py", line 3688, in aggregate
    result, how = self._aggregate(func, *args, **kwargs)
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\base.py", line 311, in _aggregate
    return self._try_aggregate_string_function(arg, *args, **kwargs), None
  File "D:\r\Anaconda3\lib\site-packages\pandas\core\base.py", line 282, in _try_aggregate_string_function
    f"'{arg}' is not a valid function for '{type(self).__name__}' object"
AttributeError: 'np.sum' is not a valid function for 'Series' object

重点看_try_aggregate_string_function的报错。

该函数如下

    def _try_aggregate_string_function(self, arg: str, *args, **kwargs):
        """
        if arg is a string, then try to operate on it:
        - try to find a function (or attribute) on ourselves
        - try to find a numpy function
        - raise

        """
        assert isinstance(arg, str)

        f = getattr(self, arg, None)		# 再这里转化的
        if f is not None:
            if callable(f):
                return f(*args, **kwargs)

            # people may try to aggregate on a non-callable attribute
            # but don't let them think they can pass args to it
            assert len(args) == 0
            assert len([kwarg for kwarg in kwargs if kwarg not in ["axis"]]) == 0
            return f

        f = getattr(np, arg, None)
        if f is not None:
            if hasattr(self, "__array__"):
                # in particular exclude Window
                return f(self, *args, **kwargs)

        raise AttributeError(
            f"'{arg}' is not a valid function for '{type(self).__name__}' object"
        )

转化的函数是这个f = getattr(np, arg, None),它能找到对应是否有函数,注释也有说,如果arg是string格式,会去寻找它本身是否有这个函数,找不到再去寻找numpy模块的,再找不到就报错。

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值