• Python之Pandas库学习(三):数据处理


    1. 合并

    可以将其理解为SQL中的JOIN操作,使用一个或多个键把多行数据结合在一起。

    1.1. 简单合并

    参数on表示合并依据的列,参数how表示用什么方式操作(默认是内连接)。

    >>> frame1 = pd.DataFrame( {'id':['ball', 'pencil', 'pen', 'mug', 'ashtray'], 'color':['white', 'red', 'red', 'black', 'green'], 'brand':['OMG', 'ABC', 'ABC', 'POD', 'POD']} )
    >>> frame1
      brand  color       id
    0   OMG  white     ball
    1   ABC    red   pencil
    2   ABC    red      pen
    3   POD  black      mug
    4   POD  green  ashtray
    >>> frame2 = pd.DataFrame( {'id':['pencil', 'pencil', 'ball', 'pen'], 'brand':['OMG', 'POD', 'ABC', 'POD']} )
    >>> frame2
      brand      id
    0   OMG  pencil
    1   POD  pencil
    2   ABC    ball
    3   POD     pen
    >>> frame2.columns = ['brand', 'nid']
    
    可以指定左边用哪一列合并,右边用哪一列合并
    >>> pd.merge(frame1, frame2, left_on='id', right_on='nid')
      brand_x  color      id brand_y     nid
    0     OMG  white    ball     ABC    ball
    1     ABC    red  pencil     OMG  pencil
    2     ABC    red  pencil     POD  pencil
    3     ABC    red     pen     POD     pen
    
    根据多个列进行,并且以外连接方式合并
    >>> frame2.columns = ['brand', 'id']
    >>> pd.merge(frame1, frame2, on=['id', 'brand'], how='outer')
      brand  color       id
    0   OMG  white     ball
    1   ABC    red   pencil
    2   ABC    red      pen
    3   POD  black      mug
    4   POD  green  ashtray
    5   OMG    NaN   pencil
    6   POD    NaN   pencil
    7   ABC    NaN     ball
    8   POD    NaN      pen
    

    1.2. 根据索引合并

    将left_index和right_index设为True
    >>> pd.merge(frame1, frame2, right_index=True, left_index=True)
      brand_x  color    id_x brand_y    id_y
    0     OMG  white    ball     OMG  pencil
    1     ABC    red  pencil     POD  pencil
    2     ABC    red     pen     ABC    ball
    3     POD  black     mug     POD     pen
    
    使用DataFrame()对象的join()函数进行合并,注意不能有重复的列名
    >>> frame2.columns=['brand2', 'id2']
    >>> frame1.join(frame2)
      brand  color       id brand2     id2
    0   OMG  white     ball    OMG  pencil
    1   ABC    red   pencil    POD  pencil
    2   ABC    red      pen    ABC    ball
    3   POD  black      mug    POD     pen
    4   POD  green  ashtray    NaN     NaN
    

    2. 拼接

    2.1. NumPy的concatenate()函数

    >>> array1 = np.arange(9).reshape((3,3))
    >>> array2 = np.arange(9).reshape((3,3))+3
    >>> array1
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    >>> array2
    array([[ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    >>> np.concatenate([array1,array2])
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    >>> np.concatenate([array1,array2], axis = 1)
    array([[ 0,  1,  2,  3,  4,  5],
           [ 3,  4,  5,  6,  7,  8],
           [ 6,  7,  8,  9, 10, 11]])
    

    2.2. Pandas的concat()函数

    >>> ser1
    1    0.105168
    2    0.344241
    3    0.798570
    4    0.648794
    dtype: float64
    >>> ser2
    5    0.161205
    6    0.427794
    7    0.813935
    8    0.742369
    dtype: float64
    >>> pd.concat([ser1, ser2])
    1    0.105168
    2    0.344241
    3    0.798570
    4    0.648794
    5    0.161205
    6    0.427794
    7    0.813935
    8    0.742369
    dtype: float64
    >>> pd.concat([ser1, ser2], axis = 1)
              0         1
    1  0.105168       NaN
    2  0.344241       NaN
    3  0.798570       NaN
    4  0.648794       NaN
    5       NaN  0.161205
    6       NaN  0.427794
    7       NaN  0.813935
    8       NaN  0.742369
    由上面可以看出concat()默认选项是外连接.
    
    指定为内连接
    >>> ser3 = pd.Series(np.random.rand(4), index = [1,2,3,4])
    >>> ser3
    1    0.599582
    2    0.123096
    3    0.870401
    4    0.635363
    dtype: float64
    >>> pd.concat([ser1, ser3], axis = 1, join = 'inner')
              0         1
    1  0.105168  0.599582
    2  0.344241  0.123096
    3  0.798570  0.870401
    4  0.648794  0.635363
    
    可以用keys参数可以创建等级索引,对列进行合并的话,keys会变成列名
    >>> pd.concat([ser1, ser2], keys=['fir','sec'])
    fir  1    0.105168
         2    0.344241
         3    0.798570
         4    0.648794
    sec  5    0.161205
         6    0.427794
         7    0.813935
         8    0.742369
    dtype: float64
    >>> pd.concat([ser1, ser2], axis=1, keys=['fir','sec'])
            fir       sec
    1  0.105168       NaN
    2  0.344241       NaN
    3  0.798570       NaN
    4  0.648794       NaN
    5       NaN  0.161205
    6       NaN  0.427794
    7       NaN  0.813935
    8       NaN  0.742369
    

    3. 组合

    使用combine_first()函数。

    >>> ser1 = pd.Series(np.random.rand(5), index = [1,2,3,4,5])
    >>> ser2 = pd.Series(np.random.rand(5), index = [1,3,5,7,9])
    >>> ser1
    1    0.426299
    2    0.732439
    3    0.951809
    4    0.955885
    5    0.183026
    dtype: float64
    >>> ser2
    1    0.981828
    3    0.162136
    5    0.364654
    7    0.607903
    9    0.345988
    dtype: float64
    >>> ser1.combine_first(ser2)
    1    0.426299
    2    0.732439
    3    0.951809
    4    0.955885
    5    0.183026
    7    0.607903
    9    0.345988
    dtype: float64
    >>> ser2.combine_first(ser1)
    1    0.981828
    2    0.732439
    3    0.162136
    4    0.955885
    5    0.364654
    7    0.607903
    9    0.345988
    dtype: float64
    
    部分合并使用切片
    >>> ser1[:4].combine_first(ser2[:4])
    1    0.426299
    2    0.732439
    3    0.951809
    4    0.955885
    5    0.364654
    7    0.607903
    dtype: float64
    

    4. 轴向旋转

    4.1. 按等级索引旋转

    stack():把列转换成行。

    unstack():把行转换成列。

    >>> frame1 = pd.DataFrame(np.arange(9).reshape(3,3), index=['white', 'black', 'red'], columns=['ball', 'pen', 'pencil'])
    >>> frame1
           ball  pen  pencil
    white     0    1       2
    black     3    4       5
    red       6    7       8
    
    >>> ser = frame1.stack()
    >>> ser
    white  ball      0
           pen       1
           pencil    2
    black  ball      3
           pen       4
           pencil    5
    red    ball      6
           pen       7
           pencil    8
    dtype: int32
    
    >>> ser = frame1.unstack()
    >>> ser
    ball    white    0
            black    3
            red      6
    pen     white    1
            black    4
            red      7
    pencil  white    2
            black    5
            red      8
    dtype: int32
    
    >>> ser.unstack(0)
           ball  pen  pencil
    white     0    1       2
    black     3    4       5
    red       6    7       8
    >>> ser.unstack(1)
            white  black  red
    ball        0      3    6
    pen         1      4    7
    pencil      2      5    8
    参数表示对第几层进行操作
    

    4.2. 从"长"向"宽"旋转

    有时候一类数据集各列都有数据项,每一列后面的数据和前面有重复,这类数据常为列表形式,将其称为长格式栈格式。还有一种宽格式,可读性强,存储数据效率更高。因此有时候需要转换。

    >>> longframe = pd.DataFrame( {'color':['white', 'white', 'white', 'red', 'red', 'red', 'black', 'black', 'black'], 'item':['ball','pen','mug','ball','pen','mug','ball','pen','mug'],'value':np.random.rand(9)} )
    >>> longframe
       color  item     value
    0  white  ball  0.657363
    1  white   pen  0.209334
    2  white   mug  0.878001
    3    red  ball  0.674560
    4    red   pen  0.278861
    5    red   mug  0.393061
    6  black  ball  0.956869
    7  black   pen  0.217121
    8  black   mug  0.611301
    
    >>> wideframe = longframe.pivot('color', 'item')
    >>> wideframe
              value                    
    item       ball       mug       pen
    color                              
    black  0.956869  0.611301  0.217121
    red    0.674560  0.393061  0.278861
    white  0.657363  0.878001  0.209334
    
    >>> longframe = pd.DataFrame( {'color':['white', 'white', 'white', 'red', 'red', 'red', 'black', 'black', 'black'], 'item':['ball','pen','mug','ball','pen','mug','ball','pen','mug'],'value':np.random.rand(9), 'game':np.arange(9)} )
    >>> wideframe = longframe.pivot('color', 'item')
    >>> wideframe
          game             value                    
    item  ball mug pen      ball       mug       pen
    color                                           
    black    6   8   7  0.122732  0.820089  0.505179
    red      3   5   4  0.314163  0.964050  0.670957
    white    0   2   1  0.219532  0.665007  0.833881
    

    使用pivot()函数指定两个键,第一个参数的列变成索引名,第二个参数的列变成列名。这样数据的可读性就很高了。

    5. 数据转换

    5.1. 删除重复元素

    使用duplicated()可以获取哪些是重复的,使用drop_duplicates()能够删除重复元素。

    >>> frame = pd.DataFrame({'color':['white', 'white', 'red', 'red', 'white'], 'value':[1,2,3,3,2]})
    >>> frame
       color  value
    0  white      1
    1  white      2
    2    red      3
    3    red      3
    4  white      2
    >>> frame.duplicated()
    0    False
    1    False
    2    False
    3     True
    4     True
    dtype: bool
    >>> frame[frame.duplicated()]
       color  value
    3    red      3
    4  white      2
    >>> frame.drop_duplicates()
       color  value
    0  white      1
    1  white      2
    2    red      3
    

    5.2. 映射

    5.2.1. 替换元素replace()

    使用replace()可以替换元素。可以传入一个字典,键为旧元素,值为新元素。

    >>> frame
       color  value
    0  white      1
    1  white      2
    2    red      3
    3    red      3
    4  white      2
    >>> mp = {'white': 'black', 'red': 'yellow'}
    >>> frame.replace(mp)
        color  value
    0   black      1
    1   black      2
    2  yellow      3
    3  yellow      3
    4   black      2
    >>> frame.replace('white', 'black')
       color  value
    0  black      1
    1  black      2
    2    red      3
    3    red      3
    4  black      2
    

    5.2.2. 添加元素map()

    使用map()可以从另外一个数据结构获取元素并将其添加到目标数据结构的列中。

    >>> frame
       color  value
    0  white      1
    1  white      2
    2    red      3
    3    red      3
    4  white      2
    >>> dic = {'white':'pure', 'red':'ignite'}
    
    >>> frame['live'] = frame['color'].map(dic)
    >>> frame
       color  value    live
    0  white      1    pure
    1  white      2    pure
    2    red      3  ignite
    3    red      3  ignite
    4  white      2    pure
    

    5.2.3. 重命名轴索引rename()

    使用rename()转换轴标签。

    >>> frame
       color  value    live
    0  white      1    pure
    1  white      2    pure
    2    red      3  ignite
    3    red      3  ignite
    4  white      2    pure
    >>> newindex = {0:'zero', 3:'three'}
    >>> newcolumns = {'color':'col', 'value':'val'}
    >>> frame.rename(index = newindex, columns = newcolumns)
             col  val    live
    zero   white    1    pure
    1      white    2    pure
    2        red    3  ignite
    three    red    3  ignite
    4      white    2    pure
    
    # 如果要将原来的frame替换掉,设置inplace参数为True
    >>> frame.rename(index = newindex, columns = newcolumns, inplace = True)
    >>> frame
             col  val    live
    zero   white    1    pure
    1      white    2    pure
    2        red    3  ignite
    three    red    3  ignite
    4      white    2    pure
    

    6. 离散化和面元划分

    6.1. cut()

    cut()函数可以将一个数组中的数据切分成几个部分。

    将数据分为几个部分,就称为几个面元。

    cut(数据数组,面元数组)

    >>> array = [3, 60, 43, 100, 52, 36, 37, 0, 80, 1000] # 数组
    >>> bins = [0, 25, 50, 75, 100] # 切割成什么
    >>> cat = pd.cut(array, bins)
    >>> cat # cat是一个Categorical(类别型)类型
    [(0, 25], (50, 75], (25, 50], (75, 100], (50, 75], (25, 50], (25, 50], NaN, (75, 100], NaN]
    Categories (4, interval[int64]): [(0, 25] < (25, 50] < (50, 75] < (75, 100]]
    >>> cat.codes # 数组原来的元素数据第几个面元
    array([ 0,  2,  1,  3,  2,  1,  1, -1,  3, -1], dtype=int8)
    >>> pd.value_counts(cat) # 每个面元有多少个元素
    (25, 50]     3
    (75, 100]    2
    (50, 75]     2
    (0, 25]      1
    dtype: int64
    

    还可以不指定面元的界限,直接传入一个整数参数,cut()会按照指定的数字,将元素划分为相应的几部分。

    >>> pd.cut(array, 5)
    [(-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (-1.0, 200.0], (800.0, 1000.0]]
    Categories (5, interval[float64]): [(-1.0, 200.0] < (200.0, 400.0] < (400.0, 600.0] < (600.0, 800.0] < (800.0, 1000.0]]
    

    6.2. qcut()

    cut()函数划分得到的面元,每个面元的数量不同。而qcut()可以保证每个面元的数量相同,且每个面元的区间大小不等。

    >>> pd.qcut(array, 5)
    [(-0.001, 29.4], (55.2, 84.0], (40.6, 55.2], (84.0, 1000.0], (40.6, 55.2], (29.4, 40.6], (29.4, 40.6], (-0.001, 29.4], (55.2, 84.0], (84.0, 1000.0]]
    Categories (5, interval[float64]): [(-0.001, 29.4] < (29.4, 40.6] < (40.6, 55.2] < (55.2, 84.0] < (84.0, 1000.0]]
    >>> cat = pd.qcut(array, 5)
    >>> pd.value_counts(cat)
    (84.0, 1000.0]    2
    (55.2, 84.0]      2
    (40.6, 55.2]      2
    (29.4, 40.6]      2
    (-0.001, 29.4]    2
    dtype: int64
    

    6.3. 异常值检测和过滤

    使用any()函数可以对每一列应用筛选条件。

    >>> frame = pd.DataFrame(np.random.randn(10, 3))
    >>> frame
              0         1         2
    0 -0.466623 -0.180515 -1.632522
    1  0.928587  1.478555 -1.170217
    2  1.366825 -0.266165  0.307137
    3  1.811664  0.155917 -1.847898
    4 -0.451448  1.668134 -0.584497
    5 -0.819943 -0.028708  1.119363
    6  0.039233 -0.316006 -1.232731
    7 -2.721860  0.369594  0.482038
    8 -0.320213 -0.456954  1.305954
    9 -0.159289 -1.138182  0.452671
    
    >>> frame.describe()
                   0          1          2
    count  10.000000  10.000000  10.000000
    mean   -0.079307   0.128567  -0.280070
    std     1.272859   0.861058   1.155481
    min    -2.721860  -1.138182  -1.847898
    25%    -0.462829  -0.303546  -1.217102
    50%    -0.239751  -0.104611  -0.138680
    75%     0.706248   0.316174   0.474696
    max     1.811664   1.668134   1.305954
    
    >>> (np.abs(frame) > frame.std())
           0      1      2
    0  False  False   True
    1  False   True   True
    2   True  False  False
    3   True  False   True
    4  False   True  False
    5  False  False  False
    6  False  False   True
    7   True  False  False
    8  False  False   True
    9  False   True  False
    
    >>> (np.abs(frame) > frame.std()).any(0) # 参数0和参数1分别是axis参数的值
    0    True
    1    True
    2    True
    
    >>> (np.abs(frame) > frame.std()).any(1)
    0     True
    1     True
    2     True
    3     True
    4     True
    5    False
    6     True
    7     True
    8     True
    9     True
    dtype: bool
        
    >>> frame[(np.abs(frame) > frame.std()).any(1)] # 第五行被筛选掉了
              0         1         2
    0 -0.466623 -0.180515 -1.632522
    1  0.928587  1.478555 -1.170217
    2  1.366825 -0.266165  0.307137
    3  1.811664  0.155917 -1.847898
    4 -0.451448  1.668134 -0.584497
    6  0.039233 -0.316006 -1.232731
    7 -2.721860  0.369594  0.482038
    8 -0.320213 -0.456954  1.305954
    9 -0.159289 -1.138182  0.452671
    

    7. 排序

    使用permutation()函数可以创建一个随机顺序的数组。

    使用take()函数可以采用新的索引次序。

    >>> frame = pd.DataFrame(np.arange(25).reshape(5,5))
    >>> frame
        0   1   2   3   4
    0   0   1   2   3   4
    1   5   6   7   8   9
    2  10  11  12  13  14
    3  15  16  17  18  19
    4  20  21  22  23  24
    >>> order = np.random.permutation(5)
    >>> order
    array([2, 4, 1, 0, 3])
    >>> frame.take(order)
        0   1   2   3   4
    2  10  11  12  13  14
    4  20  21  22  23  24
    1   5   6   7   8   9
    0   0   1   2   3   4
    3  15  16  17  18  19
    
    # 对部分操作
    >>> frame.take([3, 4, 1])
        0   1   2   3   4
    3  15  16  17  18  19
    4  20  21  22  23  24
    1   5   6   7   8   9
    

    随机取样

    >>> len(frame) # frame的行数
    5
    >>> sample = np.random.randint(0, len(frame), size = 2) # 分别是取值下限,取值上限,和取值的个数
    >>> sample
    array([1, 1])
    >>> frame.take(sample)
       0  1  2  3  4
    1  5  6  7  8  9
    1  5  6  7  8  9
    

    8. 字符串处理

    • join()

      '拼接字符'.join(string数组)

    >>> strings = ['a', 'b', 'd', 'e', 'F']
    >>> strings
    ['a', 'b', 'd', 'e', 'F']
    >>> ';'.join(strings)
    'a;b;d;e;F'
    
    • split() 和 strip()

      string.split('切割字符')

      string.strip() 去掉多余的空白字符(包括换行)

    >>> string = '233 ,     546'
    >>> string
    '233 , 	546'
    >>> string.split(',')
    ['233 ', ' 	546']
    
    >>> for s in string.split(','):
    ...   print(s.strip())
    ... 
    233
    546
    
    • find(s) 和 count(s) 和 replace(s1, s2)

      分别是找到子串的下标,子串出现了多少次,将s1替换为s2.

    • 正则表达式

      click here

    9. 数据聚合

    GroupBy 内部机制:SPLIT-APPLY-COMBINE(分组-用函数处理-合并结果)。

    group[list1].groupby(list2)

    list1表示要处理的数据的列名,list2表示根据哪些键(列名)处理。

    >>> frame = pd.DataFrame( {'color': ['red', 'white', 'red', 'green', 'white'], 'object': ['pen', 'pencil', 'mug', 'ruler', 'pen'], 'price': [2, 3, 4, 1, 100]} )
    >>> frame
       color  object  price
    0    red     pen      2
    1  white  pencil      3
    2    red     mug      4
    3  green   ruler      1
    4  white     pen    100
    >>> group = frame['price'].groupby(frame['color']) # 得到一个GroupBy对象
    >>> group.groups
    {'red': Int64Index([0, 2], dtype='int64'), 'green': Int64Index([3], dtype='int64'), 'white': Int64Index([1, 4], dtype='int64')}
    >>> group.mean()
    color
    green     1.0
    red       3.0
    white    51.5
    Name: price, dtype: float64
    >>> group.sum()
    color
    green      1
    red        6
    white    103
    Name: price, dtype: int64
    

    • agg()函数

      还可以对组使用自定义函数,只需要使用agg(函数名)就行了。

    >>> group = frame.groupby(frame['color'])
    >>> def fun(series):
    ...   return series.max() - series.min()
    ... 
    >>> group['price'].agg(fun)
    color
    green     0
    red       2
    white    97
    Name: price, dtype: int64
    
    • transfrom()函数
    >>> frame = pd.DataFrame( {'color':['white', 'red', 'green', 'white', 'green'], 'val1':[5,6,7,8,9], 'val2':[15,16,17,18,19]} )
    >>> frame
       color  val1  val2
    0  white     5    15
    1    red     6    16
    2  green     7    17
    3  white     8    18
    4  green     9    19
    >>> frame.groupby('color').transform(np.sum) # 函数必须是一个聚合函数
       val1  val2
    0    13    33
    1     6    16
    2    16    36
    3    13    33
    4    16    36
    
    • apply()函数

      将键值分类再处理。

    >>> frame['status'] = ['up', 'down', 'up', 'down', 'down']
    >>> frame
       color  val1  val2 status
    0  white     5    15     up
    1    red     6    16   down
    2  green     7    17     up
    3  white     8    18   down
    4  green     9    19   down
    >>> frame.groupby(['color', 'status']).apply(lambda x: x.max())
                  color  val1  val2 status
    color status                          
    green down    green     9    19   down
          up      green     7    17     up
    red   down      red     6    16   down
    white down    white     8    18   down
          up      white     5    15     up
    

  • 相关阅读:
    Java SE 第十一讲(面向对象之封装)续二
    Java SE 第二十六讲 包与导入语句剖析
    Java SE 第三十一,二,三 Java数组剖析,Java数组内存地址解析
    Java SE 第三十四,五,六讲 Array类解析及数组疑难剖析,冒泡排序,交换排序以及快速排序
    Java SE 第三十八,九,四十,四十一,四十二,三四IDE详细介绍,ArrayList源代码深入剖析,L
    java高效的获取指定的精度的double数
    C++ 字符常量
    C++ endl
    C++基本数据类型
    vs2005的treeview简单使用之无限级别菜单建立
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7072966.html
Copyright © 2020-2023  润新知