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'},默认0 1

它会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的别名,因为一开始底层代码就有这条赋值语句。

image.png

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

image.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模块的,再找不到就报错。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容