当前位置: 首页 > article >正文

Pandas使用教程 - 正则表达式在 Pandas 中的应用

目录

  • 基础篇15:正则表达式在 Pandas 中的应用
    • 1. 正则表达式简介
      • 1.1 什么是正则表达式?
      • 1.2 常见正则表达式语法
    • 2. Pandas 中的字符串方法与正则表达式
      • 2.1 str.contains()
      • 2.2 str.extract()
      • 2.3 str.findall()
      • 2.4 str.replace()
      • 2.5 str.match()
    • 3. 正则表达式在数据清洗中的常见应用
      • 3.1 清洗脏数据
      • 3.2 提取特定模式
      • 3.3 替换不符合规范的字符
      • 3.4 数据拆分
    • 4. 结合 Pandas 应用正则表达式的实战技巧
      • 4.1 向量化操作
      • 4.2 使用捕获组提取数据
      • 4.3 替换时使用反向引用
      • 4.4 配合 apply() 进行自定义处理
    • 5. 实战案例:利用正则表达式进行数据清洗与特征提取
      • 5.1 案例背景
      • 5.2 数据读取与预览
      • 5.3 提取电子邮件地址
      • 5.4 替换电话号码为统一格式
      • 5.5 综合清洗操作
    • 6. 进阶技巧与注意事项
      • 6.1 注意正则表达式的性能
      • 6.2 处理缺失值(NaN)
      • 6.3 使用 raw 字符串
      • 6.4 调试正则表达式
      • 6.5 多步骤处理
    • 7. 综合案例:从用户评论中提取关键信息
      • 7.1 数据准备
      • 7.2 提取电子邮件地址
      • 7.3 统一电话号码格式
      • 7.4 提取 URL 信息
      • 7.5 统计域名频次
      • 7.6 整合输出
    • 8. 总结


基础篇15:正则表达式在 Pandas 中的应用

在数据预处理中,经常会遇到文本数据中的各种模式匹配、提取和替换问题。正则表达式(Regular Expression)作为一种强大的文本匹配工具,能够描述字符串匹配规则,在数据清洗、格式转换、特征提取以及文本挖掘等方面发挥重要作用。Pandas 通过 Series.str 模块将正则表达式功能与向量化字符串操作结合,使得批量处理文本数据变得既高效又简洁。

本文将详细介绍正则表达式的基本概念、常见语法规则以及如何在 Pandas 中应用正则表达式完成各种操作,并结合多个实例展示其实际应用场景。


1. 正则表达式简介

1.1 什么是正则表达式?

正则表达式(Regular Expression,简称 regex)是一种用于描述和匹配字符串模式的工具。它允许你定义一个模式,然后用这个模式去搜索、替换或拆分字符串。数学上,可以将正则表达式看作一种描述字符串集合 L L L 的方法,例如:
L = { w ∣ w  满足正则表达式  R } L = \{ w \mid w \text{ 满足正则表达式 } R \} L={ww 满足正则表达式 R}
其中, R R R 表示一个正则表达式, w w w 为满足该模式的字符串。

正则表达式在文本数据处理中的常见应用包括:

  • 匹配:判断字符串是否符合某个模式。
  • 提取:从字符串中抽取符合模式的子串。
  • 替换:将符合模式的部分替换为新的字符串。
  • 拆分:根据匹配模式对字符串进行分割。

1.2 常见正则表达式语法

以下是一些常见的正则表达式语法规则及示例:

  • .:匹配除换行符外的任意字符。例如:a.c 可匹配 “abc”、“aXc”等。
  • *:匹配前一个字符出现 0 次或多次,例如 ab*c 可匹配 “ac”、“abc”、“abbc” 等。
  • +:匹配前一个字符出现 1 次或多次,例如 ab+c 必须至少出现一次 b。
  • ?:匹配前一个字符出现 0 次或 1 次。
  • []:匹配括号内的任一字符,例如 [abc] 匹配 “a”、“b” 或 “c”;[0-9] 匹配任一数字。
  • ^$:分别匹配字符串的开头和结尾,例如 ^Hello 匹配以 “Hello” 开头的字符串;world!$ 匹配以 “world!” 结尾的字符串。
  • \d\w\s:分别匹配数字、字母数字下划线以及空白字符;其对应的大写形式 \D\W\S 匹配相反的情况。
  • {m,n}:匹配前一个字符至少出现 m 次,至多 n 次,例如 a{2,4} 匹配 “aa”、“aaa”、“aaaa”。
  • |:表示逻辑“或”,例如 cat|dog 匹配 “cat” 或 “dog”。
  • 分组:使用小括号 () 对表达式进行分组,便于提取和引用。例如:(ab)+ 匹配 “ab”、“abab” 等。

这些语法构成了正则表达式的基础,通过组合这些规则可以构造出非常灵活的匹配模式。


2. Pandas 中的字符串方法与正则表达式

Pandas 为 Series 和 DataFrame 中的字符串操作提供了一整套向量化的方法,所有这些方法都位于 .str 访问器下。常见的方法包括:

  • str.contains():判断每个字符串是否包含某个正则表达式模式,返回布尔 Series。
  • str.match():判断字符串是否在起始位置匹配给定正则表达式,返回布尔 Series。
  • str.extract():根据正则表达式提取捕获组,返回一个 DataFrame。
  • str.findall():返回所有匹配正则表达式的子串,结果为列表形式。
  • str.replace():使用正则表达式替换字符串中匹配部分。
  • str.split():按照正则表达式拆分字符串,返回列表或 Series。

这些方法均支持传入参数 regex=True(默认启用正则表达式)以及各种标志参数(如 flags=re.IGNORECASE 等),从而实现灵活的文本匹配和转换。

2.1 str.contains()

str.contains() 方法用于检测字符串中是否存在匹配模式。示例:

import pandas as pd

s = pd.Series(["apple", "banana", "cherry", "date"])
# 检查是否包含字母 a(忽略大小写)
result = s.str.contains("a", case=False)
print(result)

输出:

0     True
1     True
2    False
3    False
dtype: bool

该方法常用于数据过滤,例如筛选出含有特定关键词的行。[citeturn0search0]

2.2 str.extract()

str.extract() 用于从字符串中提取符合捕获组的部分。示例:

s = pd.Series(["Order 1234", "Invoice 5678", "Receipt 91011"])
# 提取数字部分
extracted = s.str.extract("(\d+)")
print(extracted)

输出:

      0
0  1234
1  5678
2  91011

可以看出,正则表达式 (\d+) 捕获了连续数字序列,返回结果为 DataFrame。
数学上,若字符串 s s s 中存在数字序列,则提取结果为:
KaTeX parse error: Undefined control sequence: \d at position 26: …{extract}(s, "(\̲d̲+)")

2.3 str.findall()

str.findall() 返回字符串中所有匹配正则表达式的子串,结果为列表形式:

s = pd.Series(["abc123def", "456ghi789", "no digits here"])
matches = s.str.findall("\d+")
print(matches)

输出:

0       [123]
1    [456, 789]
2          []
dtype: object

这种方法适用于需要获取字符串中所有符合条件的信息时使用。

2.4 str.replace()

str.replace() 方法支持正则表达式替换操作,可以将匹配到的子串替换成指定字符串:

s = pd.Series(["hello 123 world", "test 456 case"])
# 将所有数字替换为 #
replaced = s.str.replace("\d+", "#", regex=True)
print(replaced)

输出:

0    hello # world
1       test # case
dtype: object

这里,正则表达式 \d+ 匹配连续数字序列,替换为 “#”。

2.5 str.match()

str.match() 判断字符串是否从开头匹配给定模式,与 contains 不同,它只检查起始部分:

s = pd.Series(["abc123", "123abc", "abc456"])
# 判断是否以 abc 开头
match_result = s.str.match("abc")
print(match_result)

输出:

0     True
1    False
2     True
dtype: bool

3. 正则表达式在数据清洗中的常见应用

在实际数据预处理中,我们经常需要利用正则表达式解决以下问题:

3.1 清洗脏数据

有时,数据中可能包含不必要的字符或格式错误的数据。正则表达式可以帮助去除多余的空格、特殊符号,或者替换错误格式的数据。例如,清洗电话号码中的空格和横线:

