Pandas 中文参考指南
Working with text data
Text data types
在 pandas 中存储文本数据有两种方式:
-
object -dtype NumPy array.
-
StringDtype extension type.
我们建议使用 StringDtype 存储文本数据。
在 pandas 1.0 之前,object dtype 是唯一的选择。由于许多原因,这是不幸的:
-
您可能会意外地将字符串和非字符串混合存储在 object dtype 数组中。最好使用专门的 dtype。
-
object dtype 会破坏诸如 DataFrame.select_dtypes() 之类的特定于 dtype 的操作。没有明确的方法来仅选择文本,同时排除非文本但仍为 object-dtype 的列。
-
阅读代码时,object dtype 的内容不如 'string' 清晰。
目前,object dtype 字符串数组和 arrays.StringArray 的性能大致相同。我们希望未来的增强功能能够显著提高性能,并降低 StringArray 的内存开销。
警告
目前 StringArray 被认为是试验性的。API 的实现和部分内容可能会在不发出警告的情况下发生变化。
为了向后兼容,object dtype 仍然是我们推断字符串列表的默认类型
In [1]: pd.Series(["a", "b", "c"])
Out[1]:
0 a
1 b
2 c
dtype: object
要显式请求 string dtype,请指定 dtype
In [2]: pd.Series(["a", "b", "c"], dtype="string")
Out[2]:
0 a
1 b
2 c
dtype: string
In [3]: pd.Series(["a", "b", "c"], dtype=pd.StringDtype())
Out[3]:
0 a
1 b
2 c
dtype: string
或在创建 Series 或 DataFrame 后指定 astype
In [4]: s = pd.Series(["a", "b", "c"])
In [5]: s
Out[5]:
0 a
1 b
2 c
dtype: object
In [6]: s.astype("string")
Out[6]:
0 a
1 b
2 c
dtype: string
您还可以将 StringDtype/"string" 用作非字符串数据的 dtype,它将转换为 string dtype:
In [7]: s = pd.Series(["a", 2, np.nan], dtype="string")
In [8]: s
Out[8]:
0 a
1 2
2 <NA>
dtype: string
In [9]: type(s[1])
Out[9]: str
或从现有的 pandas 数据进行转换:
In [10]: s1 = pd.Series([1, 2, np.nan], dtype="Int64")
In [11]: s1
Out[11]:
0 1
1 2
2 <NA>
dtype: Int64
In [12]: s2 = s1.astype("string")
In [13]: s2
Out[13]:
0 1
1 2
2 <NA>
dtype: string
In [14]: type(s2[0])
Out[14]: str
Behavior differences
以下是 StringDtype 对象的行为与 object dtype 不同的位置
-
对于 StringDtype,返回数字输出的 string accessor methods 将始终返回可为 null 的整数 dtype,而不是 int 或 float dtype,具体取决于 NA 值的存在。返回布尔输出的方法将返回一个可为 null 的布尔 dtype。
In [15]: s = pd.Series(["a", None, "b"], dtype="string")
In [16]: s
Out[16]:
0 a
1 <NA>
2 b
dtype: string
In [17]: s.str.count("a")
Out[17]:
0 1
1 <NA>
2 0
dtype: Int64
In [18]: s.dropna().str.count("a")
Out[18]:
0 1
2 0
dtype: Int64
-
这两个输出都是 Int64 dtype。将此与 object-dtype 进行比较
In [19]: s2 = pd.Series(["a", None, "b"], dtype="object")
In [20]: s2.str.count("a")
Out[20]:
0 1.0
1 NaN
2 0.0
dtype: float64
In [21]: s2.dropna().str.count("a")
Out[21]:
0 1
2 0
dtype: int64
-
如果存在 NA 值,则输出 dtype 为 float64。返回布尔值的函数类似。
In [22]: s.str.isdigit()
Out[22]:
0 False
1 <NA>
2 False
dtype: boolean
In [23]: s.str.match("a")
Out[23]:
0 True
1 <NA>
2 False
dtype: boolean
-
某些字符串函数,例如 Series.str.decode() 在 StringArray 中不可用,因为 StringArray 只保存字符串,不保存字节。
-
在比较操作中,由 StringArray 支持的 arrays.StringArray 和 Series 将返回一个具有 BooleanDtype 的对象,而不是 bool dtype 对象。StringArray 中的缺失值将在比较操作中传播,而不是总是比较不等于 numpy.nan。
本档的其他全部内容同样适用于 string 和 object 数据类型。
String methods
Series 和 Index 配备了一组字符串处理方法,使用时可轻松对数组的各个元素进行运算。最重要的是,这些方法自动排除了缺失/NA 的值。通过 str 属性访问这些方法,其名称通常与等效的(标量)内置字符串方法相符:
In [24]: s = pd.Series(
....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
....: )
....:
In [25]: s.str.lower()
Out[25]:
0 a
1 b
2 c
3 aaba
4 baca
5 <NA>
6 caba
7 dog
8 cat
dtype: string
In [26]: s.str.upper()
Out[26]:
0 A
1 B
2 C
3 AABA
4 BACA
5 <NA>
6 CABA
7 DOG
8 CAT
dtype: string
In [27]: s.str.len()
Out[27]:
0 1
1 1
2 1
3 4
4 4
5 <NA>
6 4
7 3
8 3
dtype: Int64
In [28]: idx = pd.Index([" jack", "jill ", " jesse ", "frank"])
In [29]: idx.str.strip()
Out[29]: Index(['jack', 'jill', 'jesse', 'frank'], dtype='object')
In [30]: idx.str.lstrip()
Out[30]: Index(['jack', 'jill ', 'jesse ', 'frank'], dtype='object')
In [31]: idx.str.rstrip()
Out[31]: Index([' jack', 'jill', ' jesse', 'frank'], dtype='object')
Index 上的字符串方法对于清理或转换 DataFrame 列特别有用。例如,您可能有一些包含前导或尾随空格的列:
In [32]: df = pd.DataFrame(
....: np.random.randn(3, 2), columns=[" Column A ", " Column B "], index=range(3)
....: )
....:
In [33]: df
Out[33]:
Column A Column B
0 0.469112 -0.282863
1 -1.509059 -1.135632
2 1.212112 -0.173215
由于 df.columns 是一个索引对象,因此我们可以使用访问器 .str
In [34]: df.columns.str.strip()
Out[34]: Index(['Column A', 'Column B'], dtype='object')
In [35]: df.columns.str.lower()
Out[35]: Index([' column a ', ' column b '], dtype='object')
然后,可以使用这些字符串方法来按需要清理列。此处,我们正在删除前导和尾随空格,小写所有名称,并将所有剩余的空格替换为下划线:
In [36]: df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
In [37]: df
Out[37]:
column_a column_b
0 0.469112 -0.282863
1 -1.509059 -1.135632
2 1.212112 -0.173215
如果您拥有大量元素重复的 Series(也就是说,Series 中的唯一元素数量远小于 Series 的长度),那么将原始 Series 转换为 category 类型并使用 .str.<method> 或 .dt.<property> 可能会更快。性能差异源于这样的事实:对于 Series 类型为 category 的类型,字符串运算是在 .categories 上进行的,而不是在 Series 的每个元素上进行的。 |
请注意,与字符串类型(例如,如果您无法将字符串彼此相加:s + " " + s 将不起作用(如果 s 是 Series 类型为 category 的对象))的 Series 相比,类型为 category 的 Series 存在一些限制。此外,针对 list 类型元素进行运算的 .str 方法在该 Series 中不可用。
警告
Series 类型是推断出来的,允许的类型(例如字符串)。
一般来说,.str 访问器的目的是仅处理字符串。在极少数例外情况下,不支持其他用法,并且可能在稍后禁用这些用法。
Splitting and replacing strings
split 等方法会返回一个列表系列:
In [38]: s2 = pd.Series(["a_b_c", "c_d_e", np.nan, "f_g_h"], dtype="string")
In [39]: s2.str.split("_")
Out[39]:
0 [a, b, c]
1 [c, d, e]
2 <NA>
3 [f, g, h]
dtype: object
可以使用 get 或 [] 表示法访问分割列表中的元素:
In [40]: s2.str.split("_").str.get(1)
Out[40]:
0 b
1 d
2 <NA>
3 g
dtype: object
In [41]: s2.str.split("_").str[1]
Out[41]:
0 b
1 d
2 <NA>
3 g
dtype: object
使用 expand 可以轻松地展开为返回 DataFrame。
In [42]: s2.str.split("_", expand=True)
Out[42]:
0 1 2
0 a b c
1 c d e
2 <NA> <NA> <NA>
3 f g h
当原始 Series 有 StringDtype 时,输出列也全部为 StringDtype。
还可以限制拆分数量:
In [43]: s2.str.split("_", expand=True, n=1)
Out[43]:
0 1
0 a b_c
1 c d_e
2 <NA> <NA>
3 f g_h
rsplit 与 split 类似,但它以相反的方向工作,即从字符串的末尾到字符串的开头:
In [44]: s2.str.rsplit("_", expand=True, n=1)
Out[44]:
0 1
0 a_b c
1 c_d e
2 <NA> <NA>
3 f_g h
replace 可选择使用 regular expressions:
In [45]: s3 = pd.Series(
....: ["A", "B", "C", "Aaba", "Baca", "", np.nan, "CABA", "dog", "cat"],
....: dtype="string",
....: )
....:
In [46]: s3
Out[46]:
0 A
1 B
2 C
3 Aaba
4 Baca
5
6 <NA>
7 CABA
8 dog
9 cat
dtype: string
In [47]: s3.str.replace("^.a|dog", "XX-XX ", case=False, regex=True)
Out[47]:
0 A
1 B
2 C
3 XX-XX ba
4 XX-XX ca
5
6 <NA>
7 XX-XX BA
8 XX-XX
9 XX-XX t
dtype: string
此功能在 2.0 版中已更改。
使用 regex=True 的单字符模式也将被视为正则表达式:
In [48]: s4 = pd.Series(["a.b", ".", "b", np.nan, ""], dtype="string")
In [49]: s4
Out[49]:
0 a.b
1 .
2 b
3 <NA>
4
dtype: string
In [50]: s4.str.replace(".", "a", regex=True)
Out[50]:
0 aaa
1 a
2 a
3 <NA>
4
dtype: string
如果您需要对字符串进行文本替换(相当于 str.replace()),则可以将可选 regex 参数设置为 False,而不是转义每个字符。在这种情况下,pat 和 repl 都必须是字符串:
In [51]: dollars = pd.Series(["12", "-$10", "$10,000"], dtype="string")
# These lines are equivalent
In [52]: dollars.str.replace(r"-\$", "-", regex=True)
Out[52]:
0 12
1 -10
2 $10,000
dtype: string
In [53]: dollars.str.replace("-$", "-", regex=False)
Out[53]:
0 12
1 -10
2 $10,000
dtype: string
replace 方法还可以将可调用内容用作替换。通过 re.sub() 在每个 pat 上进行调用。可调用内容应期望一个位置参数(正则表达式对象),并返回字符串。
# Reverse every lowercase alphabetic word
In [54]: pat = r"[a-z]+"
In [55]: def repl(m):
....: return m.group(0)[::-1]
....:
In [56]: pd.Series(["foo 123", "bar baz", np.nan], dtype="string").str.replace(
....: pat, repl, regex=True
....: )
....:
Out[56]:
0 oof 123
1 rab zab
2 <NA>
dtype: string
# Using regex groups
In [57]: pat = r"(?P<one>\w+) (?P<two>\w+) (?P<three>\w+)"
In [58]: def repl(m):
....: return m.group("two").swapcase()
....:
In [59]: pd.Series(["Foo Bar Baz", np.nan], dtype="string").str.replace(
....: pat, repl, regex=True
....: )
....:
Out[59]:
0 bAR
1 <NA>
dtype: string
replace 方法还接受编译好的正则表达式对象,作为 re.compile() 中的模式。所有标志都应包含在编译好的正则表达式对象中。
In [60]: import re
In [61]: regex_pat = re.compile(r"^.a|dog", flags=re.IGNORECASE)
In [62]: s3.str.replace(regex_pat, "XX-XX ", regex=True)
Out[62]:
0 A
1 B
2 C
3 XX-XX ba
4 XX-XX ca
5
6 <NA>
7 XX-XX BA
8 XX-XX
9 XX-XX t
dtype: string
当使用编译好的正则表达式对象调用 replace 时,包含 flags 参数会引发 ValueError。
In [63]: s3.str.replace(regex_pat, 'XX-XX ', flags=re.IGNORECASE)
---------------------------------------------------------------------------
ValueError: case and flags cannot be set when pat is a compiled regex
removeprefix 和 removesuffix 与 Python 3.9 中添加的 str.removeprefix 和 str.removesuffix 具有相同的效果 < https://docs.python.org/3/library/stdtypes.html#str.removeprefix>`__:
1.4.0 版中的新增功能。
In [64]: s = pd.Series(["str_foo", "str_bar", "no_prefix"])
In [65]: s.str.removeprefix("str_")
Out[65]:
0 foo
1 bar
2 no_prefix
dtype: object
In [66]: s = pd.Series(["foo_str", "bar_str", "no_suffix"])
In [67]: s.str.removesuffix("_str")
Out[67]:
0 foo
1 bar
2 no_suffix
dtype: object
Concatenation
有多种方法可以级联 Series 或 Index,通过本身或其他内容与自身或其他人进行级联,所有内容分别都基于 cat() 和 Index.str.cat。
Concatenating a single Series into a string
Series(或 Index)的内容可以进行级联:
In [68]: s = pd.Series(["a", "b", "c", "d"], dtype="string")
In [69]: s.str.cat(sep=",")
Out[69]: 'a,b,c,d'
如果没有指定,分隔符的关键字 sep 默认为空字符串 sep='':
In [70]: s.str.cat()
Out[70]: 'abcd'
默认情况下,将忽略缺失值。通过使用 na_rep,可以为其提供一个表示形式:
In [71]: t = pd.Series(["a", "b", np.nan, "d"], dtype="string")
In [72]: t.str.cat(sep=",")
Out[72]: 'a,b,d'
In [73]: t.str.cat(sep=",", na_rep="-")
Out[73]: 'a,b,-,d'
Concatenating a Series and something list-like into a Series
如果 Series(或 Index)的长度一致,则 cat() 的第一个参数可以是列表状对象。
In [74]: s.str.cat(["A", "B", "C", "D"])
Out[74]:
0 aA
1 bB
2 cC
3 dD
dtype: string
两侧的缺失值同样会导致结果中的缺失值,除非指定了 na_rep:
In [75]: s.str.cat(t)
Out[75]:
0 aa
1 bb
2 <NA>
3 dd
dtype: string
In [76]: s.str.cat(t, na_rep="-")
Out[76]:
0 aa
1 bb
2 c-
3 dd
dtype: string
Concatenating a Series and something array-like into a Series
参数 others 还可能是二维的。在这种情况下,行数必须与 Series(或 Index)的长度一致。
In [77]: d = pd.concat([t, s], axis=1)
In [78]: s
Out[78]:
0 a
1 b
2 c
3 d
dtype: string
In [79]: d
Out[79]:
0 1
0 a a
1 b b
2 <NA> c
3 d d
In [80]: s.str.cat(d, na_rep="-")
Out[80]:
0 aaa
1 bbb
2 c-c
3 ddd
dtype: string
Concatenating a Series and an indexed object into a Series, with alignment
对于使用 Series 或 DataFrame 的级联,可以通过设置 join 关键词在级联之前对索引进行对齐。
In [81]: u = pd.Series(["b", "d", "a", "c"], index=[1, 3, 0, 2], dtype="string")
In [82]: s
Out[82]:
0 a
1 b
2 c
3 d
dtype: string
In [83]: u
Out[83]:
1 b
3 d
0 a
2 c
dtype: string
In [84]: s.str.cat(u)
Out[84]:
0 aa
1 bb
2 cc
3 dd
dtype: string
In [85]: s.str.cat(u, join="left")
Out[85]:
0 aa
1 bb
2 cc
3 dd
dtype: string
join 的常见选项可用('left', 'outer', 'inner', 'right' 之一)。尤其是,对齐还意味着不同的长度不再需要一致。
In [86]: v = pd.Series(["z", "a", "b", "d", "e"], index=[-1, 0, 1, 3, 4], dtype="string")
In [87]: s
Out[87]:
0 a
1 b
2 c
3 d
dtype: string
In [88]: v
Out[88]:
-1 z
0 a
1 b
3 d
4 e
dtype: string
In [89]: s.str.cat(v, join="left", na_rep="-")
Out[89]:
0 aa
1 bb
2 c-
3 dd
dtype: string
In [90]: s.str.cat(v, join="outer", na_rep="-")
Out[90]:
-1 -z
0 aa
1 bb
2 c-
3 dd
4 -e
dtype: string
使用 others 为 DataFrame 时,可以使用相同的对齐。
In [91]: f = d.loc[[3, 2, 1, 0], :]
In [92]: s
Out[92]:
0 a
1 b
2 c
3 d
dtype: string
In [93]: f
Out[93]:
0 1
3 d d
2 <NA> c
1 b b
0 a a
In [94]: s.str.cat(f, join="left", na_rep="-")
Out[94]:
0 aaa
1 bbb
2 c-c
3 ddd
dtype: string
Concatenating a Series and many objects into a Series
几个类似数组的项目(具体来说:Series、Index 和 np.ndarray 的一维变量)可以组合在类似列表的容器中(包括迭代器、dict 视图等)。
In [95]: s
Out[95]:
0 a
1 b
2 c
3 d
dtype: string
In [96]: u
Out[96]:
1 b
3 d
0 a
2 c
dtype: string
In [97]: s.str.cat([u, u.to_numpy()], join="left")
Out[97]:
0 aab
1 bbd
2 cca
3 ddc
dtype: string
在给定类似列表中没有索引的所有元素(例如 np.ndarray)的长度,必须与 Series(或 Index)一致,但 Series 和 Index 可以有任意长度(只要未禁用 join=None 对齐):
In [98]: v
Out[98]:
-1 z
0 a
1 b
3 d
4 e
dtype: string
In [99]: s.str.cat([v, u, u.to_numpy()], join="outer", na_rep="-")
Out[99]:
-1 -z--
0 aaab
1 bbbd
2 c-ca
3 dddc
4 -e--
dtype: string
如果对包含不同索引的 others 的类似列表,使用 join='right',这些索引的并集将被用作最终级联的基础:
In [100]: u.loc[[3]]
Out[100]:
3 d
dtype: string
In [101]: v.loc[[-1, 0]]
Out[101]:
-1 z
0 a
dtype: string
In [102]: s.str.cat([u.loc[[3]], v.loc[[-1, 0]]], join="right", na_rep="-")
Out[102]:
3 dd-
-1 --z
0 a-a
dtype: string
Indexing with .str
يمكنك استخدام ترميز [] للفهرسة المباشرة لمواقع المواضع. إذا فهرست بعد نهاية السلسلة، فستكون النتيجة NaN.
In [103]: s = pd.Series(
.....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
.....: )
.....:
In [104]: s.str[0]
Out[104]:
0 A
1 B
2 C
3 A
4 B
5 <NA>
6 C
7 d
8 c
dtype: string
In [105]: s.str[1]
Out[105]:
0 <NA>
1 <NA>
2 <NA>
3 a
4 a
5 <NA>
6 A
7 o
8 a
dtype: string
Extracting substrings
Extract first match in each subject (extract)
تتقبّل طريقة extract مجموعة التقاط واحدة على الأقل باستخدام regular expression.
提取具有多个组的正则表达式将返回一个 DataFrame,每个组一列。
In [106]: pd.Series(
.....: ["a1", "b2", "c3"],
.....: dtype="string",
.....: ).str.extract(r"([ab])(\d)", expand=False)
.....:
Out[106]:
0 1
0 a 1
1 b 2
2 <NA> <NA>
不匹配的元素返回一行为 NaN 填充的行。因此,一系列杂乱的字符串可以“转换为”经过清理或更为实用的字符串的类似索引的 Series 或 DataFrame,而无需 get() 来访问元组或 re.match 对象。即使没有找到匹配项并且结果只包含 NaN,结果的类型始终是对象。
如下的命名组
In [107]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(
.....: r"(?P<letter>[ab])(?P<digit>\d)", expand=False
.....: )
.....:
Out[107]:
letter digit
0 a 1
1 b 2
2 <NA> <NA>
以及如下的可选组
In [108]: pd.Series(
.....: ["a1", "b2", "3"],
.....: dtype="string",
.....: ).str.extract(r"([ab])?(\d)", expand=False)
.....:
Out[108]:
0 1
0 a 1
1 b 2
2 <NA> 3
也可以使用。请注意,正则表达式中的任何捕获组名称都将用于列名称;否则将使用捕获组编号。
提取具有一个组的正则表达式将返回一个 DataFrame,如果 expand=True 的话,则为一列。
In [109]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=True)
Out[109]:
0
0 1
1 2
2 <NA>
如果 expand=False 的话,它将返回一个 Series。
In [110]: pd.Series(["a1", "b2", "c3"], dtype="string").str.extract(r"[ab](\d)", expand=False)
Out[110]:
0 1
1 2
2 <NA>
dtype: string
对具有恰好一个捕获组的 regex 调用 Index 将返回一个 DataFrame,如果 expand=True 的话,则为一列。
In [111]: s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
In [112]: s
Out[112]:
A11 a1
B22 b2
C33 c3
dtype: string
In [113]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=True)
Out[113]:
letter
0 A
1 B
2 C
如果 expand=False 的话,它将返回一个 Index。
In [114]: s.index.str.extract("(?P<letter>[a-zA-Z])", expand=False)
Out[114]: Index(['A', 'B', 'C'], dtype='object', name='letter')
对具有多个捕获组的 regex 调用 Index 将返回一个 DataFrame,如果 expand=True 的话。
In [115]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=True)
Out[115]:
letter 1
0 A 11
1 B 22
2 C 33
如果 expand=False 的话,它将引发 ValueError。
In [116]: s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[116], line 1
----> 1 s.index.str.extract("(?P<letter>[a-zA-Z])([0-9]+)", expand=False)
File ~/work/pandas/pandas/pandas/core/strings/accessor.py:137, in forbid_nonstring_types.<locals>._forbid_nonstring_types.<locals>.wrapper(self, *args, **kwargs)
132 msg = (
133 f"Cannot use .str.{func_name} with values of "
134 f"inferred dtype '{self._inferred_dtype}'."
135 )
136 raise TypeError(msg)
--> 137 return func(self, *args, **kwargs)
File ~/work/pandas/pandas/pandas/core/strings/accessor.py:2743, in StringMethods.extract(self, pat, flags, expand)
2740 raise ValueError("pattern contains no capture groups")
2742 if not expand and regex.groups > 1 and isinstance(self._data, ABCIndex):
-> 2743 raise ValueError("only one regex group is supported with Index")
2745 obj = self._data
2746 result_dtype = _result_dtype(obj)
ValueError: only one regex group is supported with Index
下表总结了 extract(expand=False)(第一列中的输入主题,第一行中 regex 中的组数)的行为
1 组
>1 组
Index
Index
ValueError
序列
序列
DataFrame
Extract all matches in each subject (extractall)
与 extract(仅返回第一个匹配项)不同,
In [117]: s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"], dtype="string")
In [118]: s
Out[118]:
A a1a2
B b1
C c1
dtype: string
In [119]: two_groups = "(?P<letter>[a-z])(?P<digit>[0-9])"
In [120]: s.str.extract(two_groups, expand=True)
Out[120]:
letter digit
A a 1
B b 1
C c 1
extractall 方法返回每个匹配项。extractall 的结果始终是其行上带有 MultiIndex 的 DataFrame。MultiIndex 的最后一层被命名为 match,并指示主体中的顺序。
In [121]: s.str.extractall(two_groups)
Out[121]:
letter digit
match
A 0 a 1
1 a 2
B 0 b 1
C 0 c 1
当 Series 中的每个主题字符串恰好有一个匹配项时,
In [122]: s = pd.Series(["a3", "b3", "c2"], dtype="string")
In [123]: s
Out[123]:
0 a3
1 b3
2 c2
dtype: string
然后 extractall(pat).xs(0, level='match') 会给出一个和 extract(pat) 相同的结果。
In [124]: extract_result = s.str.extract(two_groups, expand=True)
In [125]: extract_result
Out[125]:
letter digit
0 a 3
1 b 3
2 c 2
In [126]: extractall_result = s.str.extractall(two_groups)
In [127]: extractall_result
Out[127]:
letter digit
match
0 0 a 3
1 0 b 3
2 0 c 2
In [128]: extractall_result.xs(0, level="match")
Out[128]:
letter digit
0 a 3
1 b 3
2 c 2
Index 也支持 .str.extractall。它返回一个 DataFrame,其结果与带默认索引(从 0 开始)的 Series.str.extractall 相同。
In [129]: pd.Index(["a1a2", "b1", "c1"]).str.extractall(two_groups)
Out[129]:
letter digit
match
0 0 a 1
1 a 2
1 0 b 1
2 0 c 1
In [130]: pd.Series(["a1a2", "b1", "c1"], dtype="string").str.extractall(two_groups)
Out[130]:
letter digit
match
0 0 a 1
1 a 2
1 0 b 1
2 0 c 1
Testing for strings that match or contain a pattern
您可以检查元素是否包含模式:
In [131]: pattern = r"[0-9][a-z]"
In [132]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.contains(pattern)
.....:
Out[132]:
0 False
1 False
2 True
3 True
4 True
5 True
dtype: boolean
或者元素是否匹配模式:
In [133]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.match(pattern)
.....:
Out[133]:
0 False
1 False
2 True
3 True
4 False
5 True
dtype: boolean
In [134]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: ).str.fullmatch(pattern)
.....:
Out[134]:
0 False
1 False
2 True
3 True
4 False
5 False
dtype: boolean
match、fullmatch 和 contains 之间的区别是严格性:fullmatch 测试整个字符串是否与正则表达式匹配;match 测试是否有从字符串的第一个字符开始匹配正则表达式的匹配;contains 测试字符串中任何位置是否有匹配正则表达式的匹配。 |
re 包中针对这三种匹配模式的相应函数分别是 re.fullmatch、 re.match 和 re.search。
match、fullmatch、contains、startswith 和 endswith 等方法采用一个额外的 na 参数,因此可以将缺失值视为 True 或 False:
In [135]: s4 = pd.Series(
.....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"], dtype="string"
.....: )
.....:
In [136]: s4.str.contains("A", na=False)
Out[136]:
0 True
1 False
2 False
3 True
4 False
5 False
6 True
7 False
8 False
dtype: boolean
Creating indicator variables
您可以从字符串列提取虚拟变量。例如,如果它们用 '|' 分隔:
In [137]: s = pd.Series(["a", "a|b", np.nan, "a|c"], dtype="string")
In [138]: s.str.get_dummies(sep="|")
Out[138]:
a b c
0 1 0 0
1 1 1 0
2 0 0 0
3 1 0 1
字符串 Index 还支持返回 MultiIndex 的 get_dummies。
In [139]: idx = pd.Index(["a", "a|b", np.nan, "a|c"])
In [140]: idx.str.get_dummies(sep="|")
Out[140]:
MultiIndex([(1, 0, 0),
(1, 1, 0),
(0, 0, 0),
(1, 0, 1)],
names=['a', 'b', 'c'])
另请参阅 get_dummies()。
Method summary
方法
说明
连接字符串
根据分隔符拆分字符串
从字符串结尾根据分隔符拆分字符串
对每个元素建立索引(检索第 i 个元素)
在 Series 的每个元素中使用通过的分隔符来连接字符串
在分隔符上分割字符串,返回虚拟变量的 DataFrame
如果每个字符串都包含模式/正则表达式,则返回布尔数组
用其他字符串或给定结果的可调用函数替换模式/正则表达式/字符串出现
从字符串中删除前缀,即仅当字符串以前缀开始时才删除。
从字符串中删除后缀,即仅当字符串以后缀结尾时才删除。
重复值(s.str.repeat(3) 等同于 x * 3)
在字符串的左边、右边或两边添加空格
等同于 str.center
等同于 str.ljust
相当于 str.rjust
相当于 str.zfill
将长字符串拆分为长度小于给定宽度的一系列行
将 Series 中的每个字符串切片
用传入值替换每个字符串中的切片
计数模式出现的次数
对于每个元素,相当于 str.startswith(pat)
对于每个元素,相当于 str.endswith(pat)
计算每个字符串的所有模式/正则表达式出现位置的列表
_re.match_对每个元素调用,返回匹配的组作为列表
_re.search_对每个元素调用,返回 DataFram,每行一个元素,每列一个正则捕获组
_re.findall_对每个元素调用,返回 DataFrame,每行一个匹配,每列一个正则捕获组
计算字符串长度
相当于_str.strip_
相当于_str.rstrip_
相当于_str.lstrip_
相当于_str.partition_
相当于_str.rpartition_
相当于_str.lower_
相当于_str.casefold_
相当于_str.upper_
相当于_str.find_
相当于_str.rfind_
相当于_str.index_
相当于_str.rindex_
相当于_str.capitalize_
相当于_str.swapcase_
返回 Unicode 范式。相当于_unicodedata.normalize_
相当于 str.translate
相当于 str.isalnum
相当于 str.isalpha
相当于 str.isdigit
相当于 str.isspace
相当于 str.islower
相当于 str.isupper
相当于 str.istitle
相当于 str.isnumeric
相当于 str.isdecimal