pandas100个骚操作:groupby 8 个常用技巧!

简介: pandas的groupby是数据处理中一个非常强大的功能。虽然很多同学已已经非常熟悉了,但有些小技巧还是要和大家普及一下的。

然很多同学已已经非常熟悉了,但有些小技巧还是要和大家普及一下的。为了给大家演示,我们采用一个公开的数据集进行说明。


import pandas as pd
iris = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv')


随机采样5条,数据是长这样子的。


>>> iris.sample(5)
     sepal_length  sepal_width  petal_length  petal_width     species
95            5.7          3.0           4.2          1.2  versicolor
71            6.1          2.8           4.0          1.3  versicolor
133           6.3          2.8           5.1          1.5   virginica
4             5.0          3.6           1.4          0.2      setosa
33            5.5          4.2           1.4          0.2      setosa


因为是分组功能,所以被分的对象肯定是类别型的。在这个数据里,这里我们就以species进行分组举例。

首先,以species分组创建一个groupbyobject。这里单独生成groupby对象是因为后面会反复用到,其实用的熟练了直接链接起来就可以了。


iris_gb = iris.groupby('species')


一、创建频率表


假如我想知道每个species类中的数量有多少,那么直接使用groupbysize函数即可,如下。


>>> iris_gb.size()
species
setosa        50
versicolor    50
virginica     50
dtype: int64


二、计算常用的描述统计量


比如,我想要按组计算均值,那么就用mean()函数。


>>> # 计算均值
>>> iris_gb.mean()
            sepal_length  sepal_width  petal_length  petal_width
species                                                         
setosa             5.006        3.428         1.462        0.246
versicolor         5.936        2.770         4.260        1.326
virginica          6.588        2.974         5.552        2.026


默认情况下如果没有限制,那么mean()函数将对所有变量特征计算均值。如果我希望只计算某一个变量的均值,可以指定该变量,如下所示。


>>> # 单列
>>> iris_gb['sepal_length'].mean()
species
setosa        5.006
versicolor    5.936
virginica     6.588
Name: sepal_length, dtype: float64
>>> # 双列
>>> iris_gb[['sepal_length', 'petal_length']].mean()
            sepal_length  petal_length
species                               
setosa             5.006         1.462
versicolor         5.936         4.260
virginica          6.588         5.552


同理,其它描述性统计量minmax()medianhestd都是一样的用法。


三、查找最大值(最小值)索引


如果我们要查找每个组的最大值或最小值的索引时,有一个方便的功能可以直接使用。


>>> iris_gb.idxmax()
            sepal_length  sepal_width  petal_length  petal_width
species                                                         
setosa                14           15            24           43
versicolor            50           85            83           70
virginica            131          117           118          100


如何应用呢?

比如我们想查找每组sepal_length最大值对应的整条记录时,就可以这样用。注意,这里是整条记录,相当于按sepal_length最大值这个条件进行了筛选。


>>> sepal_largest = iris.loc[iris_gb['sepal_length'].idxmax()]
>>> sepal_largest
     sepal_length  sepal_width  petal_length  petal_width     species
14            5.8          4.0           1.2          0.2      setosa
50            7.0          3.2           4.7          1.4  versicolor
131           7.9          3.8           6.4          2.0   virginica


四、Groupby之后重置索引


很多时候,我们在groupby处理后还要进行其他操作。也就是说,我们想重置分组索引以使其成为正常的行和列。

第一种方法可能大家常用,就是通过reset_index()让乱序索引重置。


>>> iris_gb.max().reset_index()
      species  sepal_length  sepal_width  petal_length  petal_width
0      setosa           5.8          4.4           1.9          0.6
1  versicolor           7.0          3.4           5.1          1.8
2   virginica           7.9          3.8           6.9          2.5


但其实,还有一个看上去更加友好的用法。可以在groupby的时候就设置as_index参数,也可以达到同样效果。


>>> iris.groupby('species', as_index=False).max()
      species  sepal_length  sepal_width  petal_length  petal_width
0      setosa           5.8          4.4           1.9          0.6
1  versicolor           7.0          3.4           5.1          1.8
2   virginica           7.9          3.8           6.9          2.5


五、多种统计量汇总


上面都是单个统计量的操作,那如果我想同时操作好几个呢?

groupby还有一个超级棒的用法就是和聚合函数agg连起来使用。


>>> iris_gb[['sepal_length', 'petal_length']].agg(["min", "mean"])
           sepal_length        petal_length       
                    min   mean          min   mean
species                                           
setosa              4.3  5.006          1.0  1.462
versicolor          4.9  5.936          3.0  4.260
virginica           4.9  6.588          4.5  5.552


agg里面,我们只要列出统计量的名称即可,便可同时对每个列进行多维度统计。


六、特定列的聚合


我们也看到了,上面是的多个操作对于每个列都是一样的。实际使用过程中,我们可能对于每个列的需求都是不一样的。

