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 , \t546'
>>> string.split(',')
['233 ', ' \t546']

>>> 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM