zoukankan      html  css  js  c++  java
  • pandas学习笔记

    1.缺失值处理 - 拉格朗日插值法

    input_file数据文件内容(存在部分缺失值):

    from scipy.interpolate import lagrange
    import pandas as pd
    import numpy as np input_file
    = './data/catering_sale.xls' output_file = './data/sales.xls' data = pd.read_excel(input_file) data['销量'][(data['销量'] < 400) | (data['销量'] > 5000)] = None  # 销量小于400及大于5000的视为异常值,置为None # 自定义列向量插值函数 # 问题:当n<k时,list(range(n-k, n))会出现负数,导致y的值出现空值,会影响最终的插值结果,这个问题还未解决。。。 def ployinterp_column(s, n, k=5): # s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5 y = s[list(range(n-k, n)) + list(range(n+1, n+k+1))] y = y[y.notnull()] # 剔除空值 if n-k < 0: # 如果NaN值在前5位,则插值结果取k-n位 return lagrange(y.index, list(y))(k-n) else: return lagrange(y.index, list(y))(n) # 插值并返回插值结果 # 逐个元素判断是否需要插值 for j in range(len(data)): if (data['销量'].isnull())[j]: # 如果元素为空,则进行插值 data['销量'][j] = ployinterp_column(data['销量'], j) data.to_excel(output_file)

    output_file结果:

    # np.where()
    a = pd.Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan], index=['f', 'e', 'd', 'c', 'b', 'a'])
    b = pd.Series(np.arange(len(a), dtype=np.float64), index=['f', 'e', 'd', 'c', 'b', 'a'])
    
    # 如果a有缺失值,则用相应位置的b填充,否则使用a的原有元素
    print(np.where(pd.isnull(a), b, a))
    
    # result
    [ 0.   2.5  2.   3.5  4.5  5. ]
    # df.combine_first()
    df1 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
                     'b': [np.nan, 2., np.nan, 6.],
                     'c': range(2, 18, 4)})
    df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
                     'b': [np.nan, 3., 4., 6., 8.]})
    
    # 将df1中的缺失值用df2中相同位置的元素填充,如果没有缺失值则保持df1的原有元素
    df1.combine_first(df2)
    
    # result
         a    b     c
    0  1.0  NaN   2.0
    1  4.0  2.0   6.0
    2  5.0  4.0  10.0
    3  3.0  6.0  14.0
    4  7.0  8.0   NaN
    # 异常值处理
    data = pd.DataFrame(np.random.randn(1000, 4))
    print(data.describe())
    # result
                     0            1            2            3
    count  1000.000000  1000.000000  1000.000000  1000.000000
    mean     -0.012809     0.007609    -0.002442     0.027889
    std       1.026971     0.985884     0.999810     1.006344
    min      -3.174895    -2.970125    -3.011063    -3.440525
    25%      -0.723649    -0.657574    -0.642299    -0.647432
    50%      -0.019972     0.021018    -0.015020     0.012603
    75%       0.707184     0.678987     0.674781     0.707672
    max       3.076159     3.890196     2.869127     3.089114
    
    
    col = data[3]
    # 大于3的值为异常值
    col[np.abs(col) > 3]
    data[(np.abs(data) > 3).any(1)] # any(1)
    # np.sign()函数,大于0为1,小于0为-1
    data[np.abs(data) > 3] = np.sign(data) * 3
    print(data.describe())
    # result
                     0            1            2            3
    count  1000.000000  1000.000000  1000.000000  1000.000000
    mean     -0.012763     0.006719    -0.002428     0.028545
    std       1.026062     0.982772     0.999768     1.003687
    min      -3.000000    -2.970125    -3.000000    -3.000000
    25%      -0.723649    -0.657574    -0.642299    -0.647432
    50%      -0.019972     0.021018    -0.015020     0.012603
    75%       0.707184     0.678987     0.674781     0.707672
    max       3.000000     3.000000     2.869127     3.000000

     2.数据合并:

    # pd.merge()
    # 使用列或者索引,以类似数据库连接的方式合并多个DataFrame对象
    df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})
    df2 =  pd.DataFrame({'key': ['a', 'b', 'd'], 'data2': range(3)})
    
    print(pd.merge(df1, df2))  # 自动匹配合并列, 默认内连接
    print(pd.merge(df1, df2, on='key'))    # 显式指定
    
    # result

    data1 key data2
    0 0 b 1
    1 1 b 1
    2 6 b 1
    3 2 a 0
    4 4 a 0
    5 5 a 0

    
    df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})
    df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'], 'data2': range(3)})
    print(pd.merge(df3, df4, left_on='lkey', right_on='rkey'))    # 当不存在相同column时,需要分别指定连接列名

    # result

    data1 lkey data2 rkey
    0 0 b 1 b
    1 1 b 1 b
    2 6 b 1 b
    3 2 a 0 a
    4 4 a 0 a
    5 5 a 0 a

    ## 指定连接方式
    # 外连接
    print(pd.merge(df1, df2, how='outer'))
    
    # result
    
       data1 key  data2
    0    0.0   b    1.0
    1    1.0   b    1.0
    2    6.0   b    1.0
    3    2.0   a    0.0
    4    4.0   a    0.0
    5    5.0   a    0.0
    6    3.0   c    NaN
    7    NaN   d    2.0
    # 左连接
    df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'], 'data1': range(6)})
    df2 = pd.DataFrame({'key': ['a', 'b', 'a', 'b', 'd'] ,'data2': range(5)})
    
    print(pd.merge(df1, df2, how='left'))
    
    # result
    
        data1 key  data2
    0       0   b    1.0
    1       0   b    3.0
    2       1   b    1.0
    3       1   b    3.0
    4       2   a    0.0
    5       2   a    2.0
    6       3   c    NaN
    7       4   a    0.0
    8       4   a    2.0
    9       5   b    1.0
    10      5   b    3.0
    # 多列连接
    left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
                      'key2': ['one', 'two', 'one'],
                      'lval': [1, 2, 3]})
    right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
                       'key2': ['one', 'one', 'one', 'two'],
                       'rval': [4, 5, 6, 7]})
    
    print(pd.merge(left, right, on=['key1', 'key2']))  # 默认内连接
    
    # result
      key1 key2  lval  rval
    0  foo  one     1     4
    1  foo  one     1     5
    2  bar  one     3     6
    
    
    print(pd.merge(left, right, on=['key1', 'key2'], how='outer')) # 外连接
    
    # result
      key1 key2  lval  rval
    0  foo  one   1.0   4.0
    1  foo  one   1.0   5.0
    2  foo  two   2.0   NaN
    3  bar  one   3.0   6.0
    4  bar  two   NaN   7.0
    # 只以其中一个列连接,会出现冗余列
    pd.merge(left, right, on='key1')
    
    # result
      key1 key2_x  lval key2_y  rval
    0  foo    one     1    one     4
    1  foo    one     1    one     5
    2  foo    two     2    one     4
    3  foo    two     2    one     5
    4  bar    one     3    one     6
    5  bar    one     3    two     7
    
    
    print(pd.merge(left, right, on='key1', suffixes=('_left', '_right')))  # 给冗余列增加后缀
    
    # result
      key1 key2_left  lval key2_right  rval
    0  foo       one     1        one     4
    1  foo       one     1        one     5
    2  foo       two     2        one     4
    3  foo       two     2        one     5
    4  bar       one     3        one     6
    5  bar       one     3        two     7
    # 使用索引与列进行合并
    left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],'value': range(6)})
    right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
    
    print(pd.merge(left1, right1, left_on='key', right_index=True))    # left1使用key列连接,right1使用index列连接
    
    # result
      key  value  group_val
    0   a      0        3.5
    2   a      2        3.5
    3   a      3        3.5
    1   b      1        7.0
    4   b      4        7.0
    # 多列索引连接
    lefth = pd.DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
                       'key2': [2000, 2001, 2002, 2001, 2002],
                       'data': np.arange(5.)})
    righth = pd.DataFrame(np.arange(12).reshape((6, 2)),
                       index=[['Nevada', 'Nevada', 'Ohio', 'Ohio', 'Ohio', 'Ohio'],
                              [2001, 2000, 2000, 2000, 2001, 2002]],
                       columns=['event1', 'event2'])
    
    print(pd.merge(lefth, righth, left_on=['key1', 'key2'], right_index=True))
    
    # result

    data key1 key2 event1 event2
    0 0.0 Ohio 2000 4 5
    0 0.0 Ohio 2000 6 7
    1 1.0 Ohio 2001 8 9
    2 2.0 Ohio 2002 10 11
    3 3.0 Nevada 2001 0 1

    # pd.join()
    # pd.join()可以使用index或key合并两个及以上的DataFrame(列方向上的合并)
    left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]], index=['a', 'c', 'e'], columns=['Ohio', 'Nevada']) right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]], index=['b', 'c', 'd', 'e'], columns=['Missouri', 'Alabama']) print(left2.join(right2, how='outer')) # result Ohio Nevada Missouri Alabama a 1.0 2.0 NaN NaN b NaN NaN 7.0 8.0 c 3.0 4.0 9.0 10.0 d NaN NaN 11.0 12.0 e 5.0 6.0 13.0 14.0
    # 合并多个DataFrame
    another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],
                        index=['a', 'c', 'e', 'f'], columns=['New York', 'Oregon'])
    
    left2.join([right2, another], how='outer')
    
    # result
       Ohio  Nevada  Missouri  Alabama  New York  Oregon
    a   1.0     2.0       NaN      NaN       7.0     8.0
    b   NaN     NaN       7.0      8.0       NaN     NaN
    c   3.0     4.0       9.0     10.0       9.0    10.0
    d   NaN     NaN      11.0     12.0       NaN     NaN
    e   5.0     6.0      13.0     14.0      11.0    12.0
    f   NaN     NaN       NaN      NaN      16.0    17.0
    # 轴向连接# np.concatenate()
    arr = np.arange(12).reshape((3,4))
    print(np.concatenate([arr, arr], axis=1))  # 在column方向上连接
    
    # result
    
    array([[ 0,  1,  2, ...,  1,  2,  3],
           [ 4,  5,  6, ...,  5,  6,  7],
           [ 8,  9, 10, ...,  9, 10, 11]])
    # pd.concat()
    s1 = pd.Series([0,1], index=['a', 'b'])
    s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
    s3 = pd.Series([5, 6], index=['f', 'g'])
    
    print(pd.concat([s1, s2, s3]))    # axis参数默认为0,row方向的
    # result
    a    0
    b    1
    c    2
    d    3
    e    4
    f    5
    g    6
    dtype: int64
    
    print(pd.concat([s1, s2, s3], axis=1)) # column方向合并,值如果不存在则记为NaN
    # result
         0    1    2
    a  0.0  NaN  NaN
    b  1.0  NaN  NaN
    c  NaN  2.0  NaN
    d  NaN  3.0  NaN
    e  NaN  4.0  NaN
    f  NaN  NaN  5.0
    g  NaN  NaN  6.0
    
    
    s4 = pd.concat([s1 * 5, s3])
    s5 = pd.concat([s1, s4], axis=1)
    s5.columns = ['s1', 's4']
    print(s5)
    
    # result
        s1  s4
    a  0.0   0
    b  1.0   5
    f  NaN   5
    g  NaN   6
    
    print(pd.concat([s1, s4], axis=1, join='inner'))   # join参数指定连接方式
    # result
       0  1
    a  0  0
    b  1  5
    
    print(pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']]))    # 手动指定要连接的index  
    # result
         0    1
    a  0.0  0.0
    c  NaN  NaN
    b  1.0  5.0
    e  NaN  NaN
    # 使用keys参数对索引进行分级
    result = pd.concat([s1, s2, s3], keys=['one', 'two', 'three'])  # 在row方向合并时,keys对应每个Series的一级index,每个Series原有的index则作为二级index
    
    print(result)
    
    # result
    one    a    0
           b    1
    two    c    2
           d    3
           e    4
    three  f    5
           g    6
    dtype: int64
    # Series.unstack() 将Seris格式转换为DataFrame格式
    print(result.unstack()) # 一级索引将作为index,二级索引作为columns
    
    # result
             a    b    c    d    e    f    g
    one    0.0  1.0  NaN  NaN  NaN  NaN  NaN
    two    NaN  NaN  2.0  3.0  4.0  NaN  NaN
    three  NaN  NaN  NaN  NaN  NaN  5.0  6.0
    # 在列合并时使用keys参数指定column名称
    print(pd.concat([s1, s2, s3], axis=1, keys=['one', 'two', 'three']))   # 在column方向合并时,keys对应每个合并的Series的column
    
    # result
       one  two  three
    a  0.0  NaN    NaN
    b  1.0  NaN    NaN
    c  NaN  2.0    NaN
    d  NaN  3.0    NaN
    e  NaN  4.0    NaN
    f  NaN  NaN    5.0
    g  NaN  NaN    6.0
    # 指定分级column
    df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'], columns=['one', 'two'])
    df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'], columns=['three', 'four'])
    
    # 因为DataFrame对象已经有了column,所以keys参数会设置新的一级column, df原有的column则作为二级column df3
    = pd.concat([df1, df2], axis=1, keys=['level1', 'level2']) print(df3) print(df3.columns) # result level1 level2 one two three four a 0 1 5.0 6.0 b 2 3 NaN NaN c 4 5 7.0 8.0 MultiIndex(levels=[['level1', 'level2'], ['four', 'one', 'three', 'two']], labels=[[0, 0, 1, 1], [1, 3, 2, 0]]) # 使用字典实现相同的功能 print(pd.concat({'level1': df1, 'level2': df2}, axis=1)) #result level1 level2 one two three four a 0 1 5.0 6.0 b 2 3 NaN NaN c 4 5 7.0 8.0 # 指定分级column名称 df = pd.concat([df1, df2], axis=1, keys=['level1', 'level2'], names=['levels', 'number']) print(df) print(df.columns) # result levels level1 level2 number one two three four a 0 1 5.0 6.0 b 2 3 NaN NaN c 4 5 7.0 8.0 MultiIndex(levels=[['level1', 'level2'], ['four', 'one', 'three', 'two']], labels=[[0, 0, 1, 1], [1, 3, 2, 0]], names=['levels', 'number'])
    # ignore_index
    df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
    df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
    
    # row方向忽略索引
    print(pd.concat([df1, df2], ignore_index=True))
    # result
              a         b         c         d
    0  1.261208  0.022188 -2.489475 -1.098245
    1  0.618618 -1.179827  1.475738  0.334444
    2 -0.319088 -0.153492  0.029245  0.336055
    3 -0.999023 -0.502154       NaN  0.722256
    4  1.428007 -0.726810       NaN  0.432440
    
    # column方向忽略列名
    print(pd.concat([df1, df2], axis=1, ignore_index=True))
    # result
              0         1         2         3         4         5         6
    0  1.261208  0.022188 -2.489475 -1.098245 -0.502154  0.722256 -0.999023
    1  0.618618 -1.179827  1.475738  0.334444 -0.726810  0.432440  1.428007
    2 -0.319088 -0.153492  0.029245  0.336055       NaN       NaN       NaN

    3.重塑层次化索引

    data = pd.DataFrame(np.arange(6).reshape((2, 3)),
                        index=pd.Index(['Ohio', 'Colorado'], name='state'),
                        columns=pd.Index(['one', 'two', 'three'], name='number'))
    
    # 轴向旋转
    result = data.stack()
    print(result)
    # result
    state     number
    Ohio      one       0
              two       1
              three     2
    Colorado  one       3
              two       4
              three     5
    
    # 还原操作
    print(result.unstack())
    # result
    number    one  two  three
    state                    
    Ohio        0    1      2
    Colorado    3    4      5
    
    # 行列转置
    print(result.unstack(0))
    # result
    state   Ohio  Colorado
    number                
    one        0         3
    two        1         4
    three      2         5
    
    # 指定要转置的索引名
    print(result.unstack('number'))
    # result
    number    one  two  three
    state                    
    Ohio        0    1      2
    Colorado    3    4      5
    # 例1:
    s1 = pd.Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd']) s2 = pd.Series([4, 5, 6], index=['c', 'd', 'e']) data2 = pd.concat([s1, s2], keys=['one', 'two']) print(data2.unstack()) # result a b c d e one 0.0 1.0 2.0 3.0 NaN two NaN NaN 4.0 5.0 6.0 print(data2.unstack().stack()) # result one a 0.0 b 1.0 c 2.0 d 3.0 two c 4.0 d 5.0 e 6.0 dtype: float64 # 不dropnan值 print(data2.unstack().stack(dropna=False)) # result one a 0.0 b 1.0 c 2.0 d 3.0 e NaN two a NaN b NaN c 4.0 d 5.0 e 6.0 dtype: float64
    # 例2:
    df = pd.DataFrame({'left': result, 'right': result + 5},
                      columns=pd.Index(['left', 'right'], name='side'))
    
    print(df.unstack('state'))
    # result
    side   left          right         
    state  Ohio Colorado  Ohio Colorado
    number                             
    one       0        3     5        8
    two       1        4     6        9
    three     2        5     7       10
    
    print(df.unstack('state').stack('side'))
    # result
    state         Colorado  Ohio
    number side                 
    one    left          3     0
           right         8     5
    two    left          4     1
           right         9     6
    three  left          5     2
           right        10     7

    4.长宽格式的转换:

    所谓长格式,即相关属性都集中在同一个列中,另有一个VALUE列对应相应的属性值;

    而宽格式, 就是各个属性自成一列,不需要单独的VALUE列。

    # 导入宽格式数据
    data = pd.read_csv('./data/macrodata.csv')
    # pd.PeriodIndex 用来存放表示周期性日期的数组,数组元素是不可更改的。例如:年、季度、月、天等。
    periods = pd.PeriodIndex(year=data.year, quarter=data.quarter, name='date')
    data = pd.DataFrame(data.to_records(),  # to_records() 将DF转换成numpy record数组
                        columns=pd.Index(['realgdp', 'infl', 'unemp'], name='item'),
                        index=periods.to_timestamp('D', 'end'))
    
    print(data.head())
    # result
    item         realgdp  infl  unemp
    date                             
    1959-03-31  2710.349  0.00    5.8
    1959-06-30  2778.801  2.34    5.1
    1959-09-30  2775.488  2.74    5.3
    1959-12-31  2785.204  0.27    5.6
    1960-03-31  2847.699  2.31    5.2
    # 将宽格式转换为长格式
    # 轴向旋转 -> 重置索引 -> rename列名
    long_data = data.stack().reset_index().rename(columns={0: 'value'})
    
    print(long_data.head())
    # result
            date     item     value
    0 1959-03-31  realgdp  2710.349
    1 1959-03-31     infl     0.000
    2 1959-03-31    unemp     5.800
    3 1959-06-30  realgdp  2778.801
    4 1959-06-30     infl     2.340
    # 将长格式转换为宽格式
    """ pd.pivot()
    基于index/column的值重新调整DataFrame的坐标轴。不支持数据聚合,重复值会导致重复记录
    语法格式: df.pivot(index(optional), columns, values) """
    
    wide_data = long_data.pivot('date', 'item', 'value')
    
    print(wide_data.head())
    # result
    item        infl   realgdp  unemp
    date                             
    1959-03-31  0.00  2710.349    5.8
    1959-06-30  2.34  2778.801    5.1
    1959-09-30  2.74  2775.488    5.3
    1959-12-31  0.27  2785.204    5.6
    1960-03-31  2.31  2847.699    5.2
    # 增加一列value2
    long_data['value2'] = np.random.rand(len(long_data))
    
    print(long_data.head())
    # result
            date     item     value    value2
    0 1959-03-31  realgdp  2710.349  0.155924
    1 1959-03-31     infl     0.000  0.340776
    2 1959-03-31    unemp     5.800  0.615475
    3 1959-06-30  realgdp  2778.801  0.417256
    4 1959-06-30     infl     2.340  0.845293
    
    
    # 转换时如果不指定values,会将剩余的列都作为values列
    pivoted = long_data.pivot('date', 'item')   # data为index,item为columns
    
    print(pivoted.head())
    # result
               value                    value2                    
    item        infl   realgdp unemp      infl   realgdp     unemp
    date                                                          
    1959-03-31  0.00  2710.349   5.8  0.340776  0.155924  0.615475
    1959-06-30  2.34  2778.801   5.1  0.845293  0.417256  0.825615
    1959-09-30  2.74  2775.488   5.3  0.413700  0.512401  0.874806
    1959-12-31  0.27  2785.204   5.6  0.081047  0.358632  0.790962
    1960-03-31  2.31  2847.699   5.2  0.833500  0.395999  0.329820

    5. 删除重复数据:

    data = pd.DataFrame({'k1': ['one'] * 3 + ['two'] * 4,
                         'k2': [1, 1, 2, 3, 3, 4, 4]})
    
    print(data)
    # result
        k1  k2
    0  one   1
    1  one   1
    2  one   2
    3  two   3
    4  two   3
    5  two   4
    6  two   4
    
    
    # 判断当前行与前一行是否相同
    print(data.duplicated())
    # result
    0    False
    1     True
    2    False
    3    False
    4     True
    5    False
    6     True
    dtype: bool
    
    # drop重复行
    print(data.drop_duplicates())
    # result
        k1  k2
    0  one   1
    2  one   2
    3  two   3
    5  two   4
    # 新增v1列
    data['v1'] = range(7)
    
    # 只以k1列为标准删除重复行
    print(data.drop_duplicates(['k1']))
    # result
        k1  k2  v1
    0  one   1   0
    3  two   3   3
    
    # 以k1,k2为准,并且取最后一行的值
    print(data.drop_duplicates(['k1', 'k2'], keep='last'))
    # result
        k1  k2  v1
    1  one   1   1
    2  one   2   2
    4  two   3   4
    6  two   4   6

    6.利用函数及映射进行转换

    # 使用字典映射进行转换
    data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon', 'Pastrami',
                               'corned beef', 'Bacon', 'pastrami', 'honey ham',
                               'nova lox'],
                         'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
    print(data)
    # result
              food  ounces
    0        bacon     4.0
    1  pulled pork     3.0
    2        bacon    12.0
    3     Pastrami     6.0
    4  corned beef     7.5
    5        Bacon     8.0
    6     pastrami     3.0
    7    honey ham     5.0
    8     nova lox     6.0
    
    meat_to_animal = {
      'bacon': 'pig',
      'pulled pork': 'pig',
      'pastrami': 'cow',
      'corned beef': 'cow',
      'honey ham': 'pig',
      'nova lox': 'salmon'
      }
    
    data['animal'] = data['food'].map(str.lower).map(meat_to_animal)
    print(data)
    # result
              food  ounces  animal
    0        bacon     4.0     pig
    1  pulled pork     3.0     pig
    2        bacon    12.0     pig
    3     Pastrami     6.0     cow
    4  corned beef     7.5     cow
    5        Bacon     8.0     pig
    6     pastrami     3.0     cow
    7    honey ham     5.0     pig
    8     nova lox     6.0  salmon
    # 使用lambda匿名函数进行转换
    
    data['animal2'] = data.food.map(lambda x:meat_to_animal[x.lower()])
    
    print(data)
    # result
              food  ounces  animal animal2
    0        bacon     4.0     pig     pig
    1  pulled pork     3.0     pig     pig
    2        bacon    12.0     pig     pig
    3     Pastrami     6.0     cow     cow
    4  corned beef     7.5     cow     cow
    5        Bacon     8.0     pig     pig
    6     pastrami     3.0     cow     cow
    7    honey ham     5.0     pig     pig
    8     nova lox     6.0  salmon  salmon

    7.数据标准化

    有时候由于量纲(数据单位)不一致,导致数据的差异很大,无法进行比较,需要进行数据标准化,将数据进行一定范围的压缩,以便进行数据比对等后续操作。

    datafile = './data/normalization_data.xls'
    data = pd.read_excel(datafile, header=None)
    print(data)
    # result
         0    1    2     3
    0   78  521  602  2863
    1  144 -600 -521  2245
    2   95 -457  468 -1283
    3   69  596  695  1054
    4  190  527  691  2051
    5  101  403  470  2487
    6  146  413  435  2571
    
    
    # 最小-最大规范化
    data1 = (data - data.min()) / (data.max() - data.min())
    print(data1)
    # result
              0         1         2         3
    0  0.074380  0.937291  0.923520  1.000000
    1  0.619835  0.000000  0.000000  0.850941
    2  0.214876  0.119565  0.813322  0.000000
    3  0.000000  1.000000  1.000000  0.563676
    4  1.000000  0.942308  0.996711  0.804149
    5  0.264463  0.838629  0.814967  0.909310
    6  0.636364  0.846990  0.786184  0.929571
    
    # 零-均值规范化
    data2 = (data - data.mean()) / data.std()
    print(data2)
    # result
              0         1         2         3
    0 -0.905383  0.635863  0.464531  0.798149
    1  0.604678 -1.587675 -2.193167  0.369390
    2 -0.516428 -1.304030  0.147406 -2.078279
    3 -1.111301  0.784628  0.684625 -0.456906
    4  1.657146  0.647765  0.675159  0.234796
    5 -0.379150  0.401807  0.152139  0.537286
    6  0.650438  0.421642  0.069308  0.595564
    
    # np.ceil() 正向取整
    data3 = data/10**np.ceil(np.log10(data.abs().max()))
    print(data3)
    # result
           0      1      2       3
    0  0.078  0.521  0.602  0.2863
    1  0.144 -0.600 -0.521  0.2245
    2  0.095 -0.457  0.468 -0.1283
    3  0.069  0.596  0.695  0.1054
    4  0.190  0.527  0.691  0.2051
    5  0.101  0.403  0.470  0.2487
    6  0.146  0.413  0.435  0.2571

    8.replace替换

    data = pd.Series([1., -999., 2., -999., -1000., 3.])
    print(data)
    # result
    0       1.0
    1    -999.0
    2       2.0
    3    -999.0
    4   -1000.0
    5       3.0
    dtype: float64
    
    # 基本替换方式
    print(data.replace(-999, np.nan))
    # result
    0       1.0
    1       NaN
    2       2.0
    3       NaN
    4   -1000.0
    5       3.0
    dtype: float64
    
    # 使用列表分别替换对应位置的元素
    print(data.replace([-999, -1000], [np.nan, 0]))
    # result
    0    1.0
    1    NaN
    2    2.0
    3    NaN
    4    0.0
    5    3.0
    dtype: float64
    
    # 使用字典进行更明确的替换
    print(data.replace({-999: np.nan, -1000: 0})) # result 0 1.0 1 NaN 2 2.0 3 NaN 4 0.0 5 3.0 dtype: float64

    9.重命名轴索引:

    data = pd.DataFrame(np.arange(12).reshape((3, 4)),
                     index=['Ohio', 'Colorado', 'New York'],
                     columns=['one', 'two', 'three', 'four'])
    data.index = data.index.map(str.upper)
    
    print(data)
    # result
              one  two  three  four
    OHIO        0    1      2     3
    COLORADO    4    5      6     7
    NEW YORK    8    9     10    11
    
    # 重命名索引及列名
    print(data.rename(index=str.title, columns=str.upper))
    # result
              ONE  TWO  THREE  FOUR
    Ohio        0    1      2     3
    Colorado    4    5      6     7
    New York    8    9     10    11
    
    # 使用字典映射新索引及新列名
    print(data.rename(index={'OHIO': 'INDIANA'}, columns={'three': 'peekaboo'}))
    # result
              one  two  peekaboo  four
    INDIANA     0    1         2     3
    COLORADO    4    5         6     7
    NEW YORK    8    9        10    11

    10.数据离散化与面元划分

    ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
    bins = [18, 25, 35, 60, 100]
    
    # 按照bins中的区间划分ages中的元素
    cats = pd.cut(ages, bins)
    print(cats)
    # result
    [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
    Length: 12
    Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
    
    # 查看元素属于哪个区间
    print(cats.labels)    # python2用法
    print(cats.codes)     # python3用法
    # result
    [0 0 0 ..., 2 2 1]
    
    # 统计元素分布情况
    print(pd.value_counts(cats))
    # result
    (18, 25]     5
    (35, 60]     3
    (25, 35]     3
    (60, 100]    1
    dtype: int64
    # 默认的区间访问为左开右闭,指定right=False后,变成左闭右开
    print(pd.cut(ages, [18, 26, 36, 61, 100], right=False))
    # result
    [[18, 26), [18, 26), [18, 26), [26, 36), [18, 26), ..., [26, 36), [61, 100), [36, 61), [36, 61), [26, 36)]
    Length: 12
    Categories (4, interval[int64]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]
    
    # 手动设置标签,用来替换默认的区间
    group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
    cat2 = pd.cut(ages, bins, labels=group_names)   
    print(cat2.value_counts())
    # result
    MiddleAged    3
    Senior        1
    YoungAdult    3
    Youth         5
    dtype: int64
    # 指定区间的划分精度
    data = np.random.rand(20)
    print(pd.cut(data, 4, precision=2))
    # result
    [(0.054, 0.27], (0.71, 0.93], (0.27, 0.49], (0.27, 0.49], (0.054, 0.27], ..., (0.71, 0.93], (0.71, 0.93], (0.71, 0.93], (0.054, 0.27], (0.71, 0.93]]
    Length: 20
    Categories (4, interval[float64]): [(0.054, 0.27] < (0.27, 0.49] < (0.49, 0.71] < (0.71, 0.93]]
    # 自定义分位点
    print(pd.qcut(data, [0, 0.1, 0.5, 0.9, 1]))
    # result
    [(0.0953, 0.431], (0.893, 0.929], (0.431, 0.893], (0.0953, 0.431], (0.0953, 0.431], ..., (0.431, 0.893], (0.431, 0.893], (0.431, 0.893], (0.0536, 0.0953], (0.431, 0.893]]
    Length: 20
    Categories (4, interval[float64]): [(0.0536, 0.0953] < (0.0953, 0.431] < (0.431, 0.893] < (0.893, 0.929]]

    11.排列与随机采样

    # np.random.permutation()
    df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4)))
    print(df)
    # result
        0   1   2   3
    0   0   1   2   3
    1   4   5   6   7
    2   8   9  10  11
    3  12  13  14  15
    4  16  17  18  19
    
    # 随机取5个数组成一个排列
    sampler = np.random.permutation(5)
    print(sampler)
    # result
    [0 1 2 4 3]
    
    # 按照排列获取df中的数据
    print(df.take(sampler))
    # result
        0   1   2   3
    0   0   1   2   3
    1   4   5   6   7
    2   8   9  10  11
    4  16  17  18  19
    3  12  13  14  15
    
    # 只取排列中的后三行数据
    print(df.take(np.random.permutation(len(df))[:3]))
    # result
        0   1   2   3
    1   4   5   6   7
    4  16  17  18  19
    0   0   1   2   3
    # np.random.randint()
    bag = np.array([5, 7, -1, 6, 4])
    
    # 从0到5中随机取10个数
    sampler = np.random.randint(0, len(bag), size=10)
    print(sampler)
    # result
    [4 0 0 3 3 4 3 0 1 1]
    
    # 将sampler作为索引值,获取bag的对应元素
    draws = bag.take(sampler)
    print(draws)
    print(bag[sampler])  # 简化写法,可得同样结果
    # result
    [4 5 5 6 6 4 6 5 7 7]

    12.哑向量的使用

    哑向量通常用来表示一组彼此间相互独立的属性,也成为因子。将他们的关系用只有0和1的向量表示,就叫做哑向量。

    # 对某列取哑向量
    df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'], 'data1': range(6), 'data2': [1, 3, 5, 7, 9, 11]})
    print(pd.get_dummies(df['key']))
    # result
       a  b  c
    0  0  1  0
    1  0  1  0
    2  1  0  0
    3  0  0  1
    4  1  0  0
    5  0  1  0
    
    print(pd.get_dummies(df['data2']))
    # result
       1   3   5   7   9   11
    0   1   0   0   0   0   0
    1   0   1   0   0   0   0
    2   0   0   1   0   0   0
    3   0   0   0   1   0   0
    4   0   0   0   0   1   0
    5   0   0   0   0   0   1
    # 对列名加前缀
    dummies = pd.get_dummies(df['key'], prefix='key')
    # 将哑向量与df[data1]连接在一起
    df_with_dummy = df[['data1']].join(dummies)
    print(df_with_dummy)
    # result
       data1  key_a  key_b  key_c
    0      0      0      1      0
    1      1      0      1      0
    2      2      1      0      0
    3      3      0      0      1
    4      4      1      0      0
    5      5      0      1      0
    # 哑向量例子
    # 读入影评数据
    movies = pd.read_table('./data/movies.dat', sep='::', header=None, names=mnames)
    
    数据文件内容:
    
    # 设置列名
    mnames = ['movie_id', 'title', 'genres']
    
    # 提取genres列中的数据,将分离的元素组成集合
    genre_iter = (set(x.split('|')) for x in movies.genres)
    # 对genre_iter中的set集合解压后去重,再排序
    genres = sorted(set.union(*genre_iter))
    
    # 生成DataFrame哑向量
    dummies = pd.DataFrame(np.zeros((len(movies), len(genres))), columns=genres)    # 先根据数据文件生成一个元素均为0的DF
    for i, gen in enumerate(movies.genres): # 对genres进行循环
        dummies.loc[i, gen.split('|')] = 1   # 将genres中的项按照行号设置为1,使其成为哑向量
    
    # 将哑向量df与原df合并到一起
    movies_windic = movies.join(dummies.add_prefix('Genre_'))
    # 查看第一行数据(Series格式)
    print(movies_windic.iloc[0])
    # result
    movie_id                                       1
    title                           Toy Story (1995)
    genres               Animation|Children's|Comedy
    Genre_Action                                   0
    Genre_Adventure                                0
    Genre_Animation                                1
    Genre_Children's                               1
    Genre_Comedy                                   1
    Genre_Crime                                    0
    Genre_Documentary                              0
    Genre_Drama                                    0
    Genre_Fantasy                                  0
    Genre_Film-Noir                                0
    Genre_Horror                                   0
    Genre_Musical                                  0
    Genre_Mystery                                  0
    Genre_Romance                                  0
    Genre_Sci-Fi                                   0
    Genre_Thriller                                 0
    Genre_War                                      0
    Genre_Western                                  0
    Name: 0, dtype: object
    # 使用pd.cut()进行分类,然后转换成哑向量
    values = np.random.rand(10)
    bins = [0, 0.2, 0.4, 0.6, 0.8, 1]
    pd.get_dummies(pd.cut(values, bins))
    # result
       (0.0, 0.2]  (0.2, 0.4]  (0.4, 0.6]  (0.6, 0.8]  (0.8, 1.0]
    0           1           0           0           0           0
    1           0           0           0           1           0
    2           0           0           0           0           1
    3           0           0           1           0           0
    4           1           0           0           0           0
    5           0           0           0           1           0
    6           0           0           1           0           0
    7           0           0           0           0           1
    8           0           1           0           0           0
    9           0           1           0           0           0
  • 相关阅读:
    JavaScript笔试必备语句
    JQuery获取元素的方法总结
    JavaScript易错知识点整理
    程序员都讨厌开会?
    JS操作select下拉框动态变动(创建/删除/获取)
    用 jQuery.ajaxSetup 实现对请求和响应数据的过滤
    HTML5 学习笔记(一)——HTML5概要与新增标签
    json返回数据库的时间格式为/Date(1477294037000)/,怎样在前台进行格式化转换
    Hive 12、Hive优化
    Hive 11、Hive嵌入Python
  • 原文地址:https://www.cnblogs.com/dev-liu/p/pandas_3.html
Copyright © 2011-2022 走看看