首页 / Pandas 入门教程 / 文本数据:.str 访问器

Pandas 入门教程

文本数据:.str 访问器

本教程共 54 篇 · 第 48 篇 · 更新于 2026-08-11 · 约 8 分钟阅读

PandasPandas 入门教程str 访问器字符串处理StringDtype文本清洗

本节目标:学会用 .str 访问器对一整列文本做大小写转换、拆分、替换、连接和判断,掌握 pandas 3.0 的字符串类型。

.str 访问器:给整列批量处理字符串

Python 字符串有 "hello".upper()"a,b,c".split(",") 这些方法,但只作用于单个字符串。数据清洗时,你要处理的是整列几百个字符串。用循环一个个来?太慢也太啰嗦。

pandas 的解法是 .str 访问器:Series.str.方法名(),对列里每个元素批量执行同样的字符串操作,方法名和 Python 字符串方法基本一一对应。

import pandas as pd

s = pd.Series(["hello", "World", "pandas", "Python"])
print(s.dtype)
# str

print(s.str.upper())
# 0     HELLO
# 1     WORLD
# 2    PANDAS
# 3    PYTHON
# dtype: str
Note

pandas 3.0 起,纯字符串列默认的类型就是 str(StringDtype 的别名),不再是以前的 object。这对日常使用基本无感,但意味着字符串列有了专属类型,行为更可控。

大小写转换

一套方法把大小写玩出花:

import pandas as pd

s = pd.Series(["Hello World", "PYTHON pandas", "data SCIENCE"])

print(s.str.lower())        # 全部小写
print(s.str.upper())        # 全部大写
print(s.str.capitalize())   # 首字母大写,其余小写
print(s.str.title())        # 每个单词首字母大写
print(s.str.swapcase())     # 大小写互换

去空格

用户输入的数据,前后常带着空格,肉眼看不见,一比较就出问题。strip 系列就是干这个的:

import pandas as pd

s = pd.Series(["  hello  ", "world  ", "  pandas", " python "])
print(s.str.strip())    # 去掉首尾空格
print(s.str.lstrip())   # 只去左边
print(s.str.rstrip())   # 只去右边
# 0    hello
# 1    world
# 2    pandas
# 3    python
# dtype: str

清洗列名也是常见场景。DataFrame 的列名是 Index,同样有 .str

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(2, 2), columns=[" 姓名 ", " 年龄 "])
df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
print(df.columns.tolist())
# ['姓名', '年龄']

长度与计数

len 统计每个字符串的长度,count 统计某个字符或模式出现的次数:

import pandas as pd

s = pd.Series(["hello", "world", "python", "pandas"])
print(s.str.len())
# 0    5
# 1    5
# 2    6
# 3    6
# dtype: int64

print(s.str.count("o"))
# 0    1
# 1    1
# 2    1
# 3    0

判断类方法

判断类方法返回布尔 Series,直接可以当布尔索引(§20)用:

import pandas as pd

s = pd.Series(["123", "abc", "1a2", "  "])

print(s.str.isdigit())   # 是否全是数字
# 0     True
# 1    False
# 2    False
# 3    False

print(s.str.isalpha())   # 是否全是字母
print(s.str.isalnum())   # 是否全是字母或数字

还有 startswith、endswith、contains 三兄弟,判断”以什么开头/结尾/包含什么”:

import pandas as pd

s = pd.Series(["hello world", "python pandas", "data science"])

print(s.str.startswith("hello"))
# 0     True
# 1    False
# 2    False

print(s.str.endswith("pandas"))
# 0    False
# 1     True
# 2    False

print(s.str.contains("data"))
# 0    False
# 1    False
# 2     True

contains 默认大小写敏感,想忽略大小写加 case=False。contains 还支持正则表达式,比如 s.str.contains(r"\d+") 找出带数字的行——正则的完整玩法下节展开。

拆分:split

split 按分隔符把每个字符串拆成列表:

import pandas as pd

s = pd.Series(["a_b_c", "c_d_e", "f_g_h"])

print(s.str.split("_"))
# 0    [a, b, c]
# 1    [c, d, e]
# 2    [f, g, h]
# dtype: object

# 拆完取第 2 段
print(s.str.split("_").str[1])
# 0    b
# 1    d
# 2    g

拆出来的列表不直观?expand=True 直接把每一段变成一列,得到 DataFrame:

import pandas as pd

s = pd.Series(["a_b_c", "c_d_e", "f_g_h"])