phone_series = pd.Series(["(123) 456-7890", "123-456 7890", "1234567890"])
# 移除括号、空格和横线
clean_phone = phone_series.str.replace("[\(\)\-\s]", "", regex=True)
print(clean_phone)

输出:

0    1234567890
1    1234567890
2    1234567890
dtype: object

3.2 提取特定模式

例如,从一段文本中提取出电子邮件地址。假设数据集中包含用户评论,评论中嵌入了邮箱地址,我们可以利用正则表达式提取:

comments = pd.Series([
    "请联系我,邮箱:user@example.com,谢谢!",
    "没有邮箱信息",
    "另一个邮箱:test.user@domain.org,可用于反馈。"
])
emails = comments.str.extract("([\w\.-]+@[\w\.-]+\.\w+)")
print(emails)

输出可能为:

                 0
0   user@example.com
1               NaN
2  test.user@domain.org

正则表达式 ([\w\.-]+@[\w\.-]+\.\w+) 用于匹配电子邮件地址格式。

3.3 替换不符合规范的字符

在文本数据中,有时需要将非 ASCII 字符、特殊符号等替换掉,或者统一格式。例如,将中文全角符号替换为半角:

text_series = pd.Series(["ABC,123!", "测试,全角标点。"])
# 使用正则表达式替换全角逗号和句号为半角
converted = text_series.str.replace(",", ",", regex=True).str.replace("。", ".", regex=True)
print(converted)

输出:

0    ABC,123!
1      测试,半角标点.
dtype: object

(注:实际应用中可能需要更复杂的映射,此处仅为示例。)

3.4 数据拆分

对于一些合并在一起的数据,如地址信息、姓名等,也可以利用正则表达式拆分出有用的信息。例如,将带有分隔符的字符串拆分为多个部分:

address_series = pd.Series(["北京市-海淀区-中关村", "上海市-浦东新区-陆家嘴"])
split_addresses = address_series.str.split("-", expand=True)
print(split_addresses)

输出:

      0      1      2
0   北京市   海淀区   中关村
1   上海市  浦东新区   陆家嘴

4. 结合 Pandas 应用正则表达式的实战技巧

在 Pandas 中使用正则表达式主要依赖于向量化的字符串方法,这不仅大大提高了处理速度,还使得代码更加简洁。下面介绍几个常见的技巧和注意事项:

4.1 向量化操作

Pandas 的字符串方法都是向量化的,这意味着你可以一次性对整个 Series 应用正则表达式,而无需遍历每个元素。例如:

df["clean_text"] = df["raw_text"].str.replace(r"\s+", " ", regex=True)

此代码将 raw_text 列中所有连续空白字符替换为一个空格,既简洁又高效。

4.2 使用捕获组提取数据

利用 str.extract() 方法时,正则表达式中的括号用于捕获需要提取的部分。捕获组可以为数据提取提供命名:

# 命名捕获组提取日期:格式为 YYYY-MM-DD
df["date_extracted"] = df["text"].str.extract(r"(?P<date>\d{4}-\d{2}-\d{2})")

这样提取出的列名为 “date_extracted”,便于后续使用。

4.3 替换时使用反向引用

在使用 str.replace() 进行替换时,可以利用反向引用 $1、$2 等来引用捕获组。例如,假设需要将 “abc123” 形式的字符串转换为 “123abc”:

s = pd.Series(["abc123", "def456"])
# 将前三个字母和后面的数字交换位置
rearranged = s.str.replace(r"([a-zA-Z]{3})(\d+)", r"\2\1", regex=True)
print(rearranged)

输出:

0    123abc
1    456def
dtype: object

这里,\1\2 分别表示第一个和第二个捕获组的内容。

4.4 配合 apply() 进行自定义处理

虽然 Pandas 的内置字符串方法已经非常强大,但有时我们需要进行更为复杂的正则处理,这时可以结合 apply() 和 lambda 表达式来实现。例如,对某一列进行多步正则匹配和替换:

def custom_clean(text):
    # 首先移除所有 HTML 标签
    text = pd.Series(text).str.replace(r"<.*?>", "", regex=True).iloc[0]
    # 然后替换连续的空格为单个空格
    text = pd.Series(text).str.replace(r"\s+", " ", regex=True).iloc[0]
    return text

