Pandas数据分析groupby函数深度总结(1)

Pandas数据分析groupby函数深度总结(1)

  • groupby分组数据
    • 加载数据
    • 数据分组
      • 按'Sales Rep'列分组
      • 显示所有分组
      • 选择一个特定的组
      • 计算每组中的行数
      • 按'Sales Rep'中的姓分组
      • 按'Sales Rep'中是否包含有“William”分组
      • 按随机序列分组
      • 按'Val'列分位数分成三组
      • 按制定的'Val'列的范围进行分组
      • pd.Grouper
        • Grouping by year
        • 按季度或其他频率分组
      • 通过多列进行分组

pandas包最强大的函数之一,当属groupby了。但是大多数人对groupby函数研究是很少的,只会使用其中的一小部分功能。

groupby函数允许对数据集采用拆分-应用-组合的方法。这种方法通常用于对数据进行切片和分块,以便数据分析师能够回答特定的问题。

groupby可以做到:

  1. 根据列/条件将数据分组;
  2. 对所有组应用一个函数/转换,并将结果合并为一个输出。

本次深度总结主要有以下两个部分:

  1. groupby分组数据;
  2. 应用函数/转换:apply , agg(regate) , transform 以及 filter,然后合并数据。

本文为系列(1),总结groupby分组数据,代码采用jupyter notebook演示。

groupby分组数据

加载数据

我们使用一个虚构的销售部门的数据。该数据集包括虚构的销售代表、订单引导、交易可能完成的公司、订单值和引导日期等列。
输入:

order_leads = pd.read_csv(
    'https://raw.githubusercontent.com/FBosler/Medium-Data-Exploration/master/order_leads.csv',
    parse_dates = [3]
)
sales_team = pd.read_csv(
    'https://raw.githubusercontent.com/FBosler/Medium-Data-Exploration/master/sales_team.csv',
    parse_dates = [3]
)
df = pd.merge(order_leads,sales_team,on=['Company Id','Company Name'])
df = df.rename(columns={'Order Value':'Val','Converted':'Sale'})
df

输出:

Order Id	Company Id	Company Name	Date	Val	Sale	Sales Rep	Sales Rep Id
0	HZSXLI1IS9RGABZW	D0AUXPP07H6AVSGD	Melancholy Social-Role	2017-10-13	6952	0	William Taylor	ZTZA0ZLYZR85PTUJ
1	582WPS3OW8T6YT0R	D0AUXPP07H6AVSGD	Melancholy Social-Role	2017-09-02	7930	0	William Taylor	ZTZA0ZLYZR85PTUJ
2	KRF65MQZBOYG4Y9T	D0AUXPP07H6AVSGD	Melancholy Social-Role	2016-12-21	5538	1	William Taylor	ZTZA0ZLYZR85PTUJ
3	N3EDZ5V1WGSWW828	D0AUXPP07H6AVSGD	Melancholy Social-Role	2018-06-03	1113	0	William Taylor	ZTZA0ZLYZR85PTUJ
4	QXBC8COXEXGFSPLP	D0AUXPP07H6AVSGD	Melancholy Social-Role	2014-07-26	4596	0	William Taylor	ZTZA0ZLYZR85PTUJ
...	...	...	...	...	...	...	...	...
99995	HKZFX556ZQRZJZWR	APH243SK72T90MPS	Trade-Preparatory Quarterbacks	2017-11-06	7516	0	Ida Woodward	LF3CPWWZKSNB1AXI
99996	962CSDMAJ49E0CRK	APH243SK72T90MPS	Trade-Preparatory Quarterbacks	2018-08-02	442	1	Ida Woodward	LF3CPWWZKSNB1AXI
99997	ZW7RO9TLL6EVVJEC	APH243SK72T90MPS	Trade-Preparatory Quarterbacks	2014-11-02	8544	0	Ida Woodward	LF3CPWWZKSNB1AXI
99998	LNKGIWMZ9RT49IE9	APH243SK72T90MPS	Trade-Preparatory Quarterbacks	2017-04-01	6650	0	Ida Woodward	LF3CPWWZKSNB1AXI
99999	X9Y21H4JWX6OGC2Z	APH243SK72T90MPS	Trade-Preparatory Quarterbacks	2016-07-27	953	0	Ida Woodward	LF3CPWWZKSNB1AXI
100000 rows × 8 columns

