Pandas高级教程之Pandas中的GroupBy操作

目录
  • 简介
  • 分割数据
    • 多index
    • get_group
    • dropna
    • groups属性
    • index的层级
  • group的遍历
  • 聚合操作
    • 通用聚合方法
    • 可以同时指定多个聚合方法:
    • NamedAgg
    • 不同的列指定不同的聚合方法
  • 转换操作
  • 过滤操作
  • Apply操作

简介

pandas中的DF数据类型可以像数据库表格一样进行groupby操作。通常来说groupby操作可以分为三部分:分割数据,应用变换和和合并数据。

本文将会详细讲解Pandas中的groupby操作。

分割数据

分割数据的目的是将DF分割成为一个个的group。为了进行groupby操作,在创建DF的时候需要指定相应的label:

df = pd.DataFrame(
   ...:     {
   ...:         "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
   ...:         "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
   ...:         "C": np.random.randn(8),
   ...:         "D": np.random.randn(8),
   ...:     }
   ...: )
   ...:

df
Out[61]:
     A      B         C         D
0  foo    one -0.490565 -0.233106
1  bar    one  0.430089  1.040789
2  foo    two  0.653449 -1.155530
3  bar  three -0.610380 -0.447735
4  foo    two -0.934961  0.256358
5  bar    two -0.256263 -0.661954
6  foo    one -1.132186 -0.304330
7  foo  three  2.129757  0.445744

默认情况下,groupby的轴是x轴。可以一列group,也可以多列group:

In [8]: grouped = df.groupby("A")

In [9]: grouped = df.groupby(["A", "B"])

多index

0.24版本中,如果我们有多index,可以从中选择特定的index进行group:

In [10]: df2 = df.set_index(["A", "B"])

In [11]: grouped = df2.groupby(level=df2.index.names.difference(["B"]))

In [12]: grouped.sum()
Out[12]:
            C         D
A
bar -1.591710 -1.739537
foo -0.752861 -1.402938

get_group

get_group 可以获取分组之后的数据:

In [24]: df3 = pd.DataFrame({"X": ["A", "B", "A", "B"], "Y": [1, 4, 3, 2]})

In [25]: df3.groupby(["X"]).get_group("A")
Out[25]:
   X  Y
0  A  1
2  A  3

In [26]: df3.groupby(["X"]).get_group("B")
Out[26]:
   X  Y
1  B  4
3  B  2

dropna

默认情况下,NaN数据会被排除在groupby之外,通过设置 dropna=False 可以允许NaN数据:

In [27]: df_list = [[1, 2, 3], [1, None, 4], [2, 1, 3], [1, 2, 2]]

In [28]: df_dropna = pd.DataFrame(df_list, columns=["a", "b", "c"])

In [29]: df_dropna
Out[29]:
   a    b  c
0  1  2.0  3
1  1  NaN  4
2  2  1.0  3
3  1  2.0  2
# Default ``dropna`` is set to True, which will exclude NaNs in keys
In [30]: df_dropna.groupby(by=["b"], dropna=True).sum()
Out[30]:
     a  c
b
1.0  2  3
2.0  2  5

# In order to allow NaN in keys, set ``dropna`` to False
In [31]: df_dropna.groupby(by=["b"], dropna=False).sum()
Out[31]:
     a  c
b
1.0  2  3
2.0  2  5
NaN  1  4

groups属性

groupby对象有个groups属性,它是一个key-value字典,key是用来分类的数据,value是分类对应的值。

In [34]: grouped = df.groupby(["A", "B"])

In [35]: grouped.groups
Out[35]: {('bar', 'one'): [1], ('bar', 'three'): [3], ('bar', 'two'): [5], ('foo', 'one'): [0, 6], ('foo', 'three'): [7], ('foo', 'two'): [2, 4]}

In [36]: len(grouped)
Out[36]: 6

index的层级

对于多级index对象,groupby可以指定group的index层级:

In [40]: arrays = [
   ....:     ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
   ....:     ["one", "two", "one", "two", "one", "two", "one", "two"],
   ....: ]
   ....: 

In [41]: index = pd.MultiIndex.from_arrays(arrays, names=["first", "second"])

In [42]: s = pd.Series(np.random.randn(8), index=index)

In [43]: s
Out[43]:
first  second
bar    one      -0.919854
       two      -0.042379
baz    one       1.247642
       two      -0.009920
foo    one       0.290213
       two       0.495767
qux    one       0.362949
       two       1.548106
