pandas

头像
YjxGVG
    阅读 44 分钟

    2. pandas

    2.1 数据构造与加载

    2.1.1 构造dataframe

    • 空dataframe
        通过columns,index参数指定dataframe的行索引、列名。
    df1 = pd.DataFrame(columns=['c1', 'c2'], index=[1, 2])
    # output:
        c1    c2
    1    NaN    NaN
    2    NaN    NaN
    • 字典构造dataframe
        通过字典构造dataframe,并给dataframe添加列;可以通过index=[]参数设置df的索引。
    dict_v = {'c1': ['a', 'b', 'c'],
                  'c2': [1, 2, 3]}
    df1 = pd.DataFrame(dict_v)
    # output:
    c1    c2
    0    a    1
    1    b    2
    2    c    3

    2.1.1 describe()

      dataframe的整体信息,如数据行数,均值,标准差,分位数,最大最小值等。

    • 参数

      参数名含义可取值默认值
      percentiles输出结果中将要统计的分位数list,0到1之间,比如percentiles=[0,0.2,0.4,0.5,0.6,0.8][.25, .5, .75]
      include白名单,控制输出结果中的数据类型(即输出的类型)‘all’,np.number,np.object,'category'None
      exclude黑名单,控制输出结果中的数据类型(即不输出的类型)‘all’,np.number,np.object,'category'None
    • 输出

      结果名称含义
      count数据行数
      unique数据种类数(只有列数据为字符串格式时输出)
      top出现次数最多的一类数据(只有列数据为字符串格式时输出)
      freq出现次数最多的一类数据的出现次数(只有列数据为字符串格式时输出)
    # df_bak2
    asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0
    1    Govtbond    2    10    0.0355    2018-06-30    30.0
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    4    Finbond    5    10    0.0365    2018-06-30    21.0
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0
    
    df_bak2.describe(include='all')
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount
    count    10    10.00000    10.000000    10.00000    10    10.000000
    unique    4    NaN    NaN    NaN    4    NaN
    top    CorpbondAAA    NaN    NaN    NaN    2020-06-30    NaN
    freq    3    NaN    NaN    NaN    4    NaN
    mean    NaN    5.50000    6.900000    0.04035    NaN    23.700000
    std    NaN    3.02765    4.201851    0.00686    NaN    11.916841
    min    NaN    1.00000    1.000000    0.03150    NaN    8.000000
    25%    NaN    3.25000    5.000000    0.03575    NaN    18.250000
    50%    NaN    5.50000    5.000000    0.03900    NaN    20.000000
    75%    NaN    7.75000    10.000000    0.04625    NaN    30.000000
    max    NaN    10.00000    15.000000    0.05100    NaN    50.000000
    
    df_bak2.describe(include=[np.number])
    # output:
    asset_id    bond_period    rate    amount
    count    10.00000    10.000000    10.00000    10.000000
    mean    5.50000    6.900000    0.04035    23.700000
    std    3.02765    4.201851    0.00686    11.916841
    min    1.00000    1.000000    0.03150    8.000000
    25%    3.25000    5.000000    0.03575    18.250000
    50%    5.50000    5.000000    0.03900    20.000000
    75%    7.75000    10.000000    0.04625    30.000000
    max    10.00000    15.000000    0.05100    50.000000
    
    df_bak2.describe(include=[object])
    # output:
        asset_name    buying_time
    count    10    10
    unique    4    4
    top    CorpbondAAA    2020-06-30
    freq    3    4

    2.2 操作文件

    2.2.1 to_excel()

      保存dataframe到excel文件,可以通过参数'sheet_name'指定sheet。

    2.2.2 to_csv()

      保存dataframe到csv文件,

    2.2.3 read_csv()

      读csv文件中的数据为dataframe。header=None:表示csv文件中不包含列名,names=[]:设置df的列名。

    df = pd.read_csv(filepath_or_buffer=file_name, header=None, names=['c1', 'c2', 'c3', 'c4'])

    2.3 数据检测与过滤

      数据的检测与过滤包括缺失值、异常值检测与过滤。
    示例df:

    data_dict = {'asset_name': ['Govtbond','Govtbond','Govtbond','Finbond','Finbond','CorpbondAAA','CorpbondAAA','CorpbondAAA','CorpbondAA','CorpbondAA'],
    'asset_id': [1,2,3,4,5,6,7,8,9,10],
    'bond_period': [5,10,15,5,10,3,5,10,1,5],
    'rate':[0.0315,0.0355,0.041,0.033,0.0365,0.038, 0.04, 0.049,0.048, 0.051]}
    df_base=pd.DataFrame(data_dict)
    time_amount = pd.DataFrame(data={'asset_name': ['Govtbond','Govtbond','Govtbond','Finbond','Finbond','CorpbondAAA','CorpbondAAA', 'CorpbondAAA','CorpbondAA','CorpbondAA'],
    'asset_id': [1,2,3,4,5,6,7,8,9,10],
    'buying_time':['2019-12-31', '2018-06-30', '2015-09-30','2019-12-31', '2018-06-30', np.nan,'2020-06-30','2020-06-30',np.nan, np.nan],
    'amount': [30, np.nan, 50, 18, 21, 30, 8, 19, np.nan,12]})
    print(f"df_base=\n {df_base},\n time_amount=\n {time_amount}")
    df = df_base.merge(time_amount, how='left', on=['asset_name', 'asset_id'])

    2.3.1 dropna()

      根据指定的条件选择性的删除dataframe中含NaN的行或列。

    DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
    • 参数

      参数名含义可取值默认值
      axis决定删除NaN值时的轴,0:按行删除,1:按列删除0 or ‘index’, 1 or ‘columns’0
      how控制删除方式,any:行(或列)有NaN值则删除该行(或列),all:行(或列)的全部值为NaN时删除该行(或列)‘any’, ‘all’‘any’
      thresh这一行除去NaN值,剩余数值的数量大于等于n,便显示这一行整数可选参数
      subset从指定的列中寻找NaN值,然后删除行(只能用于删除行数据)列名可选参数
      inplace是否覆盖原dataframe,True:覆盖,不返回新的df,False:不覆盖,返回新的dfboolFalse
    原df:
        asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0
    1    Govtbond    2    10    0.0355    2018-06-30    NaN
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    4    Finbond    5    10    0.0365    2018-06-30    21.0
    5    CorpbondAAA    6    3    0.0380    NaN    30.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    8    CorpbondAA    9    1    0.0480    NaN    NaN
    9    CorpbondAA    10    5    0.0510    NaN    12.0
    # thresh参数
    df_bak=df.copy()
    df_bak.dropna(thresh=5) # 除去NaN值,剩余数值的数量大于等于5时显示该行
    # output:
    # 索引为8的行被删除
    asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0
    1    Govtbond    2    10    0.0355    2018-06-30    NaN
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    4    Finbond    5    10    0.0365    2018-06-30    21.0
    5    CorpbondAAA    6    3    0.0380    NaN    30.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    9    CorpbondAA    10    5    0.0510    NaN    12.0
    # subset参数
    df_bak=df.copy()
    df_bak.dropna(axis=0, subset=['amount']) # 根据'amount'列是否有空值来判断是否删除删除行数据
    # output:
    # amount列为NaN的行被删除
    asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    4    Finbond    5    10    0.0365    2018-06-30    21.0
    5    CorpbondAAA    6    3    0.0380    NaN    30.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    9    CorpbondAA    10    5    0.0510    NaN    12.0

    2.3.2 notnull()

      对dataframe中的对个元素判断其是否为nan并返回bool值True或False。

    2.4 填充缺失数据

    2.4.1 fillna()

      根据条件对dataframe的空值填充指定的值。

    DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
    • 参数

      参数名含义可取值默认值
      value将填充的值,如果不是标量,则会根据键或行列来填充scalar, dict, Series, or DataFrame无默认值
      method控制填充方式,pad/ffill:由前一个值填充其后的NaN值,backfill/bfill:用NaN值后面的值向前填充‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, NoneNone
      axis决定填充值时的轴,0:按行填充,1:按列填充0 or ‘index’, 1 or ‘columns’0
      limit如果指定了方法,这是向前/向后填充的连续NaN值的最大数目。换句话说,如果有超过这个数目的连续nan,它将只被部分填充。如果未指定方法,则这是将填充nan的整个轴上的最大条目数。intNone
      downcast用其他df填充NaN的控制,根据列名和行索引,将downcast中的值填入对应含NaN值的位置DF可选参数
      inplace是否覆盖原dataframe,True:覆盖,不返回新的df,False:不覆盖,返回新的dfboolFalse
    # axis参数
    df_bak=df.copy()
    df_bak.fillna(method='ffill',axis=1) # 按行 由前向后 填充,
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30
    1    Govtbond    2    10    0.0355    2018-06-30    2018-06-30
    2    Govtbond    3    15    0.041    2015-09-30    50
    3    Finbond    4    5    0.033    2019-12-31    18
    4    Finbond    5    10    0.0365    2018-06-30    21
    5    CorpbondAAA    6    3    0.038    0.038    30
    6    CorpbondAAA    7    5    0.04    2020-06-30    8
    7    CorpbondAAA    8    10    0.049    2020-06-30    19
    8    CorpbondAA    9    1    0.048    0.048    0.048
    9    CorpbondAA    10    5    0.051    0.051    12
    # limit参数
    df_bak=df.copy()
    df_bak.fillna(method='ffill',axis=1, limit=1) # 按行由前向后填充,且行连续的NaN值超过limit时,只填充前limit个NaN值
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30
    1    Govtbond    2    10    0.0355    2018-06-30    2018-06-30
    2    Govtbond    3    15    0.041    2015-09-30    50
    3    Finbond    4    5    0.033    2019-12-31    18
    4    Finbond    5    10    0.0365    2018-06-30    21
    5    CorpbondAAA    6    3    0.038    0.038    30
    6    CorpbondAAA    7    5    0.04    2020-06-30    8
    7    CorpbondAAA    8    10    0.049    2020-06-30    19
    8    CorpbondAA    9    1    0.048    0.048    NaN
    9    CorpbondAA    10    5    0.051    0.051    12

    2.4.2 dataframe缺数据时怎么补齐?

    dataframe有空行,但是数据缺失的日期并不在dataframe中,也不知道完整日期的dataframe

    2.5 数据去重

    asset_df = pd.DataFrame(data={'asset_name':['Govtbond','Govtbond','Govtbond','Finbond','Finbond','Finbond','CorpbondAAA','CorpbondAAA','CorpbondAAA','CorpbondAAA','CorpbondAA','CorpbondAA'],'asset_id': [1,2,3,4,5,5,6,7,8,8,9,10]})
    asset_df
    # output:
    asset_name    asset_id
    0    Govtbond    1
    1    Govtbond    2
    2    Govtbond    3
    3    Finbond    4
    4    Finbond    5
    5    Finbond    5
    6    CorpbondAAA    6
    7    CorpbondAAA    7
    8    CorpbondAAA    8
    9    CorpbondAAA    8
    10    CorpbondAA    9
    11    CorpbondAA    10

    2.5.1 duplicated()

      DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行(前面出现过的行)。

    • 参数

      参数名含义可取值默认值
      subset从指定的列中寻找重复值,然后bool值列名可选参数
      keep决定重复值的标记方式,‘first’:将重复值的第一个标记为True,其余标记为False; ‘last’:将重复值的最后一个标记为True,其余标记为False;False:将所有重复值标记为False}‘first’, ‘last’, False‘first’
    # keep参数
    asset_df.duplicated(keep=False) # 将重复值的所有行都标记为True
    # output:
    0     False
    1     False
    2     False
    3     False
    4      True
    5      True
    6     False
    7     False
    8      True
    9      True
    10    False
    11    False
    dtype: bool

    2.5.2 drop_duplicates()

      根据条件删除重复值(默认对比所有列的值,默认保留重复值的第一行),参数ignore_index为pandas1.0.0以上版本新加参数

    • 参数

      参数名含义可取值默认值
      subset从指定的列中寻找重复值,然后bool值列名可选参数,不输入该参数时表示所有列
      keep决定重复值的标记方式,‘first’:将重复值的第一个标记为True,其余标记为False; ‘last’:将重复值的最后一个标记为True,其余标记为False;False:将所有重复值标记为False}‘first’, ‘last’, False‘first’
      inplace是否覆盖原dataframe,True:覆盖,不返回新的df,False:不覆盖,返回新的df列名False
      ignore_index是否忽略旧索引boolFalse
    asset_df.drop_duplicates()
    # output:
    asset_name    asset_id
    0    Govtbond    1
    1    Govtbond    2
    2    Govtbond    3
    3    Finbond    4
    4    Finbond    5
    6    CorpbondAAA    6
    7    CorpbondAAA    7
    8    CorpbondAAA    8
    10    CorpbondAA    9
    11    CorpbondAA    10

    2.6 数据修改

    2.6.1 upper()&lower()

      将dataframe或series的列数据或索引的字符串转换为大写(upper())或小写(lower())。

    asset_df['asset_name'] = asset_df['asset_name'].str.upper() # 将asset_name列的值全部转换为大写
    asset_df
    # output:
    asset_name    asset_id
    0    GOVTBOND    1
    1    GOVTBOND    2
    2    GOVTBOND    3
    3    FINBOND    4
    4    FINBOND    5
    5    FINBOND    5
    6    CORPBONDAAA    6
    7    CORPBONDAAA    7
    8    CORPBONDAAA    8
    9    CORPBONDAAA    8
    10    CORPBONDAA    9
    11    CORPBONDAA    10

    2.6.2 Series.map()

      Series的map方法可以接受一个函数或含有映射关系的字典型对象,可以用于修改dataframe对象的数据子集,将指定列的值转换为其他值。

    map_dict = {
      'Govtbond':'bond1',
      'Finbond':'bond2',
      'CorpbondAAA':'bond3',
      'CorpbondAA':'bond4'
    }
    asset_df['asset_name'] = asset_df['asset_name'].map(map_dict)
    asset_df
    # output:
        asset_name    asset_id
    0    bond1    1
    1    bond1    2
    2    bond1    3
    3    bond2    4
    4    bond2    5
    5    bond2    5
    6    bond3    6
    7    bond3    7
    8    bond3    8
    9    bond3    8
    10    bond4    9
    11    bond4    10

    2.6.3 map()与lambda结合

      将map()函数与匿名函数lambda结合使用,可以一步实现数据的转换。

    asset_df['asset_name'] = asset_df['asset_name'].map(lambda x: map_dict[x])
    asset_df
    # output:
        asset_name    asset_id
    0    bond1    1
    1    bond1    2
    2    bond1    3
    3    bond2    4
    4    bond2    5
    5    bond2    5
    6    bond3    6
    7    bond3    7
    8    bond3    8
    9    bond3    8
    10    bond4    9
    11    bond4    10

    2.6.4 replace()

      replace() 函数用于替换dataframe中的元素为其他值。

    DataFrame.replace(to_replace=None, value=NoDefault.no_default, inplace=False, limit=None, regex=False, method=NoDefault.no_default)
    • 参数

      参数名含义可取值默认值
      to_replace找到将被替换的值的方法str,regex(正则表达式),list,dict,Series,int,float,or None
      value匹配到to_replace的位置将要被替换的值scalar,dict,list,str,regexNone
      inplace是否覆盖原dataframe,True:覆盖,不返回新的df,False:不覆盖,返回新的df列名False
      limit如果指定了方法,这是向前/向后填充的最大数目。换句话说,如果有超过这个数目的匹配值,它将只被部分填充。intNone
      regex是否将to_replace和(或)value解释为正则表达式。如果这是True,那么to_replace必须是一个字符串。Bool或与to_replace相同的类型False
      method当to_replace为标量、列表或元组且value为None时使用的方法。pad/ffill:由前一个值填充其后的NaN值,backfill/bfill:用NaN值后面的值向前填充‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, NoneNone

    参数 to_replace取值

    • df.replace(a, A, inplace=True)--a,b都为标量
      将dataframe所有列的a元素替换为A元素。
    • df.replace(to_replace=a, value=A, inplace=True)--a为列表,b为标量
      将dataframe所有列中,在列表a中的值全部替换为A元素。
    asset_df_bak3=asset_df.copy()
    asset_df_bak3.replace(to_replace=[0,1,2,3,10], value=0.1, inplace=True) # 将df中的0,1,2,3,10都替换为0.1
    asset_df_bak3
    # output:
    asset_name    asset_id
    0    Govtbond    0.1
    1    Govtbond    0.1
    2    Govtbond    0.1
    3    Finbond    4.0
    4    Finbond    5.0
    5    Finbond    5.0
    6    CorpbondAAA    6.0
    7    CorpbondAAA    7.0
    8    CorpbondAAA    8.0
    9    CorpbondAAA    8.0
    10    CorpbondAA    9.0
    11    CorpbondAA    0.1
    • df.replace(to_replace=a, value=A, inplace=True)--a为列表,A也为列表,且列表a与A长度一样
      将dataframe所有列中,在列表a中的值全部替换为列表A的值,替换时连个列表的值一一对应。
    • df.replace(to_replace=a, inplace=True)--a为字典,没有value参数
      将dataframe所有列中,等于字典a中key的元素全部替换为key对应的value。比如:to_replace={2:0.1,9:0.2},表示将df中的2替换为0.1,将9替换为0.2。
    • df.replace(to_replace=a,value=A, inplace=True)--a为字典,有value参数(此时字典的key为列名)
      将dataframe所有列中,等于字典a中key的列的某元素(对应的value)全部替换为A(此方法不能对多个列的元素替换为不同的值)。
    # 将asset_df_bak3中asset_name列中等于'Govtbond'和asset_id列中等于5的元素全部替换为0.55
    asset_df_bak3.replace(to_replace={'asset_name':'Govtbond','asset_id':5},value= 0.55,inplace=True)
    asset_df_bak3
    # output:
    asset_name    asset_id
    0    0.55    1.00
    1    0.55    2.00
    2    0.55    3.00
    3    Finbond    4.00
    4    Finbond    0.55
    5    Finbond    0.55
    6    CorpbondAAA    6.00
    7    CorpbondAAA    7.00
    8    CorpbondAAA    8.00
    9    CorpbondAAA    8.00
    10    CorpbondAA    9.00
    11    CorpbondAA    10.00
    • df.replace(to_replace=a, inplace=True)--a为字典,字典的key为列名,字典的value也是字典。
      此方法能对多个列的元素替换为不同的值
    # 将asset_df_bak3中asset_name列中等于'Finbond'的元素替换为'bond1',asset_id列中等于5的元素替换为0.55
    asset_df_bak3.replace(to_replace={'asset_name':{'Finbond':'bond1'},'asset_id':{5:0.55}},inplace=True)
    asset_df_bak3
    # output:
        asset_name    asset_id
    0    Govtbond    1.00
    1    Govtbond    2.00
    2    Govtbond    3.00
    3    bond1    4.00
    4    bond1    0.55
    5    bond1    0.55
    6    CorpbondAAA    6.00
    7    CorpbondAAA    7.00
    8    CorpbondAAA    8.00
    9    CorpbondAAA    8.00
    10    CorpbondAA    9.00
    11    CorpbondAA    10.00
    • df.replace(to_replace=a, regex=True, inplace=True)--根据正则表达式替换df中的元素。
    # 替换dataframe中的正负无穷值
    df.replace([np.nan, np.inf, -np.inf], 0, inplace=True)
    # 替换dataframe中的空字符串为nan
    df=df.replace('', np.nan)
    

    2.6.5 rename()

      rename()可以实现复制DataFrame并对其索引和列标签进行赋值。

    • 参数

      参数名含义可取值默认值
      mapper重命名对象的映射关系字典或表达式
      index替代指定轴(mapper, axis=0等价于index=mapper)。字典或表达式None
      axis决定重命名时的轴,0:按行重命名,1:按列重命名0 or ‘index’, 1 or ‘columns’0
      columns替代指定轴(mapper, axis=1等价于columns=mapper)。字典或表达式None
      inplace是否覆盖原dataframe,True:覆盖,不返回新的df,False:不覆盖,返回新的df列名False
      level有多层索引时可以对指定层的索引重命名int或者level nameNone
      errors是否忽略重命名过程中的错误{‘ignore’, ‘raise’}‘ignore’
    • 修改列名
    df = df.rename(columns={'c1': 'cc1'})

    2.6.6 set_index()

      用于设置dataframe的索引,可以将单列或多列设置为dataframe的索引。

    • 将单列设置为索引
    df_bak.set_index('asset_name')
    # output:
        asset_id    bond_period    rate    buying_time    amount
    asset_name                    
    Govtbond    1    5    0.0315    2019-12-31    30.0
    Govtbond    2    10    0.0355    2018-06-30    30.0
    Govtbond    3    15    0.0410    2015-09-30    50.0
    Finbond    4    5    0.0330    2019-12-31    18.0
    Finbond    5    10    0.0365    2018-06-30    21.0
    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    CorpbondAA    9    1    0.0480    2020-06-30    19.0
    CorpbondAA    10    5    0.0510    2020-06-30    12.0
    • 将多列设置为索引
    df_bak.set_index(['asset_name', 'asset_id'])
    # output:
                    bond_period    rate    buying_time    amount
    asset_name    asset_id                
    Govtbond    1    5    0.0315    2019-12-31    30.0
                2    10    0.0355    2018-06-30    30.0
                3    15    0.0410    2015-09-30    50.0
    Finbond    4    5    0.0330    2019-12-31    18.0
                5    10    0.0365    2018-06-30    21.0
    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
                7    5    0.0400    2020-06-30    8.0
                8    10    0.0490    2020-06-30    19.0
    CorpbondAA    9    1    0.0480    2020-06-30    19.0
                10    5    0.0510    2020-06-30    12.0

    2.6.7 reset_index()

      重置索引

    2.6.8 cut()

      cut()函数用于对数据分桶(bins),

    pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise', ordered=True)
    • 参数

      参数名含义可取值默认值
      x待分桶的数组(必须是一维数组)array-like
      bins分桶的标准int:,sequence of scalars:,IntervalIndex:
      right指示容器是否包括最右边的边,当bins是IntervalIndex时,这个参数被忽略boolTrue
      labels指定返回的容器的标签。array or FalseNone
      retbins是否返回分桶信息,当容器作为标量提供时很有用boolFalse
      precision存储和显示分箱标签的精度int3
      include_lowest第一个interval是否左包含。boolFalse
      duplicates如果bin边不是唯一的,抛出ValueError或删除非唯一的。 default ‘raise’, ‘drop’
    # 1、指定分桶的区间
    pd.cut(df_bak3['bond_period'], bins=[0,8,20])
    # output:
    ""
    0     (0, 8]
    1    (8, 20]
    2    (8, 20]
    3     (0, 8]
    4    (8, 20]
    5     (0, 8]
    6     (0, 8]
    7    (8, 20]
    8     (0, 8]
    9     (0, 8]
    Name: bond_period, dtype: category
    Categories (2, interval[int64]): [(0, 8] < (8, 20]]
    ""
    
    # 2、指定分桶的区间数,并返回分桶的信息
    pd.cut(df_bak3['bond_period'], bins=3, retbins=True)
    # output:
    ""
    (0     (0.986, 5.667]
     1    (5.667, 10.333]
     2     (10.333, 15.0]
     3     (0.986, 5.667]
     4    (5.667, 10.333]
     5     (0.986, 5.667]
     6     (0.986, 5.667]
     7    (5.667, 10.333]
     8     (0.986, 5.667]
     9     (0.986, 5.667]
     Name: bond_period, dtype: category
     Categories (3, interval[float64]): [(0.986, 5.667] < (5.667, 10.333] < (10.333, 15.0]],
     array([ 0.986     ,  5.66666667, 10.33333333, 15.        ]))
    ""
    
    # 3、指定分桶的区间数,并指定标签,返回分桶的信息
    pd.cut(df_bak3['bond_period'], bins=3, labels=['H', 'M', 'L'], retbins=True)
    # output:
    ""
    (0    H
     1    M
     2    L
     3    H
     4    M
     5    H
     6    H
     7    M
     8    H
     9    H
     Name: bond_period, dtype: category
     Categories (3, object): [H < M < L],
     array([ 0.986     ,  5.66666667, 10.33333333, 15.        ]))
    ""

    2.6.9 assign()

      df.assign(),为dataframe添加新列或者覆盖原有列。关键字参数为列名,如果列存在,则根据参数更新列值;如果列不存在,则添加新列。

    # 生成新列'year'
    df_bak3.assign(year=lambda x: x['buying_time'].str[:4])
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount    year
    0    Govtbond    1    5    0.0315    2019-12-31    30.0    3    2019
    1    Govtbond    2    10    0.0355    2018-06-30    30.0    5    2018
    2    Govtbond    3    15    0.0410    2015-09-30    50.0    6    2015
    3    Finbond    4    5    0.0330    2019-12-31    18.0    8    2019
    4    Finbond    5    10    0.0365    2018-06-30    21.0    1    2018
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0    7    2018
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0    9    2020
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0    19    2020
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0    10    2020
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0    15    2020
    
    # 不生成新列,覆盖'buying_time'
    df_bak3.assign(buying_time=lambda x: x['buying_time'].str[:4])
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    5    0.0315    2019    30.0    3
    1    Govtbond    2    10    0.0355    2018    30.0    5
    2    Govtbond    3    15    0.0410    2015    50.0    6
    3    Finbond    4    5    0.0330    2019    18.0    8
    4    Finbond    5    10    0.0365    2018    21.0    1
    5    CorpbondAAA    6    3    0.0380    2018    30.0    7
    6    CorpbondAAA    7    5    0.0400    2020    8.0    9
    7    CorpbondAAA    8    10    0.0490    2020    19.0    19
    8    CorpbondAA    9    1    0.0480    2020    19.0    10
    9    CorpbondAA    10    5    0.0510    2020    12.0    15

    2.6.10 pd.to_numeric()

    将dataframe列数据格式改成float。

    2.6.11 dt.date

    将dataframe列的数据格式改成日期

    2.6.12 df.columns.astype()

    修改dataframe列名的格式为字符串

    df.columns = df.columns.astype(str)

    2.7 数据格式修改

    2.7.1 pivot()

      根据索引或列重塑dataframe。没有指定为索引或者新列的原有列元素就当作新dataframe的值,没有值的位置为NaN。

    DataFrame.pivot(index=None, columns=None, values=None)
    • 参数

      参数名含义可取值默认值
      index设置为新索引的列str or object or a list of str可选参数
      columns设置为新列的列str or object or a list of str可选参数
      values用于填充新帧值的列。如果没有指定,将使用所有剩余的列,并且结果将具有分层索引的列。str, object or a list of the previous可选参数

    2.7.2 pivot_table()

      根据索引或列重塑dataframe。没有指定为索引或者新列的原有列元素就当作新dataframe的值,没有值的位置为NaN。pivot_table可以使用aggfunc参数指定需要计算的值(求和、均值等)

    DataFrame.pivot_table(values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All', observed=False, sort=True)
    • 参数

      参数名含义可取值默认值
      values用于填充新帧值的列。如果没有指定,将使用所有剩余的列,并且结果将具有分层索引的列。str, object or a list of the previous可选参数
      index设置为新索引的列str or object or a list of str可选参数
      columns设置为新列的列str or object or a list of str可选参数
      aggfunc设置对数据聚合时进行的函数操作function, list of functions, dictnumpy.mean
      fill_value缺失值填充scalarNone
    df_bak3[['asset_name', 'asset_id', 'bond_period', 'rate']].pivot_table(index=['asset_name', 'asset_id'], columns=['bond_period'])
    # output:
                rate
    bond_period    1    3    5    10    15
    asset_name    asset_id                    
    CorpbondAA    9    0.048    NaN    NaN    NaN    NaN
                10    NaN    NaN    0.0510    NaN    NaN
    CorpbondAAA    6    NaN    0.038    NaN    NaN    NaN
                7    NaN    NaN    0.0400    NaN    NaN
                8    NaN    NaN    NaN    0.0490    NaN
    Finbond        4    NaN    NaN    0.0330    NaN    NaN
                5    NaN    NaN    NaN    0.0365    NaN
    Govtbond    1    NaN    NaN    0.0315    NaN    NaN
                2    NaN    NaN    NaN    0.0355    NaN
                3    NaN    NaN    NaN    NaN    0.041

    2.7.3 unstack()

    2.8 数据提取

    2.8.1 简单取数

    # 取dataframe中的部分列
    df_bak2[['asset_name', 'asset_id','bond_period']]
    # 取amount大于20的所有行
    df_bak2[df_bak2['amount']>20]
    df_bak2[df_bak2.amount > 20]
    # 取所有大于20的值,不大于20的值为NaN
    df_bak2[df_bak2>20]
    # 如果所有列中,大于20的值的个数大于1,则保留该行数据
    df_bak2[(df_bak2>20).any(1)]
    # 取满足条件的数据对应的索引
    list(df_bak2[df_bak2.amount > 20].index)
    # 根据多个条件取数时,用&符号连接
    df_bak2[(df_bak2.amount > 20) & (df_bak2.bond_period==10)]

    2.8.2 sample()

      随机采样的可以通过sample()函数实现

    • 参数

      参数名含义可取值默认值
      n采样的数量,不可与frac同时使用int1且frac=None
      frac采样比例,不能与n一起使用floatNone
      replace允许或不允许对同一行进行多次抽样bool0
      weights str或ndarray-likeNone
      random_state随机种子,控制随机采样是否可重现intFalse
      axis行采样或列采样0 or ‘index’, 1 or ‘columns’None
      ignore_index是否忽略原有索引,重新生成索引0,1,2,...(pandas版本1.3.0之后)boolFalse

    weights
      参数weights等于str时,要求是DataFrame中的一个列名(即执行行抽样)。pandas将str表示的这个列的取值作为该行数据的抽样权重进行抽样。如果列中数据相加和不等于1,该列数据将被标准化到和为1。列中如果有缺失值,该行数据的抽样权重被视为0,也就是说不抽取这一行数据。
      weights是一个Series时,Series的长度可以和数据中行或列的长度不同。以行抽样为例,在进行抽样之前,pandas会先进行索引对齐,相当于对DataFrame和Series做一个左连接。DataFrame没有匹配到的索引对应的行抽样权重为0。

    # 根据amount列的元数大小,对应的概率采样
    df_bak2.sample(n=5,weights='amount')
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    1    Govtbond    2    10    0.0355    2018-06-30    30.0
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    # 根据weight_的采样权重大小采样,weight_中概率大于0的数的数量要大于采样条数n,否则会出现异常。
    weight_ = pd.Series([0.1, 0.1,0.3,0.2], index=[0,4,6,7])
    df_bak2.sample(n=3,weights=weight_)
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    0    Govtbond    1    5    0.0315    2019-12-31    30.0

    2.8.3 take()

      根据索引从dataframe中取数。利用numpy.random.permutation函数也可以轻松实现对DataFrame的列的采样工作,先使用permutation函数生成随机索引列表,然后使用take函数根据索引列表取数(permuting,随机重排序)。

    • 参数

      参数名含义可取值默认值
      indices待取出数据的索引array-like
      axis按行取或列取数0 or ‘index’, 1 or ‘columns’None
      is_copy是否返回副本(pandas版本1.0.0之后)boolTrue
    # 取列序号为0,1,2,3的4列
    df_bak2.take(indices=[0,1,2,3],axis=1)
    # output:
    asset_name    asset_id    bond_period    rate
    0    Govtbond    1    5    0.0315
    1    Govtbond    2    10    0.0355
    2    Govtbond    3    15    0.0410
    3    Finbond    4    5    0.0330
    4    Finbond    5    10    0.0365
    5    CorpbondAAA    6    3    0.0380
    6    CorpbondAAA    7    5    0.0400
    7    CorpbondAAA    8    10    0.0490
    8    CorpbondAA    9    1    0.0480
    9    CorpbondAA    10    5    0.0510

    3.8.4 iloc()

      根据行或列位置取数,参数可以是单个整数、整数列表(切片对象)或bool值列表。如果参数是单个整数,返回的结果是Series对象;参数是列表时(即使列表只有一个元素),返回的结果是DataFrame对象。
      当输入':'时,表示取全部行(或列),比如:df.iloc[:,[0,1,2]]表示取全部行,第0,1,2列的数据。

    # df_bak2:列'asset_name'置为索引
            asset_id    bond_period    rate    buying_time    amount
    asset_name                    
    Govtbond    1    5    0.0315    2019-12-31    30.0
    Govtbond    2    10    0.0355    2018-06-30    30.0
    Govtbond    3    15    0.0410    2015-09-30    50.0
    Finbond    4    5    0.0330    2019-12-31    18.0
    Finbond    5    10    0.0365    2018-06-30    21.0
    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    CorpbondAA    9    1    0.0480    2020-06-30    19.0
    CorpbondAA    10    5    0.0510    2020-06-30    12.0
    # 1、根据整数列表取数,取第0,1,3行,取0,1,4列
    df_bak2.iloc[[0,1,3],[0,1,4]]
    # output:
            asset_id    bond_period    amount
    asset_name            
    Govtbond    1    5    30.0
    Govtbond    2    10    30.0
    Finbond        4    5    18.0
    
    # 2、根据bool值列表取数,当bool值列表长度不够时,缺少的部分默认为False
    df_bak2.iloc[[True,True,False,True],[True,True,False,False,True]]
    # output:
            asset_id    bond_period    amount
    asset_name            
    Govtbond    1    5    30.0
    Govtbond    2    10    30.0
    Finbond        4    5    18.0

    3.8.5 loc()

      根据行或列名称取数,参数可以是单个名称、名称列表或bool值列表。如果参数是单个名称,返回的结果是Series对象;参数是列表时(即使列表只有一个元素),返回的结果是DataFrame对象。

    # 1、根据索引名称和列名称取数
    df_bak2.loc[['Govtbond'],['asset_id', 'bond_period','amount']]
    # output:
            asset_id    bond_period    amount
    asset_name            
    Govtbond    1    5    30.0
    Govtbond    2    10    30.0
    Govtbond    3    15    50.0
    
    # 2、根据bool值列表取数,当bool值列表长度不够时,缺少的部分默认为False
    df_bak2.loc[[True,True,False,True],[True,True,False,False,True]]
    # output:
            asset_id    bond_period    amount
    asset_name            
    Govtbond    1    5    30.0
    Govtbond    2    10    30.0
    Finbond        4    5    18.0
    
    # 3、根据数值大小取数
    df_bak2.loc[df_bak2['amount']>=30]
    # output:
            asset_id    bond_period    rate    buying_time    amount
    asset_name                    
    Govtbond    1    5    0.0315    2019-12-31    30.0
    Govtbond    2    10    0.0355    2018-06-30    30.0
    Govtbond    3    15    0.0410    2015-09-30    50.0
    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    
    # 4、通过loc修改dataframe中满足条件的值
    df_bak2.loc[[True,True,False,True],[True,True,False,False,True]]=[0,10,100]
    df_bak2
    # output:
        asset_id    bond_period    rate    buying_time    amount
    asset_name                    
    Govtbond    0    10    0.0315    2019-12-31    100.0
    Govtbond    0    10    0.0355    2018-06-30    100.0
    Govtbond    3    15    0.0410    2015-09-30    50.0
    Finbond    0    10    0.0330    2019-12-31    100.0
    Finbond    5    10    0.0365    2018-06-30    21.0
    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    CorpbondAA    9    1    0.0480    2020-06-30    19.0
    CorpbondAA    10    5    0.0510    2020-06-30    12.0
    
    # 5、当索引为多层索引时,可以通过元组指定不通层的索引取数
    # df:
                    max_speed    shield
    cobra    mark i    12    2
            mark ii    0    4
    sidewinder    mark i    10    20
            mark ii    1    4
    viper    mark ii    7    1
            mark iii    16    36
    df.loc[('cobra', 'mark ii')] # 返回Series对象
    df.loc[[('cobra', 'mark ii')]] # 返回DataFrame对象
    # 返回从cobra的mark i到viper索引的全部值
    df.loc[('cobra', 'mark i'):'viper']
    # 返回从cobra的mark ii到viper的mark ii索引的全部值
    df.loc[('cobra', 'mark ii'):('viper', 'mark ii')]
    # output:
                    max_speed    shield
    cobra        mark ii    0    4
    sidewinder    mark i    10    20
                mark ii    1    4
    viper        mark ii    7    1

    2.8.6 iloc与loc的对比

    • 不同点:

      iloc取数据是根据行或列位置的顺序取数,loc根据行或列名称取数;
      iloc可以通过切片的方式确定取数的位置,loc只有索引为数字时才可以,其他情况不可以;
      iloc不可以通过判断dataframe值大小来确定取数位置,loc可以根据元素大小取数;
      iloc不可以直接用于修改dataframe的元素,loc可以修改满足取数条件的位置对应的元素值;
      使用iloc根据索引大小取数的速度要稍快于loc根据列元素大小取数(大概快20%),但是将指定列置为索引需要额外耗费时间(设置索引列的时间加上iloc的时间,要大于直接loc的时间)
    • 相同点

      都可以通过bool值取数。

    2.8.7 iterrows()

      iterrows()按行遍历dataframe或series,返回两个元素:行索引和行值,其中行值为Series格式,可以根据list索引取具体的数值。

    # df_bak3
        asset_name    asset_id    bond_period    rate    buying_time    amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0
    1    Govtbond    2    10    0.0355    2018-06-30    30.0
    2    Govtbond    3    15    0.0410    2015-09-30    50.0
    3    Finbond    4    5    0.0330    2019-12-31    18.0
    4    Finbond    5    10    0.0365    2018-06-30    21.0
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0
    for index_, row in df_bak3.iterrows():
        print(index_,row)

    2.8.8 itertuples()

      itertuples为每一行产生一个namedtuple,并且行的索引值作为元组的第一个元素,pandas类型。

    for nametuple in df_bak3.itertuples():
        print(nametuple)
    
    # output:
    Pandas(Index=0, asset_name='Govtbond', asset_id=1, bond_period=5, rate=0.0315, buying_time='2019-12-31', amount=30.0)
    ...
    Pandas(Index=9, asset_name='CorpbondAA', asset_id=10, bond_period=5, rate=0.051, buying_time='2020-06-30', amount=12.0)

    2.8.9 df.str

      pandas的向量化字符串函数,可以用于dataframe中某字符串列的数据查找、截取等。

    • 方法

      方法名含义可取值默认值
      cat实现元素级的字符串连接操作,可以指定分隔符
      contains是否包含指定的子串
      endswith,startswith是否以指定的子串结尾(开始)
      get获取指定索引位置的子串
      isalnum是否为数字
      isalpha检查每个字符串中的所有字符是否为字母。
      isdecimal检查是否每个字符串中的所有字符都是数字(带小数点('1.5')、逗号(3,000)都会判别为False,'⅕'为False
      isdigit检查是否每个字符串中的所有字符都是数字(带小数点('1.5')、逗号(3,000)都会判别为False,'⅕'为False
      isnumeric检查是否每个字符串中的所有字符都是数字(带小数点('1.5')、逗号(3,000)都会判别为False,'⅕'为True)。
      islower是否为小写字母
      isupper是否为大写字母
      join使用指定分隔符将series中元素的字符串连接起来
      replacereplace('a', 'b') 使用子串b替换子串a
      split使用指定符号分割字符串
      strip(rstrip,lstrip)去除两边空值(去除右边空值,去除左边空值)
      upper,lower转大(小)写
    dataframe.str.split()

    将dataframe的某些列根据分隔符分成多列。
    如:将df2的rate_type按照“|”分割成两列,两列的列名分别为'asset_name', 'rate_type'。

    df2[['asset_name', 'rate_type']] = df2['rate_type'].str.split('|', expand=True)
    # output:
    year value_type rate
        0 2020 asset1|cii 0.19
        1 2020 asset1|nii 0.10
        2 2020 asset2|cii 0.20
        3 2020 asset2|nii 0.29

    参数expand=True时,表示将拆分的数据分成多列。

    year value_type rate asset
    0 2020 cii 0.19 asset1
    1 2020 nii 0.10 asset1
    2 2020 cii 0.20 asset2
    3 2020 nii 0.29 asset2
    

    如果拆分出来的数据的列数多于待存放数据的列,那么将数据从左到右依次保存,直到可存放数据的列用完,多于的数据将被舍弃。
    比如:

    df2['value_type'] = df2['value_type'].str.split('|', expand=True)
    # output:
        year value_type rate
        0 2020 asset1 0.19
        1 2020 asset1 0.10
        2 2020 asset2 0.20
        3 2020 asset2 0.29

    参数expand=False时,表示不将拆分的数据分成多列,以list格式保存为一列:

     year value_type rate
    0 2020 [asset1, cii] 0.19
    1 2020 [asset1, nii] 0.10
    2 2020 [asset2, cii] 0.20
    3 2020 [asset2, nii] 0.29
    
    

    2.9 数据合并

    2.9.1 concat()

      沿特定轴连接pandas对象,并沿其他轴连接可选的集合逻辑。使用concat可以实现merge的功能。

    pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
    • 参数

      参数名含义可取值默认值
      objs待连接的对象a sequence or mapping of Series or DataFrame objects无默认值,不可为空
      axis连接的轴{0/’index’, 1/’columns’}0
      join拼接方式,外连接、内连接{‘inner’, ‘outer’}‘outer’
      ignore_index是否忽略原有索引,重新生成索引boolFalse
      keys指定连接使用的键sequenceNone
      levels多级索引时使用list of sequencesNone
      names生成的层次结构索引中级别的名称listNone
      verify_integrity检查新的连接轴是否包含重复项boolFalse
      sort在连接为“外部”时,如果非连接轴尚未对齐,则对其进行排序。当join='inner'时,这没有影响,因为它已经保留了非连接轴的顺序。(pandas1.0.0)boolFalse

    2.9.2 merge()

      使用数据库样式的连接合并DataFrame或命名为Series的对象。一个Series对象被视为只有一个列的DataFrame对象。

    pandas.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
    • 参数

      参数名含义可取值默认值
      left待拼接的左dataframedataframe无默认值,不可为空
      right待拼接的右dataframedataframe无默认值,不可为空
      how拼接方式,如左连接、右连接、内连接等{‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’,cross是pandas版本1.2.0以上}‘inner’
      on要连接的列或索引级别名称。这些必须在两个数据帧中都找到。如果on为None并且没有在索引上合并,则默认为两个DataFrames中的列的交集label或list
      left_on列或索引级别的名称连接到左DataFrame。也可以是一个数组或数组的列表长度的左DataFramelabel或list
      right_on在正确的DataFrame中连接的列或索引级别名称label或list
      left_index是否使用来自左DataFrame的索引作为连接键boolFalse
      right_index是否使用来自右DataFrame的索引作为连接键boolFalse
      sort对结果DataFrame中的联接键按字典顺序排序。如果为False,则连接键的顺序取决于连接类型(how关键字)boolFalse
      suffixes长度为2的序列,其中每个元素都是可选的字符串,指示要分别添加到左侧和右侧重叠列名的后缀,比如:左右两个df都有'value'列,输入suffixes=('\_left', '\_right'),则拼接后分别为'value\_left', 'value\_right'list-like(“_x”, “_y”)
      copy是否复制boolTrue
      indicator如果为True,则在输出DataFrame中添加一个名为“\_merge”的列,该列包含关于每行源的信息。通过提供一个字符串参数,可以给列一个不同的名称。bool或strFalse
      validate如果指定,则检查merge是否为指定类型。str可选参数

    2.10 数据计算

    import random
    df_bak3=df.copy()
    df_bak3.fillna(method='ffill',inplace=True)
    df_bak3['new_amount'] = random.sample(range(1,20),10)
    # df_bak3:
        asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0    10
    1    Govtbond    2    10    0.0355    2018-06-30    30.0    12
    2    Govtbond    3    15    0.0410    2015-09-30    50.0    1
    3    Finbond    4    5    0.0330    2019-12-31    18.0    2
    4    Finbond    5    10    0.0365    2018-06-30    21.0    13
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0    15
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0    4
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0    16
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0    14
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0    17

    2.10.1 apply()

      apply()函数的作用是沿着DataFrame的轴线应用一个函数。

    DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)
    • 参数

      参数名含义可取值默认值
      func待应用的函数dataframe无默认值,不可为空
      axis指定轴线0 or ‘index’, 1 or ‘columns’0
      raw boolFalse
      result_type返回格式(只在axis=1时使用)‘expand’, ‘reduce’, ‘broadcast’, NoneNone
    # 对单列应用apply方法
    df_bak3['bond_period'] = df_bak3['bond_period'].apply(lambda x: x*12)
    df_bak3
    # output:
        asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    60    0.0315    2019-12-31    30.0    10
    1    Govtbond    2    120    0.0355    2018-06-30    30.0    12
    2    Govtbond    3    180    0.0410    2015-09-30    50.0    1
    3    Finbond    4    60    0.0330    2019-12-31    18.0    2
    4    Finbond    5    120    0.0365    2018-06-30    21.0    13
    5    CorpbondAAA    6    36    0.0380    2018-06-30    30.0    15
    6    CorpbondAAA    7    60    0.0400    2020-06-30    8.0    4
    7    CorpbondAAA    8    120    0.0490    2020-06-30    19.0    16
    8    CorpbondAA    9    12    0.0480    2020-06-30    19.0    14
    9    CorpbondAA    10    60    0.0510    2020-06-30    12.0    17
    
    # 2、求两列的和
    df_bak3['amount'] = df_bak3.apply(lambda x: x['amount'] + x['new_amount'], axis=1)
    df_bak3
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    60    0.0315    2019-12-31    40.0    10
    1    Govtbond    2    120    0.0355    2018-06-30    42.0    12
    2    Govtbond    3    180    0.0410    2015-09-30    51.0    1
    3    Finbond    4    60    0.0330    2019-12-31    20.0    2
    4    Finbond    5    120    0.0365    2018-06-30    34.0    13
    5    CorpbondAAA    6    36    0.0380    2018-06-30    45.0    15
    6    CorpbondAAA    7    60    0.0400    2020-06-30    12.0    4
    7    CorpbondAAA    8    120    0.0490    2020-06-30    35.0    16
    8    CorpbondAA    9    12    0.0480    2020-06-30    33.0    14
    9    CorpbondAA    10    60    0.0510    2020-06-30    29.0    17
    
    # 3、当传入的不是单个值时且result_type=None
    df_bak3['new_amount'] = df_bak3.apply(lambda x: [1,3], axis=1)
    df_bak3
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0    [1, 3]
    1    Govtbond    2    10    0.0355    2018-06-30    30.0    [1, 3]
    2    Govtbond    3    15    0.0410    2015-09-30    50.0    [1, 3]
    3    Finbond    4    5    0.0330    2019-12-31    18.0    [1, 3]
    4    Finbond    5    10    0.0365    2018-06-30    21.0    [1, 3]
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0    [1, 3]
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0    [1, 3]
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0    [1, 3]
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0    [1, 3]
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0    [1, 3]
    
    # 4、当传入的不是单个值时且result_type='expand',由于apply的结果只赋值给了一列,所以结果中只有一个数。
    df_bak3['new_amount'] = df_bak3.apply(lambda x: [1,3], axis=1, result_type='expand')
    df_bak3
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    Govtbond    1    5    0.0315    2019-12-31    30.0    1
    1    Govtbond    2    10    0.0355    2018-06-30    30.0    1
    2    Govtbond    3    15    0.0410    2015-09-30    50.0    1
    3    Finbond    4    5    0.0330    2019-12-31    18.0    1
    4    Finbond    5    10    0.0365    2018-06-30    21.0    1
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0    1
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0    1
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19、.0    1
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0    1
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0    1
    

    2.10.2 applymap()

      applymap()函数的作用是将函数应用到每一个元素,而apply()只会将函数应用都某一个轴线。

    # 对同一个dataframe分别应用apply()和applymap()
    df_bak3.apply(lambda x: [1,3])
    # output:
    asset_name     [1, 3]
    asset_id       [1, 3]
    bond_period    [1, 3]
    rate           [1, 3]
    buying_time    [1, 3]
    amount         [1, 3]
    new_amount     [1, 3]
    dtype: object
    
    df_bak3.apply(lambda x: [1,3], axis=1)
    # output:
    0    [1, 3]
    1    [1, 3]
    2    [1, 3]
    3    [1, 3]
    4    [1, 3]
    5    [1, 3]
    6    [1, 3]
    7    [1, 3]
    8    [1, 3]
    9    [1, 3]
    dtype: object
    
    df_bak3.applymap(lambda x: [1,3])
    # output:
        asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    1    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    2    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    3    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    4    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    5    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    6    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    7    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    8    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]
    9    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]    [1, 3]

    2.10.3 shift()

      dataframe平移。

    DataFrame.shift(periods=1, freq=None, axis=0, fill_value=NoDefault.no_default)
    # periods--平移periods行,periods是负数时表示向上平移,正数则向下平移。
    # freq--从tseries模块或时间规则使用的偏移量(索引是日期时可用)
    df_bak3.shift(periods=2)
    # output:
    asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    0    NaN    NaN    NaN    NaN    NaN    NaN    NaN
    1    NaN    NaN    NaN    NaN    NaN    NaN    NaN
    2    Govtbond    1.0    5.0    0.0315    2019-12-31    30.0    15.0
    3    Govtbond    2.0    10.0    0.0355    2018-06-30    30.0    4.0
    4    Govtbond    3.0    15.0    0.0410    2015-09-30    50.0    14.0
    5    Finbond    4.0    5.0    0.0330    2019-12-31    18.0    12.0
    6    Finbond    5.0    10.0    0.0365    2018-06-30    21.0    10.0
    7    CorpbondAAA    6.0    3.0    0.0380    2018-06-30    30.0    1.0
    8    CorpbondAAA    7.0    5.0    0.0400    2020-06-30    8.0    11.0
    9    CorpbondAAA    8.0    10.0    0.0490    2020-06-30    19.0    5.0

    2.10.4 df.groupby()

      groupby()用于对大量数据进行分组,并计算对这些分组的操作。

    • 参数

      参数名含义可取值默认值
      by用于确定groupby的组mapping, function, label, or list of labels无默认值,不可为空
      axis确定groupby的轴{0 or ‘index’, 1 or ‘columns’}0
      level如果轴是MultiIndex(层次化),则按一个或多个特定级别进行分组。int, level name, or sequence of suchNone
      as_index boolTrue
      sort对groupby的键是否排序boolTrue
      group_keys boolTrue
    ## 变量grouped是一个GroupBy对象,它实际上还没有进行任何计算
    grouped = df_bak3.groupby('asset_name')
    grouped
    # output:
    <pandas.core.groupby.groupby.DataFrameGroupBy object at 0x000002A080D98FD0>
    1) 使用groupby对dataframe按照列名、索引分组

    然后对分组的数据求均值、方差等计算。

    ## 按单列分组求和sum(),均值mean(),标准差std()等
    df_bak3.groupby('asset_name').mean()
    # output:
            asset_id    bond_period    rate    amount    new_amount
    asset_name                    
    CorpbondAA    9.5    3.0    0.049500    15.500000    12.500000
    CorpbondAAA    7.0    6.0    0.042333    19.000000    11.666667
    Finbond        4.5    7.5    0.034750    19.500000    4.500000
    Govtbond    2.0    10.0    0.036000    36.666667    4.666667
    
    ## 同时传入多个对象:对df按照多级分组,然后求列均值、标准差等。
    df_bak3.groupby(['asset_name', 'buying_time'], sort=False).sum()
    # output:
            asset_id    bond_period    rate    amount    new_amount
    asset_name    buying_time                    
    Govtbond    2019-12-31    1    5    0.0315    30.0    3
                2018-06-30    2    10    0.0355    30.0    5
                2015-09-30    3    15    0.0410    50.0    6
    Finbond        2019-12-31    4    5    0.0330    18.0    8
                2018-06-30    5    10    0.0365    21.0    1
    CorpbondAAA    2018-06-30    6    3    0.0380    30.0    7
                2020-06-30    15    15    0.0890    27.0    28
    CorpbondAA    2020-06-30    19    6    0.0990    31.0    25
    
    ## 使用size()方法查看每个分组的数据大小。
    df_bak3.groupby(['asset_name', 'buying_time'], sort=False).size()
    asset_name   buying_time
    Govtbond     2019-12-31     1
                 2018-06-30     1
                 2015-09-30     1
    Finbond      2019-12-31     1
                 2018-06-30     1
    CorpbondAAA  2018-06-30     1
                 2020-06-30     2
    CorpbondAA   2020-06-30     2
    dtype: int64
    2) groupby对象支持迭代

    产生一组二元元组(由分组名和数据块组成),其中数据块的索引与原dataframe一致。

    ## 单个键的情况
    for key1, sub_df in df_bak3.groupby(['asset_name'], sort=False):
        print(key1)
        print(sub_df)
    # output:
    Govtbond
      asset_name  asset_id  bond_period    rate buying_time  amount  new_amount
    0   Govtbond         1            5  0.0315  2019-12-31    30.0           3
    1   Govtbond         2           10  0.0355  2018-06-30    30.0           5
    2   Govtbond         3           15  0.0410  2015-09-30    50.0           6
    Finbond
      asset_name  asset_id  bond_period    rate buying_time  amount  new_amount
    3    Finbond         4            5  0.0330  2019-12-31    18.0           8
    4    Finbond         5           10  0.0365  2018-06-30    21.0           1
    CorpbondAAA
        asset_name  asset_id  bond_period   rate buying_time  amount  new_amount
    5  CorpbondAAA         6            3  0.038  2018-06-30    30.0           7
    6  CorpbondAAA         7            5  0.040  2020-06-30     8.0           9
    7  CorpbondAAA         8           10  0.049  2020-06-30    19.0          19
    CorpbondAA
       asset_name  asset_id  bond_period   rate buying_time  amount  new_amount
    8  CorpbondAA         9            1  0.048  2020-06-30    19.0          10
    9  CorpbondAA        10            5  0.051  2020-06-30    12.0          15
    
    ## 对于多重键的情况,元组的第一个元素将会是由键值组成的元组
    for (key1, key2), sub_df in df_bak3.groupby(['asset_name', 'buying_time'], sort=False):
        print(key1, key2)
        print(sub_df)
    3) groupby默认是在axis=0上进行分组的,通过设置也可以在其他任何轴上进行分组
    df_bak3.groupby('asset_name', axis=1).sum()
    4) 分组信息可以是字典

    将dataframe的列通过字典的键值对映射,可以将多列映射到同一个键值,然后传入字典根据键值分组。

    mapping={'asset_id':'asset_id','amount': 'amount',
             'new_amount': 'amount', 'buying_time':'buying_time',
            'bond_period':'bond_period', 'rate':'rate'}
    df_bak3.groupby(mapping, axis=1).sum()
    # output:
    amount    asset_id    bond_period    buying_time    rate
    0    33.0    1    5    2019-12-31    0.0315
    1    35.0    2    10    2018-06-30    0.0355
    2    56.0    3    15    2015-09-30    0.0410
    3    26.0    4    5    2019-12-31    0.0330
    4    22.0    5    10    2018-06-30    0.0365
    5    37.0    6    3    2018-06-30    0.0380
    6    17.0    7    5    2020-06-30    0.0400
    7    38.0    8    10    2020-06-30    0.0490
    8    29.0    9    1    2020-06-30    0.0480
    9    27.0    10    5    2020-06-30    0.0510
    5) groupby()的聚合操作

    对datafram数据groupby之后,可以对其他单列或多列进行聚合操作,求均值(mean())、最小值(min())、最大值(max())、求和(sum())、中位数(median())、方差(var(ddof=0), var(ddof=1))、标准差(std(ddof=0), std(ddof=1))等。格式有多种。

    import pandas as pd
    real_constrains = dict(
     name=['a', 'b', 'c', 'd', 'a','c'],
     ret=[0.3,0.12,0.13, 0.21, 6,0.01],
     duration = [0.5,1,6,2,5,10]
     )
    constrains_df = pd.DataFrame(real_constrains)
    
    res1 = constrains_df.groupby('name')['ret'].std(ddof=0)
    # 要对多列求不同的聚合计算时,可以通过agg函数传字典参数进行计算
    res2 = constrains_df.groupby('name').agg({'ret':'max','duration':'min'})
    res3 = constrains_df.groupby('name')[['ret','duration']].min()
    res4 = constrains_df.groupby('name').std(ddof=0)['ret']
    print(res1,res2,res3,res4)
    
    # output:
    name
    a    2.85
    b    0.00
    c    0.06
    d    0.00
    Name: ret, dtype: float64        ret  duration
    name                
    a     6.00       0.5
    b     0.12       1.0
    c     0.13       6.0
    d     0.21       2.0        ret  duration
    name                
    a     0.30       0.5
    b     0.12       1.0
    c     0.01       6.0
    d     0.21       2.0 name
    a    2.85
    b    0.00
    c    0.06
    d    0.00
    Name: ret, dtype: float64
    
    6) groupby的transform操作

    使用agg操作会将groupby条件相同的数据整合,而transform操作可以将结果返回原dataframe的新列,并将结果返回给每一行。

    import pandas as pd
    real_constrains = dict(
     name=['a', 'b', 'c', 'd', 'a','c'],
     ret=[0.3,0.12,0.13, 0.21, 6,0.01],
     duration = [0.5,1,6,2,5,10]
     )
    constrains_df = pd.DataFrame(real_constrains)
    
    # 使用agg无法将计算结果返回给原DF新的列
    constrains_df['ave_ret_agg'] = constrains_df.groupby('name')['ret'].mean()
    print('使用agg结果:\n', constrains_df)
    # 使用transform可以将计算结果返回原DF的每一行
    constrains_df['ave_ret_tra'] = constrains_df.groupby('name')['ret'].transform('mean')
    print('使用transform结果:\n', constrains_df)
    
    # output:
    使用agg结果:
       name   ret  duration  ave_ret_agg
    0    a  0.30       0.5          NaN
    1    b  0.12       1.0          NaN
    2    c  0.13       6.0          NaN
    3    d  0.21       2.0          NaN
    4    a  6.00       5.0          NaN
    5    c  0.01      10.0          NaN
    使用transform结果:
       name   ret  duration  ave_ret_agg  ave_ret_tra
    0    a  0.30       0.5          NaN         3.15
    1    b  0.12       1.0          NaN         0.12
    2    c  0.13       6.0          NaN         0.07
    3    d  0.21       2.0          NaN         0.21
    4    a  6.00       5.0          NaN         3.15
    5    c  0.01      10.0          NaN         0.07

    2.10.5 df.rolling(n)

      时间窗函数rolling()用于对数据进行平移计算,如计算相邻10个数据的均值mean()、和sum()、方差var()等。

    DataFrame.rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None, method='single')
    • 参数

      参数名含义可取值默认值
      window移动窗口的大小int, offset(只对datetime类索引有效), or BaseIndexer subclass
      min_periods窗口中需要一个值的最小观测数,如果不满足最小观测数,则返回np.nanintNone,如果window是整数,默认是窗口大小;如果window是偏移量,则默认为1
      center是否将窗口标签设置为窗口索引的中心boolFalse
      win_type设置窗口类型strNone
      on对于DataFrame,用于计算滚动窗口的列标签或索引级别,而不是DataFrame的索引str可选
      axis设置按行或列计算0 or 'index',1 or 'columns'0
      closed(pandas版本1.3.0)如果为“right”,则窗口中的第一个点将被排除在计算之外。如果为'left',则将窗口中的最后一个点排除在计算之外。如果'both',则将窗口中的no点排除在计算之外。如果'neither',则将窗口中的第一个和最后一个点排除在计算之外。strNone
    • 示例
    tmp_df = pd.DataFrame({'B': [0, 1, 2, np.nan, np.nan,4], 'C': [0.2, 0.5, 0.6, 0.8,np.nan, np.nan]})
    tmp_df
    # output:
    B    C
    0    0.0    0.2
    1    1.0    0.5
    2    2.0    0.6
    3    NaN    0.8
    4    NaN    NaN
    5    4.0    NaN
    ## 1、不设置最小观测数min_periods时,必须要3个数全不为nan才能输出值
    tmp_df.rolling(window=3).sum()
    # output:
    B    C
    0    NaN    NaN
    1    NaN    NaN
    2    3.0    1.3
    3    NaN    1.9
    4    NaN    NaN
    5    NaN    NaN
    
    ## 2、设置min_periods=2时,只需要3个数中有2个为数即可
    tmp_df.rolling(window=3, min_periods=2).sum()
    # output:
    B    C
    0    NaN    NaN
    1    1.0    0.7
    2    3.0    1.3
    3    3.0    1.9
    4    NaN    1.4
    5    NaN    NaN
    
    ## 3、填充空值,比较参数'center'不同时的差异。可以看出,当center=True时,会将计算结果与窗口的中间一个数据的索引对齐。center=Flse时,会将计算结果与窗口的最后一个数据的索引对齐。
    tmp_df.fillna(method='ffill', inplace=True)
    # output:
        B    C
    0    0.0    0.2
    1    1.0    0.5
    2    2.0    0.6
    3    2.0    0.8
    4    2.0    0.8
    5    4.0    0.8
    tmp_df.rolling(window=3, center=False).sum()
    # output:
    B    C
    0    NaN    NaN
    1    NaN    NaN
    2    3.0    1.3
    3    5.0    1.9
    4    6.0    2.2
    5    8.0    2.4
    tmp_df.rolling(window=3, center=True).sum()
    # output:
    B    C
    0    NaN    NaN
    1    3.0    1.3
    2    5.0    1.9
    3    6.0    2.2
    4    8.0    2.4
    5    NaN    NaN
    # output:

    2.10.6 df.sort_values()

      将dataframe按指定轴的元素排序。

    DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
    • 参数

      参数名含义可取值默认值
      by要排序的名称或名称列表
      axis指定轴{0 or ‘index’, 1 or ‘columns’}0
      ascending指定升序(ascending=True)还是降序(ascending=False),bool or list of boolTrue
      kind指定排序算法{‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’}quicksort
    • 示例
    df_bak3.sort_values(by=['asset_name', 'bond_period'], ascending=True)
    # output:
        asset_name    asset_id    bond_period    rate    buying_time    amount    new_amount
    8    CorpbondAA    9    1    0.0480    2020-06-30    19.0    10
    9    CorpbondAA    10    5    0.0510    2020-06-30    12.0    15
    5    CorpbondAAA    6    3    0.0380    2018-06-30    30.0    7
    6    CorpbondAAA    7    5    0.0400    2020-06-30    8.0    9
    7    CorpbondAAA    8    10    0.0490    2020-06-30    19.0    19
    3    Finbond    4    5    0.0330    2019-12-31    18.0    8
    4    Finbond    5    10    0.0365    2018-06-30    21.0    1
    0    Govtbond    1    5    0.0315    2019-12-31    30.0    3
    1    Govtbond    2    10    0.0355    2018-06-30    30.0    5
    2    Govtbond    3    15    0.0410    2015-09-30    50.0    6

    2.10.7 df.cumprod()

      按指定轴计算dataframe的累乘。

    real_constrains = dict(
                ret=[0.3,0.12,0.13, 0.21, 6,0.01],
                duration = [0.1,1,6,2,5,10]
            )
    df = pd.DataFrame(real_constrains)
    df['temp_cumu_price'] = df['duration']+ 1
    df['cumu_price2'] = df['temp_cumu_price'].cumprod(axis=0)
    # output:
    ret  duration  temp_cumu_price  cumu_price2
    0  0.30       0.1              1.1          1.1
    1  0.12       1.0              2.0          2.2
    2  0.13       6.0              7.0         15.4
    3  0.21       2.0              3.0         46.2
    4  6.00       5.0              6.0        277.2
    5  0.01      10.0             11.0       3049.2
    • 使用np.pord()函数同样可以实现,但是需要做循环计算,计算速度会比df.cumprod()慢很多。
    import time
    import random
    real_constrains = dict(
                ret=np.random.normal(1.151, 0.05, 1000),
                duration = np.random.normal(5, 1, 1000)
            )
    df = pd.DataFrame(real_constrains)
    df['cumu_price'] = np.nan
    st_prod = time.time()
    for idx in range(0, len(df)):
            df['cumu_price'][idx] = np.prod(df['duration'][0:idx + 1] + 1)
    et_prod = time.time()
    print('all time of prod =', et_prod-st_prod)
    st_cumprod = time.time()
    df['temp_cumu_price'] = df['duration']+ 1
    df['cumu_price2'] = df['temp_cumu_price'].cumprod(axis=0)
    et_cumprod = time.time()
    print('all time of cumprod =', et_cumprod-st_cumprod)
    # output:
    all time of prod = 0.30219101905822754
    all time of cumprod = 0.0009975433349609375

    2.10.8 sum()和cumsum()

      sum表示按指定轴、指定列求和,只对相同条件中的最后一行赋值。cumsum表示按指定轴、指定列求累加和。

    real_constrains = dict(
        duration = [1,1,6,2,5,10],
                ret=[0.12,0.12,0.13, 0.21, 6,0.01]            
            )
    
    df = pd.DataFrame(real_constrains)
    print('原DF: \n',df)
    df['cum_ret'] = df.groupby(['duration'])['ret'].cumsum()
    print('求cumsum后:\n', df)
    # output 原DF: 
        duration   ret
    0         1  0.12
    1         1  0.12
    2         6  0.13
    3         2  0.21
    4         5  6.00
    5        10  0.01
    
    # output 求cumsum后:
        duration   ret  cum_ret
    0         1  0.12     0.12
    1         1  0.12     0.24
    2         6  0.13     0.13
    3         2  0.21     0.21
    4         5  6.00     6.00
    5        10  0.01     0.01

    参考文献:
    利用 Python 进行数据分析
    Pandas数据处理三板斧


    YjxGVG
    8 声望3 粉丝