df["clean_text"] = df["raw_text"].apply(custom_clean)

这种方式灵活度较高,但在数据量较大时可能会略微降低性能。


5. 实战案例:利用正则表达式进行数据清洗与特征提取

下面通过一个实际案例,展示如何利用 Pandas 中的正则表达式方法对文本数据进行清洗和特征提取。

5.1 案例背景

假设我们有一份包含用户反馈信息的 CSV 文件,其中有一列 “feedback” 存储了用户的评论内容。评论中可能包含电子邮件地址、电话号码以及其他噪音信息。我们需要对这列数据进行清洗,提取出电子邮件地址,并将评论中的电话号码替换为统一格式。

5.2 数据读取与预览

首先读取数据:

import pandas as pd

# 模拟用户反馈数据
data_feedback = {
    "id": [1, 2, 3, 4],
    "feedback": [
        "请联系我,邮箱 user@example.com,电话:138-1234-5678。",
        "反馈不错,但我的号码是(010) 88886666,请回复。",
        "无有效联系方式。",
        "邮件:test.user@domain.org; 电话:+86 139 8765 4321。"
    ]
}
df_feedback = pd.DataFrame(data_feedback)
print("原始反馈数据:")
print(df_feedback)

输出结果:

   id                                  feedback
0   1  请联系我,邮箱 user@example.com,电话:138-1234-5678。
1   2         反馈不错,但我的号码是(010) 88886666,请回复。
2   3                             无有效联系方式。
3   4    邮件:test.user@domain.org; 电话:+86 139 8765 4321。

5.3 提取电子邮件地址

利用 str.extract() 提取反馈中的电子邮件地址:

# 提取电子邮件地址的正则表达式:匹配字母、数字、点、连字符组合的邮箱格式
df_feedback["email"] = df_feedback["feedback"].str.extract(r"([\w\.-]+@[\w\.-]+\.\w+)")
print("提取后的电子邮件地址:")
print(df_feedback[["id", "email"]])

输出结果:

   id                  email
0   1     user@example.com
1   2                   NaN
2   3                   NaN
3   4  test.user@domain.org

可以看到,第 0 行和第 4 行成功提取了电子邮件地址。

5.4 替换电话号码为统一格式

针对电话号码的格式多样性,我们可以先用正则表达式匹配常见格式,然后将其替换为统一的格式(例如,所有数字连续形式)。示例:

import re

# 定义一个函数,将匹配到的电话号码中的非数字字符去除
def normalize_phone(text):
    # 使用正则表达式匹配电话号码(简单示例:匹配包含数字、空格、括号、加号、横线的组合)
    pattern = r"([\+\d\(\)\-\s]{7,})"
    # 替换操作:将匹配到的部分进行处理
    return re.sub(pattern, lambda m: re.sub(r"\D", "", m.group(0)), text)

# 对反馈文本中的电话号码进行替换
df_feedback["feedback_clean"] = df_feedback["feedback"].str.replace(r"([\+\d\(\)\-\s]{7,})", lambda m: re.sub(r"\D", "", m.group(0)), regex=True)
print("清洗后的反馈文本:")
print(df_feedback[["id", "feedback_clean"]])

运行后,反馈文本中的电话号码将被替换为仅包含数字的格式。例如,“138-1234-5678” 会变成 “13812345678”,“(010) 88886666” 变成 “01088886666”。这种统一格式便于后续数据存储或进一步分析。

5.5 综合清洗操作

我们还可以将多步清洗操作组合在一起,利用链式调用和 pipe() 方法提高代码可读性。例如,对反馈文本同时提取电子邮件和规范电话号码:

def clean_feedback(df):
    # 提取电子邮件地址
    df["email"] = df["feedback"].str.extract(r"([\w\.-]+@[\w\.-]+\.\w+)")
    # 替换电话号码中的非数字字符
    df["feedback_clean"] = df["feedback"].str.replace(r"([\+\d\(\)\-\s]{7,})", lambda m: re.sub(r"\D", "", m.group(0)), regex=True)
    return df