print(s.str.split("_", expand=True))
#    0  1  2
# 0  a  b  c
# 1  c  d  e
# 2  f  g  h

# n=1 只拆第一刀,剩下的留在最后一段
print(s.str.split("_", expand=True, n=1))
#    0    1
# 0  a  b_c
# 1  c  d_e
# 2  f  g_h

rsplit 从右边开始拆。日期字符串拆成年月日,是 expand 最常见的用途。

替换:replace

替换有两种模式,由 regex 参数控制:

import pandas as pd

s = pd.Series(["hello world", "python pandas"])

# 字面替换:把 o 换成 0(regex=False 表示按普通字符串处理)
print(s.str.replace("o", "0", regex=False))
# 0    hell0 w0rld
# 1    pyth0n pandas

# 默认 regex=True:模式按正则解释
print(s.str.replace("l+", "L", regex=True))
# 0    heLo worLd
# 1    python pandas
Warning

str.replace 默认 regex=True,连单字符也会按正则处理。想替换的字面量里带 .$\ 这些正则特殊字符时,要么写 regex=False,要么把特殊字符转义。用 regex=False 最省心。

removeprefixremovesuffix 专门去掉固定前缀/后缀,比如文件名批量去后缀:s.str.removesuffix(".csv")

连接:cat

两个方向:整列拼成一个字符串,或者逐行拼接两列。

import pandas as pd

s = pd.Series(["a", "b", "c", "d"])

# 整列拼成一个字符串,用逗号分隔
print(s.str.cat(sep=","))
# a,b,c,d

# 两列逐行拼接
s2 = pd.Series(["1", "2", "3", "4"])
print(s.str.cat(s2, sep="-"))
# 0    a-1
# 1    b-2
# 2    c-3
# 3    d-4
# dtype: str

更常见的逐行拼接其实用 + 就行:s + "-" + s2,效果一样。cat 的优势是能处理缺失值:默认跳过 NaN,也可以用 na_rep 指定缺失值的替代文本。

按位置取字符与切片

[] 可以直接按位置取每个字符串的字符,超出长度返回 NaN,不会报错:

import pandas as pd

s = pd.Series(["hello", "world", "python", "pandas"])

print(s.str[0])     # 每个字符串的第一个字符
# 0    h
# 1    w
# 2    p
# 3    p

df = pd.DataFrame({"编号": ["A-001", "B-002", "C-003"]})
print(df["编号"].str[2:])   # 去掉前两个字符
# 0    001
# 1    002
# 2    003
# dtype: str

切片规则和 Python 字符串完全一致,str[2:] 取从第 3 个字符到结尾。

缺失值怎么处理

.str 的方法对缺失值很友好:大多数方法自动跳过 NaN,输出还是 NaN;判断类方法(startswith、contains 等)可以传 na 参数指定缺失值算 True 还是 False:

import pandas as pd
import numpy as np

s = pd.Series(["apple", np.nan, "banana"])
print(s.str.upper())
# 0     APPLE
# 1       NaN
# 2    BANANA

# 缺失值在判断里算 False,避免筛选时报错
print(s.str.contains("a", na=False))
# 0     True
# 1    False
# 2     True
# dtype: bool

3.0 的字符串类型

pandas 3.0 的字符串列默认推断为 dtype="str",这是新的 StringDtype,缺失值用 NaN 表示。如果你更习惯 pandas 2.x 时代 pd.NA 的缺失语义,可以显式指定 dtype="string"

import pandas as pd

print(pd.Series(["a", "b", None]).dtype)
# str

print(pd.Series(["a", "b", None], dtype="string").dtype)
# string

两个都是 StringDtype,只是缺失值表示不同(NaN vs pd.NA)。旧代码里常见的 object 类型字符串列,.str 方法照样能用;想升级成新类型,astype("str") 即可。装了 PyArrow 时,str 类型自动用 PyArrow 存储,内存更省、部分操作更快。

Tip

文本清洗的固定套路:strip 去空格 → lower 统一大小写 → replace 规范格式 → contains/isdigit 校验数据。把这四步串起来,绝大多数脏文本都能收拾干净。

小结

.str 访问器让字符串操作从”逐条处理”变成”整列处理”:大小写、去空格、拆分、替换、连接、判断一应俱全,方法名和 Python 字符串方法对齐,上手成本极低。配合 3.0 的 str 字符串类型,文本数据在 pandas 里终于有了正经类型。下一节在此基础上进阶:正则表达式和 extract 提取。