Pandas

作者: Recalcitrant | 来源:发表于2019-10-01 13:53 被阅读0次

    Pandas

    目录
    一、Pandas基础
    二、Pandas三大数据结构
    1.Series
    2.DataFrame
    3.Index
    三、数据取值与选择
    四、数值运算
    五、缺失值处理
    六、层级索引
    七、合并数据集:Concat与Append操作
    八、合并数据集:合并与连接
    九、累计与分组
    十、数据透视表
    十一、向量化字符串操作
    十二、时间序列处理
    十三、高性能

    一、Pandas基础

    1.安装

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pandas
    

    2.库导入

    import numpy as np
    import pandas as pd
    

    二、Pandas三大数据结构

    1.Series

    (1)Series是通用的NumPy数组

    Series对象和NumPy数组的差异:NumPy数组通过隐式定义的整数索引获取数值,而Pandas的Series对象使用一种显式定义的索引与数值相关联。

    data = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
    

    (2)Series是特殊的字典

    population_dict = {'California': 38332521, 
                       'Texas': 26448193, 
                       'New York': 19651127, 
                       'Florida': 19552860, 
                       'Illinois': 12882135}
    population = pd.Series(population_dict)
    

    Series比字典强大,支持数组形式的操作:
    如:切片

    population['New York': 'Illinois']
    

    (3)创建Series对象

    pd.Series(data, [index])
    
    • 1.data可以是列表或NumPy数组
    pd.Series([2, 4, 6])
    
    • 2.data可以是一个标量
      创建Series对象时会将data重复填充到每个索引上
    pd.Series(5, index=[100, 200, 300])
    
    • 3.data可以是一个字典
    pd.Series({'a':1, 'b':2, 'c':3})
    

    2.DataFrame

    样例用例数据

    population_dict = {'California': 38332521, 
                       'Texas': 26448193, 
                       'New York': 19651127, 
                       'Florida': 19552860, 
                       'Illinois': 12882135}
    area_dict = {'California': 423967, 
                 'Texas': 695662, 
                 'New York': 141297, 
                 'Florida': 170312, 
                 'Illinois': 149995}
    population = pd.Series(population_dict)
    area = pd.Series(area_dict)
    states = pd.DataFrame({'population': population, 'area': area})
    

    (1)DataFrame是通用的NumPy数组

    (2)DataFrame是特殊的字典

    普通字典是一个键映射一个值,而DataFrame是一列映射一个Series对象。


    (3)创建DataFrame对象

    • 1.通过单个Series对象创建
    pd.DataFrame(Series对象, columns=['索引列名称'])
    

    示例:

    pd.DataFrame(population, columns=['population'])
    
    • 2.通过字典列表创建
    data = [{'a': i, 'b': 2 * i} for i in range(3)]
    pd.DataFrame(data)
    

    如果字典中有些键不存在,Pandas会用缺失值NaN来填充:

    pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])
    
    • 3.通过Series对象字典创建
    pd.DataFrame({'population': population, 'area': area})
    

    3.Index

    (1)Index是不可变数组

    • Index对象拥有与NumPy数组相似的属性


    • Index对象的不可变特征使得多个Series和DataFrame之间进行索引共享时更加安全


    (2)Index是有序集合

    三、数据取值与选择

    1.Series数据选择方法

    示例用例数据:

    data = pd.Series([0.25, 0.5, 0.75, 1.0], index=['a', 'b', 'c', 'd'])
    

    (1)将Series看作字典

    (2)将Series看作一维数组

    Series具有和NumPy数组一样的数组数据选择功能(索引、掩码、花哨索引等)

    # 将显式索引作为切片
    data['a': 'c']
    # 将隐式整数索引作为切片
    data[1:3]
    

    注意:显式索引切片结果包含最后一个索引,隐式索引切片结果不包含最后一个索引。
    # 掩码
    data[(data > 0.3) & (data < 0.8)]
    # 花哨索引
    data[['a', 'e']]
    

    (3)索引器(loc、iloc、ix)

    示例用例数据:

    data = pd.Series(['a', 'b', 'c'], index=[1, 3, 5])
    

    ①loc显式索引

    ②iloc隐式索引

    ③ix混合索引

    2.DataFrame数据选择方法

    示例用例数据:

    area_dict = {'California': 423967, 
                 'Texas': 695662, 
                 'New York': 141297, 
                 'Florida': 170312, 
                 'Illinois': 149995}
    population_dict = {'California': 38332521, 
                       'Texas': 26448193, 
                       'New York': 19651127, 
                       'Florida': 19552860, 
                       'Illinois': 12882135}
    area = pd.Series(area_dict)
    pop = pd.Series(population_dict)
    
    data = pd.DataFrame({'area': area, 'pop': pop})
    

    (1)将DataFrame看作字典

    (2)将DataFrame看作二维数组

    • 使用索引器取值


    • 任何用于处理NumPy形式数据的方法,都可以用于这些索引器,如:掩码、花哨索引
    • 任何一种取值方法都可以用于修改数据


      image.png

    (3)其他取值方法

    • 对单个标签取值选择列,对多个标签切片选择行
    • 切片也可以直接使用行数实现(隐式索引)


    • 掩码操作可以对每一行进行过滤


    四、数值运算

    常见Python运算符与Pandas方法映射关系

    Python运算符 Pandas方法
    + add()
    - sub()、subtract()
    * mul()、multiply()
    / truediv()、div()、divide()
    // floordiv()
    % mod()
    ** pow()

    1.通用函数:保留索引

    通用函数运算结果会保留索引

    • Series


    • DataFrame


    2.通用函数:索引对齐

    (1)Series索引对齐

    • 运算结果数组的索引是两个数组索引的并集。
    • 对于缺失位置的数据,Pandas会用NaN填充,表示“此处没有数据”。


    • 如果NaN值不是想要的结果,可以用通用函数的fill_value参数来指定。


    (2)DataFrame索引对齐

    • 在计算两个DataFrame时,索引对齐规则同样会出现在共同列(并集)中。


    • df.unstack()方法可以将二维数据拆为一维数据


    3.通用函数:DataFrame与Series的运算

    • 二维数组减去一行会按行计算,Pandas减去一行默认也是按行计算。
    • 通过通用函数的axis参数,可以指定计算的方式。


    • DataFrame和Series运算时,结果的索引也会自动对齐。


    五、缺失值处理

    Pandas采用标签值表示缺失值
    有两种方式:

    1.浮点数据类型NaN
    2.Python对象类型None

    1.None:Pyhton对象类型的缺失值(object对象类型)

    • 只能用于NumPy/Pandas数组类型中的'object'类型。


    • object类型的数据会消耗更多的资源。

      注意:无法对包含None的数组进行累计操作。

    2.NaN:数值类型的缺失值(浮点型)

    • NaN是一种按照IEEE浮点数标准设计、在任何系统中都兼容的特殊浮点数。


    • 任何数与NaN进行运算结果都是NaN。


      =

    3.Pandas中None与NaN的差异

    • Pandas将None与NaN看作是等价可交换的,在适当的时候会将两者进行替换。
    • Pandas会将没有标签值的数据类型自动转换为NaN。


    • Pandas会将含缺失值的整型数组转换为浮点类型,并且将None转换为NaN。



      如果是DataFrame,则会将含缺失值的列转换为浮点类型。

    4.处理缺失值

    Pandas对不同类型缺失值的转换规则

    类型 缺失值转换规则 NA标签值
    floating浮点型 无变化 np.nan
    object对象类型 无变化 None或np.nan
    integer整数类型 强制转换为float64 np.nan
    boolean布尔类型 强制转换为object None或np.nan

    注意:Pandas中字符串类型的数据通常使用object类型存储的。

    (1)发现缺失值

    isnull()方法和data.notnull()方法:创建一个布尔类型的掩码标签

    data = pd.Series([1, np.nan, 'hello', None])
    data.isnull()
    data.notnull()
    

    (2)剔除缺失值

    data.dropna()
    
    • 1.Series
      dropna()方法返回一个去除缺失值的数据。


    • 2.DataFrame
      默认情况下剔除包含缺失值的整行数据。



      可以指定删除含缺失值的整列数据。

    df.dropna(axis=1)
    df.dropna(axis='columns')
    
    • 3.还可以自定删除条件
      ①通过how参数定义删除规则
    df.dropna(axis=删除轴, how='删除规则')
    

    ②通过thresh参数设置判定是否删除的缺失值数量

    df.dropna(axis=删除轴, thresh=最小缺失值数量)
    

    (3)填充缺失值

    ①指定值填充

    data.fillna(填充值)
    

    ②前向填充

    用缺失值前面的有效值来从前往后填充(forward-fill)

    data.fillna(method='ffill')
    

    ③后向填充

    用缺失值后面的有效值来从后往前填充(back-fill)

    data.fillna(method='bfill')
    
    • DataFrame填充方法与Series类似,只是在填充式需要设置坐标轴参数axis。若不指定则默认按行填充(用上一行的有效值填充下一行的缺失值)。


    六、层级索引

    目录
    1.多级索引Series
    2.多级索引的创建方法
    3.多级索引的取值与切片
    4.多级索引行列转换
    5.多级索引的数据累计方法

    1.多级索引Series

    示例用例数据:

    index = [('California', 2000), ('California', 2010), ('New York', 2000), ('New York', 2010), ('Texas', 2000), ('Texas', 2010)]
    populations = [33871648, 37253956, 18976457, 19378102, 20851820, 25145561]
    pop = pd.Series(populations, index=index)
    

    (1)普通方法(使用普通索引)


    缺点:在查询数据时需使用循环迭代,不够简洁(在处理大量数据时效率也不高)。

    (2)Pandas多级索引

    index = [索引元组列表]
    index = pd.MultiIndex.from_tuples(index)
    data = data.reindex(index)
    

    通过多级索引可以方便地查询数据:


    (3)高维数据的多级索引

    • 1.unstack()方法可以将一个拥有多级索引的Series转换为普通索引的DataFrame。
    • 2.stack()方法可以将使用普通索引的DataFrame转换为拥有多级索引的Series。
    data_df = data.unstack()
    data = data_df.stack()
    
    • 增加一列


    2.多级索引的创建方法

    • 为Series或DataFrame创建多级索引最直接的办法就是讲index参数设置为至少二维的索引数组。


    (1)显式地创建多级索引


    显式多级索引创建完成以后,可以通过index参数指定,或者通过reindex()方法更新Series或DataFrame的索引。

    (2)多级索引的等级名称

    可以在构造MultiIndex时通过参数names,或在构造完成后通过MultiIndex对象的names属性来指定索引的等级名称。


    (3)多级列索引

    # 多级行列索引
    index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]], names=['year', 'visit'])
    columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']], names=['subject', 'type'])
    
    # 模拟数据
    data = np.round(np.random.randn(4, 6), 1)
    data[:, ::2] *= 10
    data += 37
    
    # 创建DataFrame
    health_data = pd.DataFrame(data, index=index, columns=columns)
    health_data
    

    3.多级索引的取值与切片

    (1)Series多级索引

    • 1.如果只取最高级索引,获取的结果是一个新的Series,未被选中的低层索引值会被保留。


    • 2.如果想要直接使用较低层级的索引取值,第一层级的索引可以用空切片。


    • 3.多级索引同样支持花哨索引、掩码等操作


    (2)DataFrame多级索引

    • 可以使用loc|iloc选择多行多列


    • 在元组中使用切片会引起错误,因此Pandas使用IndexSlice对象进行切片操作


    4.多级索引行列转换

    (1)有序索引和无序索引

    多级索引局部切片要求MultiIndex的各级索引是有序的。


    (2)索引stack与unstack

    (3)索引的设置与重置

    • 1.使用name参数为列设置名称(将多级索引变成多列数据)


    • 2.将多列数据设置为多级索引


    5.多级索引的数据累计方法

    七、合并数据集:Concat与Append操作

    1.知识回顾:NumPy数组合并

    2.pd.concat()方法

    示例用例方法:

    def make_df(cols, ind):
        data = {c:[str(c) + str(i) for i in ind] for c in cols}
        print(data)
        return pd.DataFrame(data, ind)
    
    • 1.Series


    • 2.DataFrame



    (1)索引重复

    • 合并时,pd.concat方法会保留重复的索引


    处理重复索引
    1.捕捉索引重复异常:设置vertify_integrity=True,合并时若出现重复索引则触发异常。
    2.忽略重复索引:设置ignore_index=True,合并时则将会创建一个新的整数索引。


    (2)类似join的合并

    示例用例数据:

    df5 = make_df('ABC', [1, 2])
    df6 = make_df('BCD', [3, 4])
    print(df5, '\n\n', df6)
    pd.concat([df5, df6], sort=False)
    


    (3)append()方法


    注意:append()方法合并会创建新对象,效率较低。

    八、合并数据集:合并与连接

    目录
    1.数据连接的类型
    2.设置数据合并的键
    3.设置数据连接的集合操作规则
    4.设置重复列名后缀名

    1.数据连接的类型

    pd.merge()实现三种类型的数据连接(一对一、一对多、多对多)

    (1)一对一连接

    • pd.merge()方法会发现两个DataFrame都有的列,并会自动以这列作为键进行连接,生成一个新的DataFrame。
    df1 = pd.DataFrame({'employee': ['Bob', 'Jake', 'Lisa', 'Sue'], 'group': ['Accounting', 'Engineering', 'Engineering', 'HR']})
    df2 = pd.DataFrame({'employee': ['Lisa', 'Bob', 'Jake', 'Sue'], 'hire_date': [2004, 2008, 2012, 2014]})
    df3 = pd.merge(df1, df2)
    

    (2)一对多连接

    一个group对应多个employee:


    (3)多对多连接

    一个group对应多个employee,一个group对应多个skills:



    2.设置数据合并的键

    (1)on参数

    • 通过pd.merge()方法的on参数指定关联时的键
    pd.merge(df1, df2, on='参照键')
    

    注意:on参数只能在两个DataFrame有相同的列名时使用。

    (2)left_on与right_on参数


    (3)left_index与right_index参数

    • 通过索引连接
    df1a = df1.set_index('employee')
    df2a = df2.set_index('employee')
    pd.merge(df1a, df2a, left_index=True, right_index=True)
    

    • join()方法也可以按照索引进行连接


    • 可以通过 left_index|right_on或者left_on|right_index参数组合,将列和索引混合使用


    3.设置数据连接的集合操作规则

    用例数据:

    df6 = pd.DataFrame({'name': ['Peter', 'Paul', 'Mary'], 'food': ['fish', 'beans', 'bread']}, columns=['name', 'food'])
    df7 = pd.DataFrame({'name': ['Mary', 'Joseph'], 'drink': ['wine', 'beer']}, columns=['name', 'drink'])
    
    • 默认情况下pd.merge()方法采用内连接


    • 通过merge()方法的how参数指定连接规则



    4.设置重复列名后缀名

    用例数据:

    df8 = pd.DataFrame({'name': ['Bob', 'Jake', 'Lisa', 'Sue'], 'rank': [1, 2, 3, 4]})
    df9 = pd.DataFrame({'name': ['Bob', 'Jake', 'Lisa', 'Sue'], 'rank': [3, 1, 2, 4]})
    
    • 通过suffixes参数指定重复列名后缀名


    九、累计与分组

    1.累计

    Series和DataFrame支持所有的NumPy累计操作

    Pandas常见累计方法

    指标 描述
    count() 计数项
    first()、last() 第一项、最后一项
    mean()、median() 均值、中位数
    min()、max() 最小值、最大值
    std()、var() 标准差、方差
    mad() 均值绝对偏差
    prod() 所有项乘积
    sum() 所有项求和

    示例:


    • Series和DataFrame支持所有的NumPy累计操作


    • 查看常见的统计值
    df.describe()
    

    2.分组:GroupBy

    (1)GroupBy过程:分割、应用、组合

    GroupBy操作可视化过程

    groupby():传入要分割的名称,返回一个DataFrameGroupBy对象,可以进行进一步操作。

    (2)GroupBy对象

    groupby对象主要有以下四种操作:

    aggregate、filter、transform、apply(累计、过滤、转换、应用)

    用例数据:

    import seaborn as sns
    planets = sns.load_dataset('planets')
    
    # 查看前五行数据
    planets.head()
    # 查看后五行数据
    planets.tail()
    # 查看数据描述信息
    planets.describe()
    

    ①按列取值

    ②按组迭代

    ③调用方法

    • 调用方法可以让任何不由GroupBy对象直接实现的方法直接应用的每一组


    (3)累计、过滤、转换、应用

    用例数据:

    rng = np.random.RandomState(0)
    df = pd.DataFrame({'key': ['A', 'B', 'C', 'A', 'B', 'C'], 'data1': range(6), 'data2': rng.randint(0, 10, 6)}, columns=['key', 'data1', 'data2'])
    

    ①累计:aggregate()方法

    • aggregate()方法支持复杂的累计操作,如:字符串、函数、函数列表等


    • aggregate()方法可以传入一个字典,为不同的列指定不同的累计方法


    ②过滤:filter()方法

    过滤操作:按照分组属性,丢弃若干数据(返回True保留数据,返回False过滤掉数据)。

    ③转换:transform()方法

    转换:累计操作是对组内全量数据进行缩减的结果,而转换操作会返回一个新的全量数据。

    ④应用:apply()方法

    apply()方法可以在每个组上应用任意方法, 输入一个DataFrame,返回一个Pandas对象(Series或DataFrame)或一个标量(scalar)。

    (4)设置分割的键

    ①将列表、数组、Series、索引作为分组键

    • 分组键可以是长度与DataFrame匹配的任意Series或列表


    ②用字典或Series将索引映射到分组名称

    df2 = df.set_index('key')
    mapping = {'A': 'vower', 'B': 'consonant', 'C': 'consonant'}
    df2.groupby(mapping).sum()
    

    注意:索引的值要与字典的键保持统一。

    ③任意Python函数

    • 可以将任意Python函数传入groupby,函数映射到索引


    • 将函数作为分组键时,会修改函数传入索引列的值,如果没有定义索引,就会传入隐式索引的值



    ④多个有效键构成的列表

    • 只要是有效的键就可以组合起来进行分组


    (5)分组案例

    十、数据透视表

    用例数据:

    import seaborn as sns
    titanic = sns.load_dataset('titanic')
    

    1.手工制作数据透视表

    2.数据透视表语法

    pivot_table()方法:数据透视表

    # 两条语句等效
    titanic.groupby(['sex', 'class'])['survived'].aggregate('mean').unstack()
    titanic.pivot_table('survived', index='sex', columns='class')
    

    (1)多级数据透视表

    • 数据透视表中的分组可以通过各种参数指定多个等级


    (2)其他数据透视表选项

    • 通过字典为不同列指定不同的累计函数
    titanic.pivot_table(index='sex', columns='class', aggfunc={'survived': sum, 'fare': 'mean'})
    
    • margins_name参数:用来指定总数行的名称


    十一、向量化字符串操作

    1.Pandas字符串操作

    Series和Index对象提供了str属性,可以方便地实现对字符串的操作,并且正确地处理缺失值。


    2.Pandas字符串方法列表

    (1)与Python字符串方法相似的方法

    几乎所有Python内置的字符串方法都被复制到Pandas的向量化字符串方法中。
    注意:这些方法的返回值可能与Python内置函数不同。
    示例:

    (2)正则表达式方法

    Pandas向量化字符串方法与Python标准库re模块函数对应关系

    方法 描述
    match() 对每个元素调用re.match(),返回布尔类型值
    extract() 对每个元素调用re.match(),返回匹配的字符串组(groups)
    findall() 对每个元素调用re.findall()
    replace() 用正则模式替换字符串
    contains() 对每个元素调用re.search(),返回布尔类型值
    count() 统计符合正则模式的字符串数量
    split() 等价于str.split(),支持正则表达式
    rsplit() 等价于str.rsplit(),支持正则表达式

    示例:



    (3)其他字符串方法

    方法 描述
    get() 获取元素索引位置上的值,索引从0开始
    slice() 对元素进行切片取值
    slice_replace() 对元素进行切片替换
    cat() 连接字符串(此方法功能复杂,建议阅读文档)
    repeat() 重复元素
    normalize() 将字符串转换为Unicode规范格式
    pad() 在字符串的左边、右边或两边增加空格
    wrap() 将字符串按照指定的宽度换行
    join() 用分隔符连接Series的每个元素
    get_dummies() 按照分隔符提取每个元素的dummy变量,转换为独热(one-hot)编码的DataFrame

    ①向量化字符串取值与切片操作

    • 切片操作


    • 取值操作


    ②指标变量

    # A=出生在美国
    # B=出生在英国
    # C=喜欢奶酪
    # D=喜欢午餐肉
    full_monte = pd.DataFrame({'name': monte, 'info': ['B|C|D', 'B|D', 'A|C', 'B|D', 'B|C', 'B|C|D']})
    
    • 独热编码
    # 快速将指标变量转换为独热编码
    full_monte['info'].str.get_dummies('|')
    

    十二、时间序列处理

    基本概念

    • 时间戳:表示某个具体的时间点
    • 时间间隔与周期:表示开始时间点与结束时间点之间的时间长度
    • 时间增量(持续时间):表示精确的时间长度

    1.Python日期与时间工具

    (1)原生Python日期时间工具

    from datetime import datetime
    from dateutil import parser
    

    (2)时间类型数组:NumPy datetime64类型

    日期与时间单位格式代码

    代码 含义
    Y
    M
    W
    D
    h
    m
    s
    ms 毫秒
    us 微秒
    ns 纳秒
    ps 皮秒
    fs 飞秒
    as 原秒

    (3)Pandas日期时间工具

    • Pandas所有关于日期时间的处理方法全部都是通过TimeStamp对象实现的。


    • 可以直接进行NumPy类型的向量化运算。


    2.Pandas时间序列:用时间作索引

    (1)Pandas时间序列数据结构

    时间戳:Timestamp类型
    周期型:Period类型
    时间增量(持续时间):Timedelta类型

    • 能够解析多种多种日期时间格式


    • 当用一个日期减去另一个日期时,返回的结果是TimedeltaIndex类型



    (2)时间频率与偏移量

    Pandas频率代码

    代码 描述
    D
    W
    M 月末
    Q 季末
    A 年末
    H 小时
    T 分钟
    S
    L 毫秒
    U 微秒
    N 纳秒
    B 天(仅含工作日)
    BM 月末(仅含工作日)
    BQ 季末(仅含工作日)
    BA 年末(仅含工作日)
    BH 小时(工作时间)
    MS 月初
    BMS 月初(仅含工作日)
    B- 仅含工作日
    -S
    • 所有代码都对应有一个偏移量,可以在pandas.tseries.offsets里找到
    from pandas.tseries.offsets import BDay
    

    (3)重新取样和频率转换

    数据读取:

    • 1.安装pandas-datareader
    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pandas-datareader
    
    • 2.读取数据
    from pandas_datareader import data
    tencent = data.get_data_yahoo('0700.hk', start='2000-11-01', end='2019-08-20')
    
    • 3.读取收盘价
    tencent = tencent['Close']
    
    • 4.画图
    %matplotlib inline
    import matplotlib.pyplot as plt
    tencent.plot()
    

    ①重新取样和频率转换

    重新取样

    resample():数据累计
    asfreq():数据选择

    tencent.plot(alpha=0.5, style='-')
    # resample()方法是数据累计采样,结果为上一年的均值
    tencent.resample('BA').mean().plot(style=':')
    # asfreq()方法是数据选择采样,结果为上一年最后一个工作日的收盘价
    tencent.asfreq('BA').plot(style='k:')
    
    plt.legend(['input', 'resample', 'asfreq'], loc='upper left')
    
    fig, ax = plt.subplots(2, sharex=True)
    data = tencent.iloc[: 10]
    
    data.asfreq('D').plot(ax=ax[0], marker='o')
    
    data.asfreq('D', method='bfill').plot(ax=ax[1], style=['-o'])
    data.asfreq('D', method='ffill').plot(ax=ax[1], style=['--o'])
    ax[1].legend(['back-fill', 'forward-fill'])
    

    ②时间迁移

    时间迁移

    shift():迁移数据
    tshift():迁移索引

    fig, ax = plt.subplots(3, sharey=True)
    fig.subplots_adjust(hspace=0.36)
    
    # 重新按天采样,向后填充缺失值
    tencent = tencent.asfreq('D', method='pad')
    
    tencent.plot(ax=ax[0])
    # 迁移数据
    tencent.shift(900).plot(ax=ax[1])
    # 迁移索引
    tencent.tshift(900).plot(ax=ax[2])
    
    # 设置图例与标签
    local_max = pd.to_datetime('2007-11-05')
    offset = pd.Timedelta(900, 'D')
    
    ax[0].legend(['input'], loc=2)
    ax[0].get_xticklabels()[4].set(weight='heavy', color='red')
    ax[0].axvline(local_max, alpha=0.3, color='red')
    
    ax[1].legend(['input'], loc=2)
    ax[1].get_xticklabels()[4].set(weight='heavy', color='red')
    ax[1].axvline(local_max + offset, alpha=0.3, color='red')
    
    ax[2].legend(['input'], loc=2)
    ax[2].get_xticklabels()[1].set(weight='heavy', color='red')
    ax[2].axvline(local_max + offset, alpha=0.3, color='red')
    

    ③移动时间窗口

    • Series和DataFrame有一个rolling属性,可以实现计算移动统计值。
    rolling = tencent.rolling(365, center=True)
    data = pd.DataFrame({'input': tencent, 'one-year rolling_mean': rolling.mean(), 'one-year rolling_std': rolling.std()})
    ax = data.plot(style=['-', '--', ':'])
    ax.lines[0].set_alpha(0.3)
    

    十三、高性能Pandas:eval()与query()

    1.pandas.eval()实现高性能运算

    • pandas.eval()方法用字符串代数式实现了DataFrame的高性能运算。
    • pandas.eval()在执行时不需要为临时数组分配全部内存。

    2.pandas.eval()支持的运算

    (1)算术运算符

    pd.eval()支持所有的算术运算符

    result1 = -df1 * df2 / (df3 + df4) - df1
    result2 = pd.eval("-df1 * df2 / (df3 + df4) - df1")
    np.allclose(result1, result2)
    

    (2)比较运算符

    pd.eval()支持所有的比较运算符,包括链式代数式

    result1 = (df1 < df2) & (df2 <= df3) & (df3 != df4)
    result2 = pd.eval('df1 < df2 <= df3 != df4')
    np.allclose(result1, result2)
    

    (3)位运算符

    pd.eval()支持&(与)、|(或)等运算符

    result1 = (df1 < 0.5) & (df2 <= 0.5) & (df3 < df4)
    result2 = pd.eval('(df1 < 0.5) & (df2 <= 0.5) & (df3 < df4)')
    np.allclose(result1, result2)
    

    (4)对象属性与索引

    result1 = df2.T[0] + df3.iloc[1]
    result2 = pd.eval('df2.T[0] + df3.iloc[1]')
    np.allclose(result1, result2)
    

    注意:目前pd.eval()尚不支持函数调用、条件语句、循环及更复杂的运算。如果需要进行这些运算,可以借助Numexpr来实现。

    3.DataFrame.eval()实现列间运算

    df = pd.DataFrame(np.random.rand(1000, 3), columns=['A', 'B', 'C'])
    result1 = (df['A'] + df['B']) / (df['C'] - 1)
    result2 = pd.eval("(df.A + df.B) / (df.C - 1)")
    # 更简洁的方式
    result3 = df.eval("(A + B) / (C - 1)")
    np.allclose(result1, result2), np.allclose(result1, result3)
    
    • 1.新增列


    • 2.修改列


    • 3.DataFrame.eval()使用局部变量


    4.DataFrame.query()方法

    Cmean = df['C'].mean()
    result1 = df[(df.A < Cmean) & (df.B < Cmean)]
    result2 = df.query("A < @Cmean and B < @Cmean")
    np.allclose(result1, result2)
    

    相关文章

      网友评论

        本文标题:Pandas

        本文链接:https://www.haomeiwen.com/subject/mudgtctx.html