处理文本数据#

文本数据类型#

在 pandas 中存储文本数据有两种方法:

  1. object -dtype NumPy 数组。

  2. StringDtype 扩展类型。

我们建议使用 StringDtype 来存储文本数据。

在 pandas 1.0 之前,object dtype 是唯一的选择。这在很多方面都令人不快:

  1. 您可能会意外地在 object dtype 数组中存储字符串和非字符串的*混合*。拥有一个专门的 dtype 会更好。

  2. object dtype 会破坏特定于 dtype 的操作,例如 DataFrame.select_dtypes() 。无法清楚地选择*仅*文本列,同时排除仍然是 object dtype 的非文本列。

  3. 在阅读代码时,object dtype 数组的内容不如 'string' 清楚。

目前,包含字符串的 object dtype 数组和 arrays.StringArray 的性能大致相同。我们预计未来的增强功能将显着提高 StringArray 的性能并降低其内存开销。

警告

StringArray 目前仍被视为实验性的。其实现和部分 API 可能会在不发出警告的情况下进行更改。

为了向后兼容,object dtype 仍然是我们推断字符串列表的默认类型

要显式请求 string dtype,请指定 dtype

或者在创建 SeriesDataFrame 后使用 astype

您还可以使用 StringDtype "string" 作为非字符串数据的 dtype,它将被转换为 string dtype:

或者从现有的 pandas 数据转换:

行为差异#

这些是 StringDtype 对象行为与 object dtype 不同的地方

  1. 对于 StringDtype,返回**数值**输出的 string accessor methods 将始终返回可为空的整数 dtype,而不是根据 NA 值是否存在而返回 int 或 float dtype。返回**布尔值**输出的方法将返回可为空的布尔 dtype。

    输出均为 Int64 dtype。与 object-dtype 相比:

    当存在 NA 值时,输出 dtype 为 float64。对于返回布尔值的类似方法也是如此。

  1. 某些字符串方法,例如 Series.str.decode() ,在 StringArray 上不可用,因为 StringArray 只保存字符串,而不是字节。

  2. 在比较运算中,arrays.StringArray 和由 StringArray 支持的 Series 将返回带有 BooleanDtype 的对象,而不是 bool dtype 对象。 StringArray 中的缺失值将在比较运算中传播,而不是像 numpy.nan 那样总是比较不等。

本文档其余部分的其他内容同样适用于 stringobject dtype。

字符串方法#

Series 和 Index 都配备了一组字符串处理方法,可以轻松地对数组的每个元素进行操作。也许最重要的是,这些方法会自动排除缺失/NA 值。这些方法通过 str 属性访问,并且通常具有与等效的(标量)内置字符串方法相同的名称:

Index 上的字符串方法在清理或转换 DataFrame 列时特别有用。例如,您可能有名为“ Leading or trailing whitespace”的列:

由于 df.columns 是一个 Index 对象,我们可以使用 .str 访问器

然后可以使用这些字符串方法按需清理列。这里我们正在删除前导和尾随空格,将所有名称转换为小写,并将任何剩余的空格替换为下划线:

备注

如果您的 Series 中有许多重复的元素(即 Series 中唯一元素的数量远小于 Series 的长度),则可以更快地将原始 Series 转换为 category 类型,然后在其上使用 .str.<method>.dt.<property>。性能差异来自于这样一个事实:对于 category 类型的 Series,字符串操作是在 .categories 上执行的,而不是在 Series 的每个元素上执行的。

请注意,具有字符串 .categoriescategory 类型 Series 在某些方面与字符串类型的 Series 存在局限性(例如,您不能将字符串相加:如果 scategory 类型的 Series,则 s + " " + s 将不起作用)。此外,在处理类型为 list 的元素时,此类 Series 不提供 .str 方法。

警告

Series 的类型会被推断出来,并且只允许使用字符串类型。

一般来说,.str 访问器仅用于字符串。除了极少数例外,其他用法不被支持,并且将来可能会被禁用。

拆分和替换字符串#

split 这样的方法会返回一个 Series 的列表:

可以使用 get[] 符号来访问拆分列表中的元素:

使用 expand 可以轻松地将其展开以返回一个 DataFrame。

当原始 Series 具有 StringDtype 时,输出列也将全部是 StringDtype

也可以限制拆分的次数:

rsplitsplit 类似,只是它沿着反方向工作,即从字符串末尾到字符串开头:

replace 可选地使用 regular expressions

在 2.0 版本发生变更.

regex=True 的单字符模式也将被视为正则表达式:

如果您想进行字面字符串替换(等同于 str.replace() ),您可以将可选的 regex 参数设置为 False,而不是转义每个字符。在这种情况下,patrepl 都必须是字符串:

replace 方法也可以接受一个可调用对象作为替换。它使用 re.sub() 对每个 pat 调用。可调用对象应该接受一个位置参数(一个正则表达式对象)并返回一个字符串。

replace 方法还接受来自 re.compile() 的已编译正则表达式对象作为模式。所有标志都应包含在已编译的正则表达式对象中。

当使用已编译的正则表达式对象调用 replace 时包含 flags 参数将引发 ValueError

removeprefixremovesuffix 的效果与 Python 3.9 中添加的 str.removeprefixstr.removesuffix <https://docs.python.org/3/library/stdtypes.html#str.removeprefix>`__ 相同:

在 1.4.0 版本加入.

连接#

有几种方法可以将 SeriesIndex 与自身或其他对象连接起来,它们都基于 cat()``Index.str.cat`。

将单个 Series 连接成一个字符串#

可以连接 Series``(或 ``Index)的内容:

如果未指定,分隔符的关键字 sep 默认为空字符串 sep=''

默认情况下,会忽略缺失值。使用 na_rep,可以为它们指定表示:

将 Series 和类似列表的对象连接成一个 Series#

cat() 的第一个参数可以是类似列表的对象,前提是它的长度与调用它的 Series``(或 ``Index)匹配。

任何一方的缺失值都会导致结果中出现缺失值,除非 指定了 na_rep

将 Series 和类数组的对象连接成一个 Series#

参数 others 也可以是二维的。在这种情况下,行数必须与调用方的 Series``(或 ``Index)的长度匹配。

将 Series 和带索引的对象连接成一个 Series,并进行对齐#

通过设置 join 关键字,可以对 Series 或 DataFrame 进行索引对齐后再进行连接。

join 可用选项(’left’, ‘outer’, ‘inner’, ‘right’ 之一)都可以使用。特别是,对齐也意味着不同长度的索引不需要再完全匹配。

othersDataFrame 时,也可以使用相同的对齐方式:

将 Series 和多个对象连接成一个 Series#

可以将在类列表容器(包括迭代器、dict 视图等)中的多个类数组项(特别是:SeriesIndex``np.ndarray` 的一维变体)组合起来。

传入列表中的所有无索引元素(例如 np.ndarray)必须与调用方的 Series``(或 ``Index)长度匹配,但 SeriesIndex 可以具有任意长度(只要通过 join=None 禁用了对齐):

如果对包含不同索引的类列表 others 使用 join='right',则这些索引的并集将用作最终连接的基础:

使用 .str 进行索引#

您可以使用 [] 表示法按位置直接索引。如果索引超出了字符串的末尾,结果将是 NaN

提取子字符串#

提取每个主题的第一个匹配项 (extract)#

The extract method accepts a regular expression with at least one capture group.

提取包含多个捕获组的正则表达式会返回一个 DataFrame,每个捕获组占一列。

不匹配的元素将返回一个全为 NaN 的行。因此,一个包含杂乱字符串的 Series 可以被“转换”为一个具有相同索引的 Series 或 DataFrame,其中包含已清理或更有用的字符串,而无需使用 get() 来访问元组或 re.match 对象。结果的 dtype 始终是 object,即使没有找到匹配项并且结果只包含 NaN

可以使用形如

的命名捕获组和可选捕获组。请注意,正则表达式中的任何捕获组名称都将用作列名;否则将使用捕获组编号。

也可以使用。请注意,正则表达式中的任何捕获组名称都将用作列名;否则捕获组编号将用作列名。

提取包含单个捕获组的正则表达式会返回一个 DataFrame,如果 expand=True,则只有一列。

如果 expand=False,则返回一个 Series。

在一个 Index 上使用包含恰好一个捕获组的正则表达式调用会返回一个 DataFrame,如果 expand=True,则只有一列。

如果 expand=False,则返回一个 Index

在一个 Index 上使用包含多个捕获组的正则表达式调用会返回一个 DataFrame,如果 expand=True

如果 expand=False,则引发 ValueError