数据分组

调用groupby的默认方法是明确提供列名以拆分数据集。然而,这是鲜为人知的是,也可以传递一个Series数据到groupby来分组。唯一限制是该Series与DataFrame具有相同的长度。这意味着可以通过列的已处理版本进行组,而无需为此创建新的辅助列。

按’Sales Rep’列分组

输入:

grouped = df.groupby('Sales Rep')
grouped

输出:

<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f3b06e835e0>

现在创建了一个dataframe的groupby对象。 让我们进一步分析:

显示所有分组

调用分组对象上的组返回每个组的索引列表(因为每行可以通过其索引唯一识别)

输入:

grouped.groups

输出:

{
'Aaron Hendrickson': Int64Index(
[25612, 25613, 25614, 25615, 25616, 25617, 25618, 25619, 25620, 25621,..., 25894, 25895, 25896, 25897, 25898, 25899, 25900, 25901, 25902, 25903], dtype='int64', length=292
),
'Adam Sawyer': Int64Index(
[67140, 67141, 67142, 67143, 67144, 67145, 67146, 67147, 67148, 67149, ..., 67454, 67455, 67456, 67457, 67458, 67459, 67460, 67461, 67462, 67463], dtype='int64', length=324
),
...
'Yvonne Lindsey': Int64Index([20384, 20385, 20386, 20387, 20388, 20389, 20390, 20391, 20392, 20393, 20394, 20395, 20396, 20397, 20398, 20399, 20400, 20401, ... , 20447, 20448, 20449, 20450], dtype='int64', length=67)
}

选择一个特定的组

调用get_group函数,可以返回相应的数据子集。

输入:

grouped.get_group('Aaron Hendrickson')

输出:

Order Id	Company Id	Company Name	Date	Val	Sale	Sales Rep	Sales Rep Id
25612	3BJY12LWBN7D0GJL	CE4544HJOFMONMH2	Follow-Up Boundary	2014-09-04	1940	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
25613	W3HHOSC1H6A1PW37	CE4544HJOFMONMH2	Follow-Up Boundary	2015-09-24	2109	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
25614	G9JKIZO4WD945GBH	CE4544HJOFMONMH2	Follow-Up Boundary	2014-12-06	4300	1	Aaron Hendrickson	AEMLQ09IYM72ACBL
25615	BKIJVKZ7REVN6P8B	CE4544HJOFMONMH2	Follow-Up Boundary	2017-05-07	3026	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
25616	WFHGWR4PAD04A2GJ	CE4544HJOFMONMH2	Follow-Up Boundary	2016-01-20	5033	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
...	...	...	...	...	...	...	...	...
25899	NATK7K3TZUH32BBE	CGDGXAW6GNU6JIEG	Fiftieth Art'S	2015-01-27	6095	1	Aaron Hendrickson	AEMLQ09IYM72ACBL
25900	EGD6IRB0UML62XB0	CGDGXAW6GNU6JIEG	Fiftieth Art'S	2018-11-04	7652	1	Aaron Hendrickson	AEMLQ09IYM72ACBL
25901	9Z18A7D1T8EUH58D	CGDGXAW6GNU6JIEG	Fiftieth Art'S	2016-05-08	4746	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
25902	R0LUW64V2F3O2HSD	CGDGXAW6GNU6JIEG	Fiftieth Art'S	2017-02-16	6158	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
25903	UMHMBM5M179IHX6D	CGDGXAW6GNU6JIEG	Fiftieth Art'S	2017-07-28	2164	0	Aaron Hendrickson	AEMLQ09IYM72ACBL
292 rows × 8 columns

计算每组中的行数

