Pandas的clip和replace正則替換

之前已發佈

DataFrame的apply和applymap方法以及Series中的map方法

利用Pandas進行數據轉換(map、replace、rename、duplicated等函數的使用)

本文再補充更多的關於replace函數的用法,以及沒有提到的clip函數。


clip函數

clip用於對超過或者低於某些值的數進行截斷。

準備示例數據:

>>> data = {'col_0': [9, -3, 0, -1, 5], 'col_1': [-2, -7, 6, 8, -5]}
>>> df = pd.DataFrame(data)
>>> df
   col_0  col_1
0      9     -2
1     -3     -7
2      0      6
3     -1      8
4      5     -5

Clips對超過或者低於指定閾值的數據將替換爲指定閾值:

>>> df.clip(-4, 6)
   col_0  col_1
0      6     -2
1     -3     -4
2      0      6
3     -1      6
4      5     -4

傳入兩個Series,並指定axis=0則可以對每一行數據都用指定的範圍進行截斷:

>>> df
   col_0  col_1
0      9     -2
1     -3     -7
2      0      6
3     -1      8
4      5     -5


>>> t1 = pd.Series([2, -4, -1, 6, 3])
>>> t2 = pd.Series([6, 0, 3, 9, 8])
>>> df.clip(t1, t2, axis=0)
   col_0  col_1
0      6      2
1     -3     -4
2      0      3
3      6      8
4      5      3

比如對於第一行數據9 和 -2被截斷在[2,6]的範圍,大於6取6,小於2取2.



DataFrame或Series的replace方法

對指定的單個標量值進行替換:

>>> s = pd.Series([0, 1, 2, 3, 4])
>>> s.replace(0, 5)
0    5
1    1
2    2
3    3
4    4
dtype: int64
>>> df = pd.DataFrame({'A': [0, 1, 2, 3, 4],
...                    'B': [5, 6, 7, 8, 9],
...                    'C': ['a', 'b', 'c', 'd', 'e']})
>>> df.replace(0, 5)
   A  B  C
0  5  5  a
1  1  6  b
2  2  7  c
3  3  8  d
4  4  9  e

將指定的列表內的所有標量值都替換爲指定值:

>>> df.replace([0, 1, 2, 3], 4)
   A  B  C
0  4  5  a
1  4  6  b
2  4  7  c
3  4  8  d
4  4  9  e

傳入兩個長度一致的列表,則有一一對應的替換關係:

>>> df.replace([0, 1, 2, 3], [4, 3, 2, 1])
   A  B  C
0  4  5  a
1  3  6  b
2  2  7  c
3  1  8  d
4  4  9  e

其中0替換爲4,1替換爲3,2依然替換爲2,替換爲1。

對指定標量值使用向上填充的方式進行替換:

>>> s.replace([1, 2], method='bfill')
0    0
1    3
2    3
3    3
4    4
dtype: int64

原本的1和2都被下面3向上填充。

使用單個普通字典進行替換,效果與傳入兩個長度一致的列表一致:

>>> df.replace({0: 10, 1: 100})
     A  B  C
0   10  5  a
1  100  6  b
2    2  7  c
3    3  8  d
4    4  9  e

傳入兩個參數,則字典中的鍵爲要被替換的鍵,值爲要被替換的值,第二個參數爲替換後的值:

>>> df.replace({'A': 0, 'B': 5}, 100)
     A    B  C
0  100  100  a
1    1    6  b
2    2    7  c
3    3    8  d
4    4    9  e

還可以傳入嵌套字典,外層字典的鍵表示要替換的列,內層字典的鍵值表示被替換的值和替換後的值:

>>> df.replace({'A': {0: 100, 4: 400}})
     A  B  C
0  100  5  a
1    1  6  b
2    2  7  c
3    3  8  d
4  400  9  e

指定參數regex=True即可實現正則表達式替換。

>>> df = pd.DataFrame({'A': ['bat', 'foo', 'bait'],
...                    'B': ['abc', 'bar', 'xyz']})
>>> df.replace(to_replace=r'^ba.$', value='new', regex=True)
      A    B
0   new  abc
1   foo  new
2  bait  xyz

下面將A列符合^ba.$規則的都替換爲new

>>> df.replace({'A': r'^ba.$'}, {'A': 'new'}, regex=True)
      A    B
0   new  abc
1   foo  bar
2  bait  xyz

也可以直接向regex參數傳遞替換規則:

>>> df.replace(regex=r'^ba.$', value='new')
      A    B
0   new  abc
1   foo  new
2  bait  xyz
>>> df.replace(regex={r'^ba.$': 'new', 'foo': 'xyz'})
      A    B
0   new  abc
1   xyz  new
2  bait  xyz
>>> df.replace(regex=[r'^ba.$', 'foo'], value='new')
      A    B
0   new  abc
1   new  new
2  bait  xyz

Tips:傳入一個字典和傳入兩個替換參數的默認行爲不一樣。

s = pd.Series([10, 'a', 'a', 'b', 'a'])

s.replace({'a': None}) 

相當於:

s.replace(to_replace={'a': None}, value=None, method=None)

>>> s.replace({'a': None})
0      10
1    None
2    None
3       b
4    None
dtype: object

s.replace('a', None)

相當於:

s.replace(to_replace='a', value=None, method='pad')

>>> s.replace('a', None)
0    10
1    10
2    10
3     b
4     b
dtype: object


Series.str.replace

Series.str.replace默認支持正則表達式:

>>> se1 = pd.Series(['foo', 'fuz', np.nan])
>>> se1.str.replace('f.', 'ba')
0    bao
1    baz
2    NaN
dtype: object

也可以設置參數regex=False關閉:

>>> se1.str.replace('f.', 'ba', regex=False)
0    bao
1    fuz
2    NaN
dtype: object

當給第二個參數repl傳遞一個函數時,該函數接收一個正則表達式對象,返回一個字符串作爲替換結果:

>>> def f(arg):
    print(arg, type(arg))
    return arg.group(0)


>>> se1.str.replace('f.', f)
<re.Match object; span=(0, 2), match='fo'> <class 're.Match'>
<re.Match object; span=(0, 2), match='fu'> <class 're.Match'>
0    foo
1    fuz
2    NaN
dtype: object

根據此特性實現將每個小寫單詞都倒序:

>>> repl = lambda m: m.group(0)[::-1]
>>> se2 = pd.Series(['foo 123', 'bar baz', np.nan])
>>> se2.str.replace(r'[a-z]+', repl)
0    oof 123
1    rab zab
2        NaN
dtype: object

使用正則表達式的組(提取第二組並交換大小寫):

pat = r"(?P<one>\w+) (?P<two>\w+) (?P<three>\w+)"
repl = lambda m: m.group('two').swapcase()
pd.Series(['One Two Three', 'Foo Bar Baz']).str.replace(pat, repl)
0    tWO
1    bAR
dtype: object

還可以使用python編譯好的正則表達式對象便於複用:

import re
regex_pat = re.compile(r'FUZ', flags=re.IGNORECASE)
pd.Series(['foo', 'fuz', np.nan]).str.replace(regex_pat, 'bar')
0    foo
1    bar
2    NaN
dtype: object
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章