dtype: float64

group第一级:

In [44]: grouped = s.groupby(level=0)

In [45]: grouped.sum()
Out[45]:
first
bar   -0.962232
baz    1.237723
foo    0.785980
qux    1.911055
dtype: float64

group第二级:

In [46]: s.groupby(level="second").sum()
Out[46]:
second
one    0.980950
two    1.991575
dtype: float64

group的遍历

得到group对象之后,我们可以通过for语句来遍历group:

In [62]: grouped = df.groupby('A')

In [63]: for name, group in grouped:
   ....:     print(name)
   ....:     print(group)
   ....:
bar
     A      B         C         D
1  bar    one  0.254161  1.511763
3  bar  three  0.215897 -0.990582
5  bar    two -0.077118  1.211526
foo
     A      B         C         D
0  foo    one -0.575247  1.346061
2  foo    two -1.143704  1.627081
4  foo    two  1.193555 -0.441652
6  foo    one -0.408530  0.268520
7  foo  three -0.862495  0.024580

如果是多字段group,group的名字是一个元组:

In [64]: for name, group in df.groupby(['A', 'B']):
   ....:     print(name)
   ....:     print(group)
   ....:
('bar', 'one')
     A    B         C         D
1  bar  one  0.254161  1.511763
('bar', 'three')
     A      B         C         D
3  bar  three  0.215897 -0.990582
('bar', 'two')
     A    B         C         D
5  bar  two -0.077118  1.211526
('foo', 'one')
     A    B         C         D
0  foo  one -0.575247  1.346061
6  foo  one -0.408530  0.268520
('foo', 'three')
     A      B         C        D
7  foo  three -0.862495  0.02458
('foo', 'two')
     A    B         C         D
2  foo  two -1.143704  1.627081
4  foo  two  1.193555 -0.441652

聚合操作

分组之后,就可以进行聚合操作:

In [67]: grouped = df.groupby("A")

In [68]: grouped.aggregate(np.sum)
Out[68]:
            C         D
A
bar  0.392940  1.732707
foo -1.796421  2.824590

In [69]: grouped = df.groupby(["A", "B"])

In [70]: grouped.aggregate(np.sum)
Out[70]:
                  C         D
A   B
bar one    0.254161  1.511763
    three  0.215897 -0.990582
    two   -0.077118  1.211526
foo one   -0.983776  1.614581
    three -0.862495  0.024580
    two    0.049851  1.185429

对于多index数据来说,默认返回值也是多index的。如果想使用新的index,可以添加 as_index = False:

In [71]: grouped = df.groupby(["A", "B"], as_index=False)

In [72]: grouped.aggregate(np.sum)
Out[72]:
     A      B         C         D
0  bar    one  0.254161  1.511763
1  bar  three  0.215897 -0.990582
2  bar    two -0.077118  1.211526
3  foo    one -0.983776  1.614581
4  foo  three -0.862495  0.024580
5  foo    two  0.049851  1.185429

In [73]: df.groupby("A", as_index=False).sum()
Out[73]:
     A         C         D
0  bar  0.392940  1.732707
1  foo -1.796421  2.824590

上面的效果等同于reset_index

In [74]: df.groupby(["A", "B"]).sum().reset_index()

grouped.size() 计算group的大小:

In [75]: grouped.size()
Out[75]:
     A      B  size
0  bar    one     1
1  bar  three     1
2  bar    two     1
3  foo    one     2
4  foo  three     1
5  foo    two     2

grouped.describe() 描述group的信息:

In [76]: grouped.describe()
Out[76]:
      C                                                    ...         D
  count      mean       std       min       25%       50%  ...       std       min       25%       50%       75%       max
0   1.0  0.254161       NaN  0.254161  0.254161  0.254161  ...       NaN  1.511763  1.511763  1.511763  1.511763  1.511763
1   1.0  0.215897       NaN  0.215897  0.215897  0.215897  ...       NaN -0.990582 -0.990582 -0.990582 -0.990582 -0.990582
2   1.0 -0.077118       NaN -0.077118 -0.077118 -0.077118  ...       NaN  1.211526  1.211526  1.211526  1.211526  1.211526
3   2.0 -0.491888  0.117887 -0.575247 -0.533567 -0.491888  ...  0.761937  0.268520  0.537905  0.807291  1.076676  1.346061
4   1.0 -0.862495       NaN -0.862495 -0.862495 -0.862495  ...       NaN  0.024580  0.024580  0.024580  0.024580  0.024580
5   2.0  0.024925  1.652692 -1.143704 -0.559389  0.024925  ...  1.462816 -0.441652  0.075531  0.592714  1.109898  1.627081

[6 rows x 16 columns]

通用聚合方法

下面是通用的聚合方法:

函数 描述
mean() 平均值
sum() 求和
size() 计算size
count() group的统计
std() 标准差
var() 方差
sem() 均值的标准误
describe() 统计信息描述
first() 第一个group值
last() 最后一个group值
nth() 第n个group值
min() 最小值
max() 最大值

可以同时指定多个聚合方法:

In [81]: grouped = df.groupby("A")

In [82]: grouped["C"].agg([np.sum, np.mean, np.std])
Out[82]:
          sum      mean       std
A
bar  0.392940  0.130980  0.181231
foo -1.796421 -0.359284  0.912265

可以重命名:

In [84]: (
   ....:     grouped["C"]
   ....:     .agg([np.sum, np.mean, np.std])
   ....:     .rename(columns={"sum": "foo", "mean": "bar", "std": "baz"})
   ....: )
   ....:
Out[84]:
          foo       bar       baz
A
bar  0.392940  0.130980  0.181231
foo -1.796421 -0.359284  0.912265

NamedAgg

NamedAgg 可以对聚合进行更精准的定义,它包含 column 和aggfunc 两个定制化的字段。

In [88]: animals = pd.DataFrame(
   ....:     {
   ....:         "kind": ["cat", "dog", "cat", "dog"],
   ....:         "height": [9.1, 6.0, 9.5, 34.0],
   ....:         "weight": [7.9, 7.5, 9.9, 198.0],
   ....:     }
   ....: )
   ....: 

In [89]: animals
Out[89]:
  kind  height  weight
0  cat     9.1     7.9
1  dog     6.0     7.5
2  cat     9.5     9.9
3  dog    34.0   198.0

In [90]: animals.groupby("kind").agg(
   ....:     min_height=pd.NamedAgg(column="height", aggfunc="min"),
   ....:     max_height=pd.NamedAgg(column="height", aggfunc="max"),
   ....:     average_weight=pd.NamedAgg(column="weight", aggfunc=np.mean),
   ....: )
   ....:
Out[90]:
      min_height  max_height  average_weight
kind
cat          9.1         9.5            8.90
dog          6.0        34.0          102.75

或者直接使用一个元组:

In [91]: animals.groupby("kind").agg(
   ....:     min_height=("height", "min"),
   ....:     max_height=("height", "max"),
   ....:     average_weight=("weight", np.mean),
   ....: )
   ....:
Out[91]:
      min_height  max_height  average_weight
kind
cat          9.1         9.5            8.90
dog          6.0        34.0          102.75

不同的列指定不同的聚合方法

通过给agg方法传入一个字典,可以指定不同的列使用不同的聚合:

In [95]: grouped.agg({"C": "sum", "D": "std"})
Out[95]:
            C         D
A
bar  0.392940  1.366330
foo -1.796421  0.884785

转换操作

转换是将对象转换为同样大小对象的操作。在数据分析的过程中,经常需要进行数据的转换操作。

可以接lambda操作:

In [112]: ts.groupby(lambda x: x.year).transform(lambda x: x.max() - x.min())

填充na值:

In [121]: transformed = grouped.transform(lambda x: x.fillna(x.mean()))

过滤操作

filter方法可以通过lambda表达式来过滤我们不需要的数据:

In [136]: sf = pd.Series([1, 1, 2, 3, 3, 3])

In [137]: sf.groupby(sf).filter(lambda x: x.sum() > 2)
Out[137]:
3    3
4    3
5    3
dtype: int64

Apply操作

有些数据可能不适合进行聚合或者转换操作,Pandas提供了一个 apply 方法,用来进行更加灵活的转换操作。

In [156]: df
Out[156]:
     A      B         C         D
0  foo    one -0.575247  1.346061
1  bar    one  0.254161  1.511763
2  foo    two -1.143704  1.627081
3  bar  three  0.215897 -0.990582
4  foo    two  1.193555 -0.441652
5  bar    two -0.077118  1.211526
6  foo    one -0.408530  0.268520
7  foo  three -0.862495  0.024580

In [157]: grouped = df.groupby("A")

# could also just call .describe()
In [158]: grouped["C"].apply(lambda x: x.describe())
Out[158]:
A
bar  count    3.000000
     mean     0.130980
     std      0.181231
     min     -0.077118
     25%      0.069390
                ...