所以在这种情况下,我们可以通过为不同的列单独设置不同的统计量。


>>> iris_gb.agg({"sepal_length": ["min", "max"], "petal_length": ["mean", "std"]})
           sepal_length      petal_length          
                    min  max         mean       std
species                                            
setosa              4.3  5.8        1.462  0.173664
versicolor          4.9  7.0        4.260  0.469911
virginica           4.9  7.9        5.552  0.551895


7、NamedAgg命名统计量


现在我又有新的想法了。上面的多级索引看起来有点不太友好,我想把每个列下面的统计量和列名分别合并起来。可以使用NamedAgg来完成列的命名。


>>> iris_gb.agg(
...     sepal_min=pd.NamedAgg(column="sepal_length", aggfunc="min"),
...     sepal_max=pd.NamedAgg(column="sepal_length", aggfunc="max"),
...     petal_mean=pd.NamedAgg(column="petal_length", aggfunc="mean"),
...     petal_std=pd.NamedAgg(column="petal_length", aggfunc="std")
... )
            sepal_min  sepal_max  petal_mean  petal_std
species                                                
setosa            4.3        5.8       1.462   0.173664
versicolor        4.9        7.0       4.260   0.469911
virginica         4.9        7.9       5.552   0.551895


因为NamedAgg是一个元组,所以我们也可以直接赋值元组给新的命名,效果一样,但看上去更简洁。


iris_gb.agg(
    sepal_min=("sepal_length", "min"),
    sepal_max=("sepal_length", "max"),
    petal_mean=("petal_length", "mean"),
    petal_std=("petal_length", "std")
)


八、使用自定义函数


上面agg聚合函数中我们都是通过添加一个统计量名称来完成操作的,除此之外我们也可直接给一个功能对象。


>>> iris_gb.agg(pd.Series.mean)
            sepal_length  sepal_width  petal_length  petal_width
species                                                         
setosa             5.006        3.428         1.462        0.246
versicolor         5.936        2.770         4.260        1.326
virginica          6.588        2.974         5.552        2.026


不仅如此,名称和功能对象也可一起使用。


iris_gb.agg(["min", pd.Series.mean])


更骚的是,我们还可以自定义函数,也都是可以的。


>>> def double_length(x):
...     return 2*x.mean()
... 
>>> iris_gb.agg(double_length)
            sepal_length  sepal_width  petal_length  petal_width
species                                                         
setosa            10.012        6.856         2.924        0.492
versicolor        11.872        5.540         8.520        2.652
virginica         13.176        5.948        11.104        4.052


当然如果想更简洁,也可以使用lambda函数。总之,用法非常灵活,可以自由组合搭配。


iris_gb.agg(lambda x: x.mean())

以上就是使用groupby过程中可能会用到的8个操作,如果你熟练使用起来会发现这个功能是真的很强大。如果喜欢东哥的骚操作,请给我点个赞和在看参考:https://towardsdatascience.com/8-things-to-know-to-get-started-with-with-pandas-groupby-3086dc91acb4


我是东哥,最近正在原创👉「pandas100个骚操作」系列话题,欢迎订阅。订阅后,文章更新可第一时间推送至订阅号,每篇都不错过。

相关文章
|
3月前
|
数据挖掘 Python
pandas中的groupby函数应用
pandas中的groupby函数应用
20 0
pandas中的groupby函数应用
|
3月前
|
数据挖掘 数据处理 Python
Pandas中groupby后的数据排序技巧
Pandas中groupby后的数据排序技巧
173 0
|
4月前
|
SQL 数据挖掘 数据处理
不再纠结,一文详解pandas中的map、apply、applymap、groupby、agg...
不再纠结,一文详解pandas中的map、apply、applymap、groupby、agg...
|
6月前
|
Python
pandas中groupby和shift结合实现相邻行的计算
pandas中groupby和shift结合实现相邻行的计算
102 0
Pandas groupby分组后求各组行数
Pandas groupby分组后求各组行数
Pandas groupby分组后求各组行数
|
数据可视化 数据挖掘 API
5分钟掌握Pandas GroupBy
5分钟掌握Pandas GroupBy
156 0
5分钟掌握Pandas GroupBy
|
算法 数据挖掘 C语言
Pandas数据分析之groupby妙用
今天本人在赶学校课程作业的时候突然发现groupby这个分组函数还是蛮有用的,有了这个分组之后你可以实现很多统计目标。 当然,最主要的是,他的使用非常简单 本期我们以上期作业为例,单走一篇文章来看看这个函数可以实现哪些功能:
Pandas数据分析之groupby妙用
|
关系型数据库 MySQL Python
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(五)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(五)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(五)
|
关系型数据库 MySQL Python
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(四)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(四)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(四)
|
关系型数据库 MySQL 索引
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(三)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(三)
DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)(三)