为了演示一些高级分组功能,将通过使用apply步骤的最简单版本:size方法(计算每个组中的行数)。这样做可以专注于groupby的应用。

输入:

grouped.size()

输出:

Sales Rep
Aaron Hendrickson    292
Adam Sawyer          324
Adele Kimmel         115
Adrian Daugherty     369
Adrianna Shelton      37
                    ... 
Willie Lin            44
Willie Rau            95
Willie Sanchez       309
Yvonne Jones          74
Yvonne Lindsey        67
Length: 499, dtype: int64

按’Sales Rep’中的姓分组

下面的例子是通过’Sales Rep’这个列的变体分组。原来的分组方法只能是通过创建辅助列的方法来分组,这个方法可以避免修改原数据,保证原数据不被污染。
通过使用str方法提取人名中的姓。
输入:

df.groupby(
    df['Sales Rep'].str.split(' ').str[0]
).size()

输出:

Sales Rep
Aaron        292
Adam         324
Adele        115
Adrian       369
Adrianna      37
            ... 
Wesley       144
Wilbert      213
William     1393
Willie       448
Yvonne       141
Length: 318, dtype: int64

按’Sales Rep’中是否包含有“William”分组

输入:

df.groupby(
    df['Sales Rep'].apply(lambda x: 'William' in x)
).size()

输出:

Sales Rep
False    97111
True      2889
dtype: int64

按随机序列分组

输入:

df.groupby(
    pd.Series(np.random.choice(list('ABCDG'),len(df)))
).size()

输出:

A    19852
B    19949
C    20184
D    19912
G    20103
dtype: int64

按’Val’列分位数分成三组

输入:

df.groupby(
    pd.qcut(x=df['Val'],q=3,labels=['low','mid','high'])
).size()

输出:

Val
low     33339
mid     33336
high    33325
dtype: int64

按制定的’Val’列的范围进行分组

输入:

df.groupby(
    pd.cut(df['Val'],[0,3000,5000,7000,10000])
).size()

输出:

Val
(0, 3000]        29220
(3000, 5000]     19892
(5000, 7000]     20359
(7000, 10000]    30529
dtype: int64

pd.Grouper

pd.Grouper是很重要的一个函数,在处理时间序列数据时非常有用。

Grouping by year

api使用样例:pd.Grouper(key=, freq=),通过该函数可以根据指定列的指定时间频率对数据进行分组。本例中对’Date’列按’Y’进行分组。

输入:

df.groupby(pd.Grouper(key='Date',freq='Y')).size()

输出:

Date
2014-12-31    19956
2015-12-31    20054
2016-12-31    20133
2017-12-31    20079
2018-12-31    19778
Freq: A-DEC, dtype: int64

按季度或其他频率分组

除了按’Y’分组,还可以按’D’,‘W’,‘M’,或者’Q’分组,具体如下表:

Pandas数据分析groupby函数深度总结(1)_第1张图片
输入:

df.groupby(pd.Grouper(key='Date',freq='SM')).size()

输出:

Date
2013-12-31    761
2014-01-15    837
2014-01-31    820
2014-02-15    740
2014-02-28    817
             ... 
2018-10-31    810
2018-11-15    805
2018-11-30    824
2018-12-15    837
2018-12-31     50
Freq: SM-15, Length: 121, dtype: int64

通过多列进行分组

输入:

df.groupby(['Sales Rep','Company Name']).size()

输出:

Sales Rep          Company Name               
Aaron Hendrickson  6-Foot Homosexuals             20
                   63D House'S                    27
                   Angular Liberalism             28
                   Boon Blish'S                   18
                   Business-Like Structures       21
                                                  ..
Yvonne Jones       Entry-Limiting Westinghouse    20
                   Intractable Fairgoers          18
                   Smarter Java                   17
Yvonne Lindsey     Meretricious Fabrication       28
                   Shrill Co-Op                   39
Length: 4619, dtype: int64

你可能感兴趣的:(数据科学库,python,pandas,数据科学)