foo  min     -1.143704
     25%     -0.862495
     50%     -0.575247
     75%     -0.408530
     max      1.193555
Name: C, Length: 16, dtype: float64

可以外接函数:

In [159]: grouped = df.groupby('A')['C']

In [160]: def f(group):
   .....:     return pd.DataFrame({'original': group,
   .....:                          'demeaned': group - group.mean()})
   .....: 

In [161]: grouped.apply(f)
Out[161]:
   original  demeaned
0 -0.575247 -0.215962
1  0.254161  0.123181
2 -1.143704 -0.784420
3  0.215897  0.084917
4  1.193555  1.552839
5 -0.077118 -0.208098
6 -0.408530 -0.049245
7 -0.862495 -0.503211

本文已收录于 http://www.flydean.com/11-python-pandas-groupby/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

到此这篇关于Pandas高级教程之Pandas中的GroupBy操作的文章就介绍到这了,更多相关Pandas GroupBy用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • pandas groupby 分组取每组的前几行记录方法

    直接上例子. import pandas as pd df = pd.DataFrame({'class':['a','a','b','b','a','a','b','c','c'],'score':[3,5,6,7,8,9,10,11,14]}) df: class score 0 a 3 1 a 5 2 b 6 3 b 7 4 a 8 5 a 9 6 b 10 7 c 11 8 c 14 df.sort_values(['class','score'],ascending=[1,0],inp

  • pandas之分组groupby()的使用整理与总结

    前言 在使用pandas的时候,有些场景需要对数据内部进行分组处理,如一组全校学生成绩的数据,我们想通过班级进行分组,或者再对班级分组后的性别进行分组来进行分析,这时通过pandas下的groupby()函数就可以解决.在使用pandas进行数据分析时,groupby()函数将会是一个数据分析辅助的利器. groupby的作用可以参考 超好用的 pandas 之 groupby 中作者的插图进行直观的理解: 准备 读入的数据是一段学生信息的数据,下面将以这个数据为例进行整理grouby()函数的

  • Pandas之groupby( )用法笔记小结

    groupby官方解释 DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs) Group series using mapper (dict or key function, apply given function to group, return result as series) or by a series of

  • 浅谈pandas用groupby后对层级索引levels的处理方法

    层及索引levels,刚开始学习pandas的时候没有太多的操作关于groupby,仅仅是简单的count.sum.size等等,没有更深入的利用groupby后的数据进行处理.近来数据处理的时候有遇到这类问题花了一点时间,所以这里记录以及复习一下:(以下皆是个人实践后的理解) 我使用一个实例来讲解下面的问题:一张数据表中有三列(动物物种.物种品种.品种价格),选出每个物种从大到小品种的前两种,最后只需要品种和价格这两列. 以上这张表是我们后面需要处理的数据表 (物种 品种 价格) levels

  • pandas获取groupby分组里最大值所在的行方法

    pandas获取groupby分组里最大值所在的行方法 如下面这个DataFrame,按照Mt分组,取出Count最大的那行 import pandas as pd df = pd.DataFrame({'Sp':['a','b','c','d','e','f'], 'Mt':['s1', 's1', 's2','s2','s2','s3'], 'Value':[1,2,3,4,5,6], 'Count':[3,2,5,10,10,6]}) df Count Mt Sp Value 0 3 s1

  • pandas数据预处理之dataframe的groupby操作方法

    在数据预处理过程中可能会遇到这样的问题,如下图:数据中某一个key有多组数据,如何分别对每个key进行相同的运算? dataframe里面给出了一个group by的一个操作,对于"group by"操作,我们通常是指以下一个或多个操作步骤: l (Splitting)按照一些规则将数据分为不同的组: l (Applying)对于每组数据分别执行一个函数: l (Combining)将结果组合到一个数据结构中: 使用dataframe实现groupby的用法: # -*- coding

  • Pandas高级教程之Pandas中的GroupBy操作

    目录 简介 分割数据 多index get_group dropna groups属性 index的层级 group的遍历 聚合操作 通用聚合方法 可以同时指定多个聚合方法: NamedAgg 不同的列指定不同的聚合方法 转换操作 过滤操作 Apply操作 简介 pandas中的DF数据类型可以像数据库表格一样进行groupby操作.通常来说groupby操作可以分为三部分:分割数据,应用变换和和合并数据. 本文将会详细讲解Pandas中的groupby操作. 分割数据 分割数据的目的是将DF分

  • Python Pandas教程之series 上的转换操作

    前言: 在转换操作中,我们执行各种操作,例如更改系列的数据类型,将系列更改为列表等.为了执行转换操作,我们有各种有助于转换的功能,例如.astype()等.tolist(). 代码#1: # 使用 astype 转换 series 数据类型的 Python 程序 # importing pandas module import pandas as pd # 从 url 读取 csv 文件 data = pd.read_csv("nba.csv") # 删除空值列以避免错误 data.d

  • pandas进阶教程之Dataframe的apply方法

    目录 apply方法介绍 用例1 用例2 用例3 总结 apply方法介绍 方法形式为 apply(func, axis=0, raw=False, result_type=None, agrs=(), **kwargs),沿Dataframe的轴应用func函数. 传递给函数的对象是Series对象,当axis=0时,其索引是Dataframe的索引:当axis=1时,其索引是Dataframe的列. 默认情况下,result_type=None,最终返回的类型是从func函数的返回推断出来的

  • pytorch教程之Tensor的值及操作使用学习

    目录 1.Tensors 建立5*3的矩阵,未初始化 建立随机初始化矩阵 建立零初始化矩阵,数据类型是Long 建立一个tensor数据来源于data 获取tensor的size 2.对Tensor的操作 实现加法的四种方式 所有原地替换 使用标准的numpy操作 使用torch.view 改变tensor的形状 tensor转化为numpy的数字,使用item Torch Tensor 和numpy的相互转换 将numpy array转化为pytorch Tensor CUDA Tensors

  • Angular2学习教程之ng中变更检测问题详解

    开发中遇到的问题 在开发中遇到一个这样的问题,代码不便透露,这里用简单的例子还原一下问题所在: 有三个组件,第一个是用来展示Todo列表的组件TodoComponent,Todo是个类,包含id和name属性. @Component({ selector: 'todo-list', template: ` <p *ngFor='let item of todos'>{{ item.name }}</p> `, }) export class TodoComponent{ @Inpu

  • Spring Boot高级教程之Spring Boot连接MySql数据库

    Spring Boot可以大大简化持久化任务,几乎不需要写SQL语句,在之前章节"Spring Boot 构建框架"中我们新建了一个Spring Boot应用程序,本章在原有的工程中与数据库建立连接. Spring Boot有两种方法与数据库建立连接,一种是使用JdbcTemplate,另一种集成Mybatis,下面分别为大家介绍一下如何集成和使用这两种方式. 1. 使用JdbcTemplate <dependency> <groupId>mysql</g

  • iOS学习教程之UIView中坐标转换详解

    本文主要介绍的是关于iOS UIView坐标转换的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 在开发中我们经常会需要判断两个控件是否包含重叠,此时如果控件A和B的坐标原点如果不确定的话,那么肯定会导致比较不正确发生错误 判断包含重叠的代码如下: CGRectContainsRect(<#CGRect rect1#>, <#CGRect rect2#>) CGRectContainsPoint(<#CGRect rect#>, <#CGPoint

  • WMI入门教程之WMI中的类在哪里?

    使用WMI归根到底是对WMI类的访问,如何找到合适的类是其中关键的一步.我一直在为找不到合适的类和命名空间苦恼.你也有这样的问题吗? 类层次结构 WMI的类是以命名空间和继承层次方式组织的,呈树形结构.命名空间的根是root,在它的下面还有十几个命名空间,最常用的是root\cimv2.命名空间的信息存储在静态类__Namespace类中,要查询当前命名空间下的所有命名空间,可以查看__Namespace类的实例.以下是在我的机器上使用PowerShell查询到的命名空间: 复制代码 代码如下:

  • java基本教程之Thread中start()和run()的区别 java多线程教程

    Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start() 和 run()相关源码(基于JDK1.7.0_40) start() 和 run()的区别说明start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用.run()   : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在

  • PHP教程之PHP中shell脚本的使用方法分享

    作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高阶语言中才具有的控制结构,包括循环和分支. PHP经过长时间的发展,很多用户都很了解PHP了,这里我发表一下个人理解,和大家讨论讨论.大多数情况下,我使用 exec() 命令和数据数组处理所有东西.或者对更简单的命令使用 shell_exec(),尤其是不关心结果时.如果仅需返回一个 PHP shell脚本,我就使用 passthru().通常,我

随机推荐