下表总结了 extract(expand=False) 的行为(第一列是输入主题,第一行是正则表达式的组数)

1 组

>1 组

Index

Index

ValueError

Series

Series

DataFrame

提取每个主题的所有匹配项 (extractall)#

``extract``(只返回第一个匹配项)不同,

extractall 方法返回每个匹配项。extractall 的结果始终是一个 DataFrame,其行具有 MultiIndexMultiIndex 的最后一级命名为 match,并指示主题中的顺序。

当 Series 中的每个主题字符串只有一个匹配项时,

extractall(pat).xs(0, level='match')extract(pat) 的结果相同。

Index 也支持 .str.extractall。它返回一个 DataFrame,其结果与具有默认索引(从 0 开始)的 Series.str.extractall 相同。

测试与模式匹配或包含模式的字符串#

您可以检查元素是否包含某个模式:

或者元素是否匹配某个模式:

备注

matchfullmatchcontains 之间的区别在于严格程度:“fullmatch 测试整个字符串是否与正则表达式匹配;match 测试正则表达式是否与字符串的第一个字符匹配;contains 测试正则表达式是否与字符串中的任何位置匹配。

re 包中这三种匹配模式对应的函数分别是 re.fullmatchre.matchre.search

matchfullmatchcontainsstartswithendswith 等方法接受一个额外的 na 参数,因此可以将被视为 True 或 False 的缺失值:

创建指示变量#

您可以从字符串列中提取虚拟变量。例如,如果它们由 '|' 分隔:

字符串 Index 也支持 get_dummies,它返回一个 MultiIndex

另请参阅 get_dummies()

方法摘要#

方法

描述

cat()

连接字符串

split()

按分隔符分割字符串

rsplit()

从字符串末尾开始按分隔符分割字符串

get()

索引到每个元素(检索第 i 个元素)

join()

使用传入的分隔符连接 Series 中每个元素中的字符串

get_dummies()

按分隔符分割字符串,返回虚拟变量的 DataFrame

contains()

如果每个字符串包含模式/正则表达式,则返回布尔数组

replace()

将模式/正则表达式/字符串的出现替换为其他字符串或给定出现的调用返回的结果

removeprefix()

删除字符串中的前缀,即仅当字符串以指定前缀开头时才删除。

removesuffix()

删除字符串中的后缀,即仅当字符串以指定后缀结尾时才删除。

repeat()

重复值(s.str.repeat(3) 等同于 x * 3

pad()

在字符串两侧添加空白

center()

等同于 str.center

ljust()

等同于 str.ljust

rjust()

等同于 str.rjust

zfill()

等同于 str.zfill

wrap()

将长字符串分割成宽度小于给定宽度的行

slice()

对 Series 中的每个字符串进行切片

slice_replace()

用提供的值替换每个字符串中的切片

count()

计算模式出现的次数

startswith()

对于每个元素,等同于 str.startswith(pat)

endswith()

对于每个元素,等同于 str.endswith(pat)

findall()

计算每个字符串中模式/正则表达式的所有出现次数列表

match()

对每个元素调用 re.match,返回匹配的组作为列表

extract()

对每个元素调用 re.search,返回一个 DataFrame,其中每个元素为一行,每个正则表达式捕获组为一列

extractall()

对每个元素调用 re.findall,返回一个 DataFrame,其中每个匹配项为一行,每个正则表达式捕获组为一列

len()

计算字符串长度

strip()

等同于 str.strip

rstrip()

等同于 str.rstrip

lstrip()

等同于 str.lstrip

partition()

等同于 str.partition

rpartition()

等同于 str.rpartition

lower()

等同于 str.lower

casefold()

等同于 str.casefold

upper()

等同于 str.upper

find()

等同于 str.find

rfind()

等同于 str.rfind

index()

等同于 str.index

rindex()

等同于 str.rindex

capitalize()

等同于 str.capitalize

swapcase()

等同于 str.swapcase

normalize()

返回 Unicode NORM 形式。等同于 unicodedata.normalize

translate()

等同于 str.translate

isalnum()

等同于 str.isalnum

isalpha()

等同于 str.isalpha

isdigit()

等同于 str.isdigit

isspace()

等同于 str.isspace

islower()

等同于 str.islower

isupper()

等同于 str.isupper

istitle()

等同于 str.istitle

isnumeric()

等同于 str.isnumeric

isdecimal()

等同于 str.isdecimal