5 使用 .str 索引
可以使用 []
符號直接按位置進(jìn)行索引兔毙,如果索引超過字符串的長度论衍,結(jié)果將是 NaN
In [96]: s = pd.Series(
....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
....: )
....:
In [97]: s.str[0]
Out[97]:
0 A
1 B
2 C
3 A
4 B
5 <NA>
6 C
7 d
8 c
dtype: string
In [98]: s.str[1]
Out[98]:
0 <NA>
1 <NA>
2 <NA>
3 a
4 a
5 <NA>
6 A
7 o
8 a
dtype: string
6 提取子字符串
6.1 提取第一個匹配項(extract)
在 0.23
版本之前酌予,extract
方法的參數(shù) expand
默認(rèn)為 False
阶牍。當(dāng) expand=False
時笙纤,expand
會根據(jù)正則表達(dá)式模式返回一個 Series
、Index
或 DataFrame
當(dāng) expand=True
時宵蛀,它總是返回一個 DataFrame
,這種方式更加符合用戶的需求县貌,從 0.23.0
版本開始就是默認(rèn)的
extract
方法接受一個至少包含一個捕獲組的正則表達(dá)式
如果是包含多個組的正則表達(dá)式將返回一個 DataFrame
术陶,每個捕獲組是一列
In [99]: pd.Series(
....: ["a1", "b2", "c3"],
....: dtype="string",
....: ).str.extract(r"([ab])(\d)", expand=False)
....:
Out[99]:
0 1
0 a 1
1 b 2
2 <NA> <NA>
未匹配的行會填充 NaN
,可以從混亂的字符串序列中提取出有規(guī)則的信息煤痕。
對于命名分組
In [100]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(
.....: r"(?P<letter>[ab])(?P<digit>\d)", expand=False
.....: )
.....:
Out[100]:
letter digit
0 a 1
1 b 2
2 <NA> <NA>
對于可選的分組
In [101]: pd.Series(
.....: ["a1", "b2", "3"],
.....: dtype="string",
.....: ).str.extract(r"([ab])?(\d)", expand=False)
.....:
Out[101]:
0 1
0 a 1
1 b 2
2 <NA> 3
注意:正則表達(dá)式中的任何捕獲組名稱都將用作列名梧宫,否則將使用捕獲組號
如果 expand=True
,則返回一個 DataFrame
In [102]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=True)
Out[102]:
0
0 1
1 2
2 <NA>
如果 expand=False
摆碉,則返回一個 Series
In [103]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=False)
Out[103]:
0 1
1 2
2 <NA>
dtype: string
對于索引塘匣,如果 expand=True
,且只有一個捕獲組則返回一個只有一列的 DataFrame
In [104]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
In [105]: s
Out[105]:
A11 a1
B22 b2
C33 c3
dtype: string
In [106]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
Out[106]:
letter
0 A
1 B
2 C
此時巷帝,如果 expand=False
將會返回一個 Index
In [107]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
Out[107]: Index(['A', 'B', 'C'], dtype='object', name='letter')
對于索引忌卤,正則表達(dá)式設(shè)置多個分組將返回 DataFrame
In [108]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
Out[108]:
letter 1
0 A 11
1 B 22
2 C 33
如果 expand=False
將會拋出 ValueError
異常
>>> s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
ValueError: only one regex group is supported with Index
6.2 提取所有匹配(extractall)
對于 extract
只返回第一個匹配項
In [109]: s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"], dtype="string")
In [110]: s
Out[110]:
A a1a2
B b1
C c1
dtype: string
In [111]: two_groups = "(?P<letter>[a-z])(?P<digit>[0-9])"
In [112]: s.str.extract(two_groups, expand=True)
Out[112]:
letter digit
A a 1
B b 1
C c 1
與 extract
不同,extractall
方法返回每個匹配項楞泼,其結(jié)果始終是具有 MultiIndex
的 DataFrame
驰徊。
MultiIndex
的最后一級名為 match
,標(biāo)示的是匹配的順序
In [113]: s.str.extractall(two_groups)
Out[113]:
letter digit
match
A 0 a 1
1 a 2
B 0 b 1
C 0 c 1
對于只有一個匹配的 Series
In [114]: s = pd.Series(["a3", "b3", "c2"], dtype="string")
In [115]: s
Out[115]:
0 a3
1 b3
2 c2
dtype: string
extractall(pat).xs(0, level='match')
與 extract(pat)
的結(jié)果一致
In [116]: extract_result = s.str.extract(two_groups, expand=True)
In [117]: extract_result
Out[117]:
letter digit
0 a 3
1 b 3
2 c 2
In [118]: extractall_result = s.str.extractall(two_groups)
In [119]: extractall_result
Out[119]:
letter digit
match
0 0 a 3
1 0 b 3
2 0 c 2
In [120]: extractall_result.xs(0, level="match")
Out[120]:
letter digit
0 a 3
1 b 3
2 c 2
Index
也支持 .str.extractall
现拒,它返回一個 DataFrame
,其結(jié)果與 Series.str
相同望侈。
In [121]: pd.Index(["a1a2", "b1", "c1"]).str.extractall(two_groups)
Out[121]:
letter digit
match
0 0 a 1
1 a 2
1 0 b 1
2 0 c 1
In [122]: pd.Series(["a1a2", "b1", "c1"], dtype="string").str.extractall(two_groups)
Out[122]:
letter digit
match
0 0 a 1
1 a 2
1 0 b 1
2 0 c 1
7 測試字符串匹配與包含
您可以檢查字符串元素中是否包含正則匹配模式
In [123]: pattern = r"[0-9][a-z]"
In [124]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.contains(pattern)
.....:
Out[124]:
0 False
1 False
2 True
3 True
4 True
5 True
dtype: boolean
或者字符串元素是否與模式匹配
In [125]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.match(pattern)
.....:
Out[125]:
0 False
1 False
2 True
3 True
4 False
5 True
dtype: boolean
而在 1.1.0
版本中
In [126]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.fullmatch(pattern)
.....:
Out[126]:
0 False
1 False
2 True
3 True
4 False
5 False
dtype: boolean
注意:
match
印蔬、fullmatch
和 contains
之間的區(qū)別是:
-
fullmatch
:測試整個字符串是否與正則表達(dá)式完全匹配 -
match
:測試字符串的開頭是否與正則表達(dá)式匹配 -
contains
:測試字符串中的任何位置是否存在正則表達(dá)式的匹配
這三個函數(shù)于 re
模塊的 re.fullmatch
、re.match
和 re.search
對應(yīng)
像 match
, fullmatch
, contains
, startswith
和 endswith
有一個額外的 na
參數(shù)脱衙,用于將缺失值替換為 True
或 False
In [127]: s4 = pd.Series(
.....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
.....: )
.....:
In [128]: s4.str.contains("A", na=False)
Out[128]:
0 True
1 False
2 False
3 True
4 False
5 False
6 True
7 False
8 False
dtype: boolean
8 創(chuàng)建指標(biāo)變量
您可以從字符串列中提取指標(biāo)變量侥猬。例如,如果使用 '|'
分隔的字符串
In [129]: s = pd.Series(["a", "a|b", np.nan, "a|c"], dtype="string")
In [130]: s.str.get_dummies(sep="|")
Out[130]:
a b c
0 1 0 0
1 1 1 0
2 0 0 0
3 1 0 1
字符串 Index
也支持 get_dummies
捐韩,它返回一個 MultiIndex
In [131]: idx = pd.Index(["a", "a|b", np.nan, "a|c"])
In [132]: idx.str.get_dummies(sep="|")
Out[132]:
MultiIndex([(1, 0, 0),
(1, 1, 0),
(0, 0, 0),
(1, 0, 1)],
names=['a', 'b', 'c'])