df_feedback_clean = df_feedback.pipe(clean_feedback)
print("综合清洗后的反馈数据:")
print(df_feedback_clean)

通过 pipe() 链式调用,可以使代码更具模块化和可维护性。


6. 进阶技巧与注意事项

在 Pandas 中使用正则表达式进行数据处理时,还有一些进阶技巧和常见注意事项需要掌握:

6.1 注意正则表达式的性能

正则表达式虽然功能强大,但在大数据量下计算开销较大。建议:

  • 尽量使用向量化的字符串方法,而不是对每个元素使用 Python 循环;
  • 对于复杂正则表达式,考虑提前编译正则表达式(使用 re.compile()),以提高重复匹配的效率;
  • 如果只需要简单匹配,尽量使用简单模式,避免过多使用贪婪匹配等可能导致性能下降的模式。

6.2 处理缺失值(NaN)

在使用 Pandas 字符串方法时,如果 Series 中存在 NaN 值,这些方法通常会返回 NaN。可以先使用 fillna() 方法填充缺失值:

df["feedback"] = df["feedback"].fillna("")

这样可以避免在正则操作中产生错误或不期望的结果。

6.3 使用 raw 字符串

在编写正则表达式时,建议使用 Python 的原始字符串(以 r 开头的字符串),这样可以避免转义字符问题。例如:

pattern = r"\d+"

而非 "\\d+"

6.4 调试正则表达式

对于复杂的正则表达式,可以先在单个字符串上测试,再将其应用于整个 Series。借助在线正则表达式工具(如 regex101.com)也能快速调试和验证正则表达式的正确性。

6.5 多步骤处理

对于复杂文本清洗任务,建议将正则处理拆分为多个步骤,每步单独调用 Pandas 的字符串方法或自定义函数,这样更易于调试和维护。利用 pipe() 或 apply() 可以帮助实现这种模块化设计。


7. 综合案例:从用户评论中提取关键信息

为加深理解,下面给出一个综合案例,假设我们有一份用户评论数据,评论中可能包含电子邮件、电话号码以及 URL。我们的目标是:

  1. 提取评论中的电子邮件地址。
  2. 将评论中的电话号码统一为纯数字格式。
  3. 提取 URL,并统计各个域名的出现频次。

7.1 数据准备

import pandas as pd
import re

data_comments = {
    "评论": [
        "联系我:user1@example.com,电话:138-1234-5678,访问 https://www.example.com 获取更多信息。",
        "请发送邮件至 contact@domain.org 或拨打(010) 88886666。",
        "无联系方式,请访问 http://testsite.net。",
        "用户反馈: 邮件 test.user@service.cn; 电话:+86 139 8765 4321; 更多请看 https://service.cn/about。"
    ]
}
df_comments = pd.DataFrame(data_comments)
print("原始评论数据:")
print(df_comments)

7.2 提取电子邮件地址

df_comments["email"] = df_comments["评论"].str.extract(r"([\w\.-]+@[\w\.-]+\.\w+)")

7.3 统一电话号码格式

电话号码可能有多种格式,统一方式为提取所有数字:

df_comments["phone"] = df_comments["评论"].str.extract(r"([\+\d\(\)\-\s]{7,})")
# 对提取到的电话号码去除所有非数字字符
df_comments["phone"] = df_comments["phone"].apply(lambda x: re.sub(r"\D", "", x) if pd.notna(x) else x)

7.4 提取 URL 信息

利用正则表达式提取 URL,并进一步解析域名:

# 提取 URL,简单模式示例:匹配 http 或 https 开头的 URL
df_comments["url"] = df_comments["评论"].str.extract(r"(https?://[\w\.-/]+)")
# 提取域名部分
df_comments["domain"] = df_comments["url"].str.extract(r"https?://([\w\.-]+)")

7.5 统计域名频次

利用 Pandas 的 value_counts 方法统计域名出现次数:

domain_counts = df_comments["domain"].value_counts()
print("域名出现频次:")
print(domain_counts)

7.6 整合输出

将所有提取结果整合输出:

print("综合清洗后的评论数据:")
print(df_comments[["email", "phone", "url", "domain"]])

