【Pandas】学习与记录(2)isin&apply&groupby&agg

目录

Pandas基础命令速查表

pandas的isin索引和~反向索引

pandas apply() 函数用法

python处理数据的风骚操作[pandas 之 groupby&agg]

agg


pandas的isin索引和~反向索引

 有的时候会经常遇到条件过滤的场景,这个时候可能经常使用isin或者是~来进行一步操作,而不是写条件语句的方式,这样来提高效率和简洁度。

1、直接根据条件进行索引,isin()接受一个列表,判断该列中元素是否在列表中

import numpy as np
import pandas as pd
df=pd.DataFrame(np.random.randn(4,4),columns=['A','B','C','D'])
df
Out[189]: 
          A         B         C         D
0  0.289595  0.202207 -0.850390  0.197016
1  0.403254 -1.287074  0.916361  0.055136
2 -0.359261 -1.266615 -0.733625 -0.790208
3  0.164862 -0.649637  0.716620  1.447703
df['E'] = ['aa', 'bb', 'cc', 'cc']
df
Out[191]: 
          A         B         C         D   E
0  0.289595  0.202207 -0.850390  0.197016  aa
1  0.403254 -1.287074  0.916361  0.055136  bb
2 -0.359261 -1.266615 -0.733625 -0.790208  cc
3  0.164862 -0.649637  0.716620  1.447703  cc
df.E.isin(['aa','cc'])
Out[192]: 
0     True
1    False
2     True
3     True
Name: E, dtype: bool
df[df.E.isin(['aa','cc'])]
Out[193]: 
          A         B         C         D   E
0  0.289595  0.202207 -0.850390  0.197016  aa
2 -0.359261 -1.266615 -0.733625 -0.790208  cc
3  0.164862 -0.649637  0.716620  1.447703  cc

 2、根据多条件进行索引,此时用&(交集)或者|(并集)进行连接

df[df.E.isin(['aa'])|df.E.isin(['cc'])]
Out[194]: 
          A         B         C         D   E
0  0.289595  0.202207 -0.850390  0.197016  aa
2 -0.359261 -1.266615 -0.733625 -0.790208  cc
3  0.164862 -0.649637  0.716620  1.447703  cc
df[df.E.isin(['aa'])]
Out[195]: 
          A         B        C         D   E
0  0.289595  0.202207 -0.85039  0.197016  aa

3、通过字典的形式传递多个条件{‘某列’:[条件],‘某列’:[条件],} 

df['D'] = [1,2,3,4]
df[df.isin({'D':[0,3],'E':['aa','cc']})]
Out[200]: 
    A   B   C    D    E
0 NaN NaN NaN  NaN   aa
1 NaN NaN NaN  NaN  NaN
2 NaN NaN NaN  3.0   cc
3 NaN NaN NaN  NaN   cc

4、~相当于isnotin

df[~(df.E=='cc')]
Out[202]: 
          A         B         C  D   E
0  0.289595  0.202207 -0.850390  1  aa
1  0.403254 -1.287074  0.916361  2  bb

pandas apply() 函数用法

python处理数据的风骚操作[pandas 之 groupby&agg]

import pandas as pd

df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/sample-salesv3.xlsx?raw=True")
df["date"] = pd.to_datetime(df['date'])
df.head()

 数据如下:

统计'ext price'这个属性在每个月的累和(sum)值,resample 只有在index为date类型的时候才能用:

resample
重新采样,是对原样本重新处理的一个方法,是一个对常规时间序列数据重新采样和频率转换的便捷的方法。

set_index( ) 将DataFrame 中的列转化为行索引


df.set_index('date').resample('M')['ext price'].sum()


