拆分和替换字符串

类似split的方法返回一个列表类型的序列:

  1. In [15]: s2 = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'])
  2. In [16]: s2.str.split('_')
  3. Out[16]:
  4. 0 [a, b, c]
  5. 1 [c, d, e]
  6. 2 NaN
  7. 3 [f, g, h]
  8. dtype: object

切分后的列表中的元素可以通过 get 方法或者 [] 方法进行读取:

  1. In [17]: s2.str.split('_').str.get(1)
  2. Out[17]:
  3. 0 b
  4. 1 d
  5. 2 NaN
  6. 3 g
  7. dtype: object
  8. In [18]: s2.str.split('_').str[1]
  9. Out[18]:
  10. 0 b
  11. 1 d
  12. 2 NaN
  13. 3 g
  14. dtype: object

使用expand方法可以轻易地将这种返回展开为一个数据表.

  1. In [19]: s2.str.split('_', expand=True)
  2. Out[19]:
  3. 0 1 2
  4. 0 a b c
  5. 1 c d e
  6. 2 NaN NaN NaN
  7. 3 f g h

同样,我们也可以限制切分的次数:

  1. In [20]: s2.str.split('_', expand=True, n=1)
  2. Out[20]:
  3. 0 1
  4. 0 a b_c
  5. 1 c d_e
  6. 2 NaN NaN
  7. 3 f g_h

rsplitsplit相似,不同的是,这个切分的方向是反的。即,从字串的尾端向首段切分:

  1. In [21]: s2.str.rsplit('_', expand=True, n=1)
  2. Out[21]:
  3. 0 1
  4. 0 a_b c
  5. 1 c_d e
  6. 2 NaN NaN
  7. 3 f_g h

replace 方法默认使用 正则表达式:

  1. In [22]: s3 = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca',
  2. ....: '', np.nan, 'CABA', 'dog', 'cat'])
  3. ....:
  4. In [23]: s3
  5. Out[23]:
  6. 0 A
  7. 1 B
  8. 2 C
  9. 3 Aaba
  10. 4 Baca
  11. 5
  12. 6 NaN
  13. 7 CABA
  14. 8 dog
  15. 9 cat
  16. dtype: object
  17. In [24]: s3.str.replace('^.a|dog', 'XX-XX ', case=False)
  18. Out[24]:
  19. 0 A
  20. 1 B
  21. 2 C
  22. 3 XX-XX ba
  23. 4 XX-XX ca
  24. 5
  25. 6 NaN
  26. 7 XX-XX BA
  27. 8 XX-XX
  28. 9 XX-XX t
  29. dtype: object

一定要实时记得,是正则表达式,因此要格外小心。例如,因为正则表达式中的‘$’符号,下列代码将会导致一些麻烦:

  1. # Consider the following badly formatted financial data
  2. In [25]: dollars = pd.Series(['12', '-$10', '$10,000'])
  3. # This does what you'd naively expect:
  4. In [26]: dollars.str.replace('$', '')
  5. Out[26]:
  6. 0 12
  7. 1 -10
  8. 2 10,000
  9. dtype: object
  10. # But this doesn't:
  11. In [27]: dollars.str.replace('-$', '-')
  12. Out[27]:
  13. 0 12
  14. 1 -$10
  15. 2 $10,000
  16. dtype: object
  17. # We need to escape the special character (for >1 len patterns)
  18. In [28]: dollars.str.replace(r'-\$', '-')
  19. Out[28]:
  20. 0 12
  21. 1 -10
  22. 2 $10,000
  23. dtype: object

New in version 0.23.0.

如果你只是向单纯地替换字符((等价于python中的str.replace()), ,你可以将可选参数 regex 设置为 False,而不是傻傻地转义所有符号。这种情况下,patrepl 就都将作为普通字符对待:

  1. # These lines are equivalent
  2. In [29]: dollars.str.replace(r'-\$', '-')
  3. Out[29]:
  4. 0 12
  5. 1 -10
  6. 2 $10,000
  7. dtype: object
  8. In [30]: dollars.str.replace('-$', '-', regex=False)
  9. Out[30]:
  10. 0 12
  11. 1 -10
  12. 2 $10,000
  13. dtype: object

New in version 0.20.0.

replace 方法也可以传入一个可调用对象作为替换值。它针对每一个 pat 通过 re.sub()来调用。可调用对象应只具有一个形参(一个正则表达式对象)并且返回一个字符串。

  1. # Reverse every lowercase alphabetic word
  2. In [31]: pat = r'[a-z]+'
  3. In [32]: repl = lambda m: m.group(0)[::-1]
  4. In [33]: pd.Series(['foo 123', 'bar baz', np.nan]).str.replace(pat, repl)
  5. Out[33]:
  6. 0 oof 123
  7. 1 rab zab
  8. 2 NaN
  9. dtype: object
  10. # Using regex groups
  11. In [34]: pat = r"(?P<one>\w+) (?P<two>\w+) (?P<three>\w+)"
  12. In [35]: repl = lambda m: m.group('two').swapcase()
  13. In [36]: pd.Series(['Foo Bar Baz', np.nan]).str.replace(pat, repl)
  14. Out[36]:
  15. 0 bAR
  16. 1 NaN
  17. dtype: object

New in version 0.20.0.

replace 方法也可以接受一个来自 re.compile() 编译过的正则表达式对象,来做为表达式。所有的标记都应该被包含在这个已经编译好的正则表达式对象中。

  1. In [37]: import re
  2. In [38]: regex_pat = re.compile(r'^.a|dog', flags=re.IGNORECASE)
  3. In [39]: s3.str.replace(regex_pat, 'XX-XX ')
  4. Out[39]:
  5. 0 A
  6. 1 B
  7. 2 C
  8. 3 XX-XX ba
  9. 4 XX-XX ca
  10. 5
  11. 6 NaN
  12. 7 XX-XX BA
  13. 8 XX-XX
  14. 9 XX-XX t
  15. dtype: object

如果在已经使用编译的正则对象中继续传入flags 参数,并进行替换,将会导致ValueError.

  1. In [40]: s3.str.replace(regex_pat, 'XX-XX ', flags=re.IGNORECASE)
  2. ---------------------------------------------------------------------------
  3. ValueError: case and flags cannot be set when pat is a compiled regex