通过这一系列操作,我们能够从用户评论中自动提取出关键信息,为后续的数据分析和建模提供有效特征。


8. 总结

本文详细讲解了正则表达式在 Pandas 中的应用,主要内容包括:

  1. 正则表达式基础:介绍了正则表达式的基本概念和常用语法,如字符匹配、数量词、捕获组、反向引用等。
  2. Pandas 字符串方法:重点说明了 Pandas 中的 str.contains、str.extract、str.findall、str.replace 和 str.match 等方法,并展示了如何利用这些方法实现批量文本匹配、提取和替换。
  3. 应用场景:通过清洗电话号码、提取电子邮件地址、拆分地址信息等案例,展示了正则表达式在数据清洗、格式统一和特征提取中的实际应用。
  4. 进阶技巧:讨论了使用向量化操作、捕获组、反向引用以及结合 apply() 实现自定义正则处理的高级方法,同时强调了性能优化、缺失值处理和调试技巧。
  5. 综合实战案例:以用户评论数据为例,展示了如何一步步利用正则表达式提取电子邮件、规范电话号码、提取 URL 并统计域名频次,最终得到清洗后的数据,为后续分析打下基础。
  6. 流程图示意:利用 Mermaid 语法绘制了数据清洗的基本流程图,帮助读者直观理解各个步骤之间的关系。

正则表达式作为一种灵活且高效的文本处理工具,与 Pandas 的向量化字符串方法相结合,为大规模文本数据清洗和特征提取提供了极大的便利。无论是数据科学家、数据分析师还是机器学习工程师,掌握正则表达式的应用都是提升数据处理效率和质量的重要技能。

在实际项目中,建议:

  • 充分利用 Pandas 的内置字符串方法来实现向量化正则处理;
  • 在遇到复杂文本处理任务时,合理拆分步骤并结合自定义函数进行逐步调试;
  • 注意正则表达式的性能问题,对于大规模数据,建议先使用 re.compile() 预编译正则表达式;
  • 使用在线工具(如 regex101.com)测试和验证正则表达式,以确保其正确性;
  • 结合数据可视化工具,直观展示正则处理前后的数据对比,从而验证数据清洗效果。

总之,正则表达式在 Pandas 中的应用为数据清洗和特征提取提供了强大的支持。希望本文能够帮助你全面理解并灵活运用正则表达式技术,在实际数据处理中高效提取和清洗文本数据,从而为后续分析和建模打下坚实基础。



http://www.kler.cn/a/538783.html

相关文章:

  • 【Qt 常用控件】输入类控件1(QLineEdit和QTextEdit 输入框)
  • elasticsearch实战三 elasticsearch与mysql数据实时同步
  • [LeetCode]day17 349.两个数组的交集
  • 2025年日祭
  • 无限使用Cursor
  • PostGIS:使用shp2pgsql、pgsql2shp、OGR2OGR函数进行数据导入、导出
  • FlutterWeb实战:02-加载体验优化
  • Elasticsearch的使用场景、数据量级及选择原因?为什么没有用Hbase?
  • 按钮凸起与按下css效果
  • 番外02:前端八股文面试题-CSS篇
  • ZooKeeper作为注册中心有什么问题? ZooKeeper作为注册中心,海量服务同时重启有什么问题?
  • DeepSeek LLM 论文解读:相信长期主义开源理念可扩展大语言模型(DeepSeek 吹响通用人工智能的号角)
  • 使用LLaMA Factory踩坑记录
  • 基于PAI 低代码实现大语言模型微调和部署
  • python中的lambda function(ChatGPT回答)
  • 【算法刷题指南】二分查找
  • 电商java 面试题_JAVA电商项目面试题(一)
  • Windows图形界面(GUI)-QT-C/C++ - QT Dial
  • python连点器
  • 百度的冰桶算法
  • 未来十年的前端走向以及需要掌握什么技能
  • 搜维尔科技:提供人形机器人传感器的应用案例分析
  • 简单的Python记事本应用程序
  • 初次体验Tauri和Sycamore (2)
  • 使用 Apache Spark 进行大数据分析
  • c/c++蓝桥杯经典编程题100道(17)二叉树遍历