"""
date
2014-01-31    185361.66
2014-02-28    146211.62
2014-03-31    203921.38
2014-04-30    174574.11
2014-05-31    165418.55
2014-06-30    174089.33
2014-07-31    191662.11
2014-08-31    153778.59
2014-09-30    168443.17
2014-10-31    171495.32
2014-11-30    119961.22
2014-12-31    163867.26
Freq: M, Name: ext price, dtype: float64
"""

 进一步的,我们想知道每个用户每个月的sum值,那么就需要一个groupby了:

df.set_index('date').groupby('name')['ext price'].resample("M").sum()
"""
name                             date      
Barton LLC                       2014-01-31     6177.57
                                 2014-02-28    12218.03
                                 2014-03-31     3513.53
                                 2014-04-30    11474.20
                                 2014-05-31    10220.17
                                 2014-06-30    10463.73
                                 2014-07-31     6750.48
                                 2014-08-31    17541.46
                                 2014-09-30    14053.61
                                 2014-10-31     9351.68
                                 2014-11-30     4901.14
                                 2014-12-31     2772.90
Cronin, Oberbrunner and Spencer  2014-01-31     1141.75
                                 2014-02-28    13976.26
                                 2014-03-31    11691.62
                                 2014-04-30     3685.44
                                 2014-05-31     6760.11
                                 2014-06-30     5379.67
                                 2014-07-31     6020.30
                                 2014-08-31     5399.58
                                 2014-09-30    12693.74
                                 2014-10-31     9324.37
                                 2014-11-30     6021.11
                                 2014-12-31     7640.60
Frami, Hills and Schmidt         2014-01-31     5112.34
                                 2014-02-28     4124.53
                                 2014-03-31    10397.44
                                 2014-04-30     5036.18
                                 2014-05-31     4097.87
                                 2014-06-30    13192.19
                                                 ...   
Trantow-Barrows                  2014-07-31    11987.34
                                 2014-08-31    17251.65
                                 2014-09-30     6992.48
                                 2014-10-31    10064.27
                                 2014-11-30     6550.10
                                 2014-12-31    10124.23
White-Trantow                    2014-01-31    13703.77
                                 2014-02-28    11783.98
                                 2014-03-31     8583.05
                                 2014-04-30    19009.20
                                 2014-05-31     5877.29
                                 2014-06-30    14791.32
                                 2014-07-31    10242.62
                                 2014-08-31    12287.21
                                 2014-09-30     5315.16
                                 2014-10-31    19896.85
                                 2014-11-30     9544.61
                                 2014-12-31     4806.93
Will LLC                         2014-01-31    20953.87
                                 2014-02-28    13613.06
                                 2014-03-31     9838.93
                                 2014-04-30     6094.94
                                 2014-05-31    11856.95
                                 2014-06-30     2419.52
                                 2014-07-31    11017.54
                                 2014-08-31     1439.82
                                 2014-09-30     4345.99
                                 2014-10-31     7085.33
                                 2014-11-30     3210.44
                                 2014-12-31    12561.21
Name: ext price, Length: 240, dtype: float64

"""

结果肯定是对的,但是不够完美。我们可以使用Grouper写得更加简洁:

# df.set_index('date').groupby('name')['ext price'].resample("M").sum()
df.groupby(['name', pd.Grouper(key='date', freq='M')])['ext price'].sum()

结果和上面?一样,就不列出来了。
显然,这种写法多敲了很多次键盘,那么它的好处是啥呢?
首先,逻辑上更加直接,当你敲代码完成以上统计的时候,你首先想到的就是groupby操作,而set_index, resample好像不会立马想到。想到了groupby这个'动作'之后,你就会紧接着想按照哪个key来操作,此时,你只需要用字符串,或者Grouper把key定义好就行了。最后使用聚合函数,就得到了结果。所以,从人类的思考角度看,后者更容易记忆。

另外,Grouper里的freq可以方便的改成其他周期参数(resample也可以),比如:

# 按照年度,且截止到12月最后一天统计ext price的sum值
df.groupby(['name', pd.Grouper(key='date', freq='A-DEC')])['ext price'].sum()
"""
name                             date      
Barton LLC                       2014-12-31    109438.50
Cronin, Oberbrunner and Spencer  2014-12-31     89734.55
Frami, Hills and Schmidt         2014-12-31    103569.59
Fritsch, Russel and Anderson     2014-12-31    112214.71
Halvorson, Crona and Champlin    2014-12-31     70004.36
Herman LLC                       2014-12-31     82865.00
Jerde-Hilpert                    2014-12-31    112591.43
Kassulke, Ondricka and Metz      2014-12-31     86451.07
Keeling LLC                      2014-12-31    100934.30
Kiehn-Spinka                     2014-12-31     99608.77
Koepp Ltd                        2014-12-31    103660.54
Kuhn-Gusikowski                  2014-12-31     91094.28
Kulas Inc                        2014-12-31    137351.96
Pollich LLC                      2014-12-31     87347.18
Purdy-Kunde                      2014-12-31     77898.21
Sanford and Sons                 2014-12-31     98822.98
Stokes LLC                       2014-12-31     91535.92
Trantow-Barrows                  2014-12-31    123381.38
White-Trantow                    2014-12-31    135841.99
Will LLC                          2014-12-31    104437.60
Name: ext price, dtype: float64

"""

agg

从0.20.1开始,pandas引入了agg函数,它提供基于列的聚合操作。而groupby可以看做是基于行,或者说index的聚合操作

从实现上看,groupby返回的是一个DataFrameGroupBy结构,这个结构必须调用聚合函数(如sum)之后,才会得到结构为Series的数据结果。
而agg是DataFrame的直接方法,返回的也是一个DataFrame。当然,很多功能用sum、mean等等也可以实现。但是agg更加简洁, 而且传给它的函数可以是字符串,也可以自定义,参数是column对应的子DataFrame

举个栗子?吧:

df[["ext price", "quantity", "unit price"]].agg(['sum', 'mean'])

 怎么样,是不是比使用

df[["ext price", "quantity"]].sum()
df['unit price'].mean()

简洁多了?

上例中,你还可以针对不同的列使用不同的聚合函数:

df.agg({'ext price': ['sum', 'mean'], 'quantity': ['sum', 'mean'], 'unit price': ['mean']})

另外,自定义函数怎么用呢,也是so easy.
比如,我想统计sku中,购买次数最多的产品编号,可以这样做:

# 这里的x是sku对应的column
get_max = lambda x: x.value_counts(dropna=False).index[0]
df.agg({'ext price': ['sum', 'mean'], 
        'quantity': ['sum', 'mean'], 
        'unit price': ['mean'], 
        'sku': [get_max]})

<lambda>看起来很不协调,把它去掉: 

get_max = lambda x: x.value_counts(dropna=False).index[0]
# python就是灵活啊。
get_max.__name__ = "most frequent"
df.agg({'ext price': ['sum', 'mean'], 
        'quantity': ['sum', 'mean'], 
        'unit price': ['mean'], 
        'sku': [get_max]})

另外,还有一个小问题,那就是如果你希望输出的列按照某个顺序排列,可以使用collections的OrderedDict:

get_max = lambda x: x.value_counts(dropna=False).index[0]
get_max.__name__ = "most frequent"
import collections

agg_dict = {
        'ext price': ['sum', 'mean'], 
        'quantity': ['sum', 'mean'], 
        'unit price': ['mean'], 
        'sku': [get_max]}
# 按照列名的长度排序。 OrderedDict的顺序是跟插入顺序一致的
df.agg(collections.OrderedDict(sorted(agg_dict.items(), key = lambda x: len(x[0]))))


参考:

Python-pandas--set_index与reset_index

python中resample函数实现重采样和降采样

使用到的数据:DATA | TRAIN 练习题数据集

练习的代码:10套练习,教你如何用Pandas做数据分析【1-5】 

10套练习,教你如何用Pandas做数据分析【6-10】 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值