Pandas中字符串處理的核心方法與正則匹配實戰(zhàn)教學
本節(jié)學習目標
- 掌握 Pandas
str訪問器的常用方法 - 學會字符串的分割、拼接、替換與提取
- 理解正則表達式的基本語法
- 能夠在 Pandas 中使用正則進行高級文本匹配
- 能夠處理實際的文本數(shù)據(jù)(如郵箱提取、地址解析等)
為什么學這個?
在真實數(shù)據(jù)中,文本數(shù)據(jù)無處不在:
- 客戶的姓名、地址、電話號碼
- 商品的描述、分類標簽
- 用戶評論、社交媒體帖子
- 日志文件中的 URL、IP 地址
這些文本數(shù)據(jù)往往格式不統(tǒng)一、包含多余字符或需要從中提取關鍵信息。比如:
- 給你一列包含郵箱地址的數(shù)據(jù),從中提取出用戶名部分。
- 給你一列"省-市-區(qū)"格式的地址,拆分成三個獨立的列。
- 從一列商品描述中提取出所有的數(shù)字(價格、規(guī)格等)。
如果你只會用基礎的字符串方法(如 Python 的 .split()、.replace()),處理 Pandas 數(shù)據(jù)會非常低效。Pandas 的 str 訪問器專為批量文本處理設計,配合正則表達式,可以完成極其復雜的文本操作。
打個比方:如果說數(shù)據(jù)篩選是手術刀,那字符串處理就是"顯微鏡"——它讓你看清文字中最微小的細節(jié),并從中提取出有價值的信息。
核心知識點講解
str 訪問器入門
Pandas 的 Series 對象有一個 .str 屬性,它提供了數(shù)十種字符串操作方法。這些方法會自動應用到 Series 的每一個元素上(向量化操作)。
import pandas as pd
import numpy as np
# 創(chuàng)建示例數(shù)據(jù)
df = pd.DataFrame({
'姓名': ['張三', '李四', '王五', '趙六', '孫七'],
'郵箱': ['zhang@email.com', 'li@work.cn', 'wang@school.edu', 'zhao@gmail.com', 'sun@company.org'],
'電話': ['138-0000-1234', '139 0000 5678', '13600009012', '186-0000-3456', '185 0000 7890'],
'地址': ['北京市朝陽區(qū)', '上海市浦東新區(qū)', '廣州市天河區(qū)', '深圳市南山區(qū)', '杭州市西湖區(qū)'],
'備注': ['VIP客戶, 高價值', '新客戶', '老客戶, 多次購買', None, 'VIP客戶']
})
# ===== 使用 .str 訪問字符串方法 =====
# 轉(zhuǎn)大寫/小寫
print(df['郵箱'].str.upper())
print(df['郵箱'].str.lower())
# 獲取長度
print(df['地址'].str.len())
# 判斷是否包含某字符串
print(df['地址'].str.contains('區(qū)')) # 都包含"區(qū)"
# 判斷開頭和結尾
print(df['地址'].str.startswith('北京'))
print(df['地址'].str.endswith('區(qū)'))
# 替換
print(df['電話'].str.replace('-', ''))
print(df['電話'].str.replace('-', '').str.replace(' ', ''))
# 去除空白字符
print(df['電話'].str.strip()) # 去除首尾空白
字符串常用方法詳解
1. 分割字符串(split)
# ===== 分割字符串 =====
df = pd.DataFrame({
'全名': ['張 三', '李 四', '王 五'],
'標簽': '電子產(chǎn)品,服裝,食品', # 這個會被廣播到所有行
'地址': ['北京市-朝陽區(qū)-望京', '上海市-浦東區(qū)-陸家嘴', '廣州市-天河區(qū)-體育西']
})
# 按空格分割姓名
name_split = df['全名'].str.split(' ')
print(name_split)
# 輸出:
# 0 [張, 三]
# 1 [李, 四]
# 2 [王, 五]
# 分割后展開為多列
name_df = df['全名'].str.split(' ', expand=True)
name_df.columns = ['姓', '名']
print(name_df)
# 分割地址
addr_df = df['地址'].str.split('-', expand=True)
addr_df.columns = ['省/市', '區(qū)', '街道']
print(addr_df)
# 只取分割后的第一部分
print(df['地址'].str.split('-').str[0]) # ['北京市', '上海市', '廣州市']
2. 拼接字符串(cat)
# ===== 拼接字符串 =====
# Series 之間拼接
s1 = pd.Series(['北京', '上海', '廣州'])
s2 = pd.Series(['朝陽', '浦東', '天河'])
print(s1.str.cat(s2, sep='-')) # 北京-朝陽, 上海-浦東, 廣州-天河
# 拼接常量
print(s1.str.cat('-中國')) # 北京-中國, 上海-中國, 廣州-中國
# 在 DataFrame 中拼接多列
df = pd.DataFrame({
'姓': ['張', '李', '王'],
'名': ['三', '四', '五']
})
df['全名'] = df['姓'].str.cat(df['名'])
print(df)
# 也可以直接:
df['全名'] = df['姓'] + df['名'] # 更簡潔
3. 子串提取(slice)
# ===== 提取子串 =====
df = pd.DataFrame({
'身份證號': ['110101199001011234', '310101199202025678', '440101199503039012']
})
# 提取出生年份(第7-10位)
df['出生年份'] = df['身份證號'].str[6:10]
# 提取地區(qū)碼(前6位)
df['地區(qū)碼'] = df['身份證號'].str[:6]
print(df)
4. 大小寫與空白處理
# ===== 大小寫轉(zhuǎn)換 =====
df = pd.DataFrame({
'text': ['Hello World', 'PYTHON', 'machine learning', 'Data Science']
})
print(df['text'].str.lower()) # 全部小寫
print(df['text'].str.upper()) # 全部大寫
print(df['text'].str.title()) # 首字母大寫
print(df['text'].str.capitalize()) # 句子首字母大寫
print(df['text'].str.swapcase()) # 大小寫互換
# ===== 空白處理 =====
df2 = pd.DataFrame({
'text': [' hello ', 'world\n', '\tpython\t', ' data science ']
})
print(df2['text'].str.strip()) # 去除首尾空白
print(df2['text'].str.lstrip()) # 去除左側(cè)空白
print(df2['text'].str.rstrip()) # 去除右側(cè)空白
5. 對齊與填充
# ===== 字符串對齊 =====
df = pd.DataFrame({
'編號': ['1', '23', '456', '7890']
})
# 右對齊,左邊用 0 填充到 5 位
print(df['編號'].str.pad(5, side='left', fillchar='0'))
# 輸出:00001, 00023, 00456, 07890
# 等價方法:zfill
print(df['編號'].str.zfill(5)) # 更常用!
正則表達式(Regular Expression)基礎
1. 什么是正則表達式?
正則表達式是一種用模式來匹配字符串的語言。它用簡短的符號組合描述字符串的格式規(guī)則。
比喻:如果你要找"所有以 138 開頭的11位手機號",在正則中就是 138\d{8}。
2. 常用正則元字符
| 符號 | 含義 | 示例 | 匹配 |
|---|---|---|---|
. | 任意字符(除換行) | a.c | abc, a_c, a c |
\d | 數(shù)字(0-9) | \d\d | 12, 99 |
\w | 字母、數(shù)字、下劃線 | a\wb | axb, a1b, a_b |
\s | 空白字符 | a\sb | a b |
^ | 字符串開頭 | ^abc | abc… |
$ | 字符串結尾 | xyz$ | …xyz |
* | 0 次或多次 | ab*c | ac, abc, abbc |
+ | 1 次或多次 | ab+c | abc, abbc(不匹配 ac) |
? | 0 次或 1 次 | ab?c | ac, abc |
{n} | 恰好 n 次 | \d{4} | 1234 |
{n,m} | n 到 m 次 | \d{2,4} | 12, 123, 1234 |
[...] | 字符集合 | [abc] | a 或 b 或 c |
(?:) | 非捕獲分組 | - | - |
| ` | ` | 或 | `cat |
3. 在 Pandas 中使用正則
# ===== str.contains() —— 正則匹配 =====
df = pd.DataFrame({
'郵箱': ['abc@email.com', 'xyz@work.cn', 'test123@school.edu', 'admin@company.org', 'user']
})
# 匹配郵箱格式
mask = df['郵箱'].str.contains(r'^[\w.]+@[\w.]+\.\w+$', regex=True)
print(df[mask])
# ===== str.match() —— 從頭匹配 =====
# match 從字符串開頭開始匹配
df2 = pd.DataFrame({
'文本': ['123-456-7890', 'ABC-DEF', '42-99', 'xyz', '100-200-300']
})
# 匹配"數(shù)字-數(shù)字"格式(從開頭)
print(df2['文本'].str.match(r'^\d+-\d+'))
# ===== str.extract() —— 提取匹配內(nèi)容 =====
df3 = pd.DataFrame({
'日志': ['2024-01-15 INFO: User login', '2024-02-20 ERROR: Timeout',
'2024-03-10 WARN: Disk full', '2024-04-05 DEBUG: Test']
})
# 提取日期和日志級別
extracted = df3['日志'].str.extract(r'(\d{4}-\d{2}-\d{2})\s+(\w+):')
extracted.columns = ['日期', '級別']
print(extracted)
# ===== str.extractall() —— 提取所有匹配 =====
df4 = pd.DataFrame({
'文本': ['價格是100元,折扣價80元', '售價200元,運費15元', '免費']
})
# 提取所有數(shù)字
matches = df4['文本'].str.extractall(r'(\d+)元')
print(matches)
實戰(zhàn)場景:常見文本處理任務
場景 1:郵箱提取
# 從文本中提取郵箱地址
df = pd.DataFrame({
'描述': [
'聯(lián)系人:張三,郵箱 zhang@company.com,電話 138xxxx',
'郵箱:li.work@gmail.com,請發(fā)郵件聯(lián)系',
'無聯(lián)系方式',
'admin@school.edu.cn 是官方郵箱',
'請發(fā)郵件到 test123@work.org 或 backup@test.com'
]
})
# 提取第一個郵箱地址
df['郵箱'] = df['描述'].str.extract(r'([\w.+-]+@[\w.-]+\.\w+)')
print(df)
場景 2:地址解析
# 將地址拆分為省、市、區(qū)
df = pd.DataFrame({
'完整地址': [
'廣東省廣州市天河區(qū)天河路1號',
'北京市朝陽區(qū)建國路88號',
'浙江省杭州市西湖區(qū)文三路100號',
'上海市浦東新區(qū)世紀大道1號'
]
})
# 用正則提?。ê喕妫瑢嶋H地址格式更復雜)
addr = df['完整地址'].str.extract(
r'(?P<省>[^省]+省|(?P<直轄市>[北上廣][^\s]+?市))(?P<市>[^市]+市)(?P<區(qū)>[^區(qū)]+區(qū))'
)
print(addr)
# 更簡單的方式:固定模式拆分
# 假設格式都是"省/市+市名+區(qū)名+詳細地址"
df['省份'] = df['完整地址'].str.extract(r'^([^省市]+[省]?)(?:省)?(.+?)市')
場景 3:數(shù)據(jù)清洗與標準化
# 清理不規(guī)范的電話號碼
df = pd.DataFrame({
'電話': [
'138-0000-1234',
'139 0000 5678',
'13600009012',
'186(0000)3456',
'185-0000-7890',
'+86 138 0000 1234'
]
})
# 去除所有非數(shù)字字符
df['電話_清理'] = df['電話'].str.replace(r'\D', '', regex=True)
# 去掉國家代碼
df['電話_清理'] = df['電話_清理'].str.replace(r'^86', '', regex=True)
# 標準化格式
df['電話_標準'] = df['電話_清理'].str.replace(
r'(\d{3})(\d{4})(\d{4})', r'\1-\2-\3', regex=True
)
print(df)
場景 4:關鍵詞提取與分類
# 根據(jù)評論內(nèi)容自動分類
df = pd.DataFrame({
'評論': [
'這個手機屏幕很大,拍照效果很好',
'電池太不耐用了,半天就沒電',
'價格太貴了,性價比不高',
'物流很快,包裝也很好',
'音質(zhì)不錯,但是低音效果一般',
'運行速度很快,打游戲很流暢'
]
})
# 定義關鍵詞
keywords = {
'屏幕': '顯示',
'拍照': '拍照',
'電池': '續(xù)航',
'沒電': '續(xù)航',
'價格': '價格',
'貴': '價格',
'性價比': '價格',
'物流': '物流',
'包裝': '物流',
'音質(zhì)': '音質(zhì)',
'低音': '音質(zhì)',
'速度': '性能',
'流暢': '性能'
}
# 創(chuàng)建一個匹配函數(shù)
def classify_review(text):
categories = []
for keyword, category in keywords.items():
if keyword in str(text):
categories.append(category)
return list(set(categories)) # 去重
df['分類'] = df['評論'].apply(classify_review)
print(df)
高級正則技巧
1. 命名分組
# 使用命名分組提取信息
df = pd.DataFrame({
'日期文本': ['生于1990年05月20日', '入職于2020年01月15日', '更新于2024年03月10日']
})
result = df['日期文本'].str.extract(
r'生于|入職于|更新于(?P<年>\d{4})年(?P<月>\d{2})月(?P<日>\d{2})日'
)
# 更準確的寫法:
result = df['日期文本'].str.extract(
r'(?P<年>\d{4})年(?P<月>\d{2})月(?P<日>\d{2})日'
)
print(result)
2. 零寬斷言(Lookaround)
# 正向先行斷言:匹配后面跟著特定內(nèi)容的字符串
df = pd.DataFrame({
'文本': ['價格是100元', '重量是200克', '時間是30分鐘', '長度是50厘米']
})
# 提取"是"和"克"之間的數(shù)字
df['數(shù)字'] = df['文本'].str.extract(r'(?<=是)\d+(?=克)')
print(df)
# 只有"重量是200克"能匹配到 200
3. 多模式匹配
# 同時用多個正則進行替換
df = pd.DataFrame({
'文本': ['[重要] 會議通知 (2024)', '{內(nèi)部} 財務報表 【加密】']
})
# 去除所有括號及其內(nèi)容
df['清理后'] = df['文本'].str.replace(r'[\[\]\(\)\{\}【】].*?[\]\)\}】]', '', regex=True)
df['清理后'] = df['清理后'].str.strip()
print(df)
實戰(zhàn)練習
練習 1:學生信息清洗
題目:以下學生信息數(shù)據(jù)格式混亂,請清洗。
# 參考答案
import pandas as pd
import numpy as np
df = pd.DataFrame({
'姓名': [' 張三 ', '李四', ' 王五 ', '趙六 ', '孫七'],
'郵箱': ['ZHANG@EMAIL.COM', 'li@work.CN', 'wang@SCHOOL.edu', 'zHAO@gmail.COM', 'sun@company.ORG'],
'成績': ['95分', '87分', '92分', '78分', '88分']
})
# 1. 去除姓名前后空白
df['姓名'] = df['姓名'].str.strip()
# 2. 郵箱標準化為首字母大寫
df['郵箱'] = df['郵箱'].str.lower()
# 3. 提取成績數(shù)字并轉(zhuǎn)為整數(shù)
df['成績'] = df['成績'].str.replace('分', '').astype(int)
print("清洗后:")
print(df)
print(f"\n數(shù)據(jù)類型:\n{df.dtypes}")
練習 2:日志文件解析
題目:解析以下服務器日志數(shù)據(jù)。
# 參考答案
import pandas as pd
df = pd.DataFrame({
'日志': [
'[2024-01-15 10:30:22] ERROR 192.168.1.100 Connection timeout',
'[2024-01-15 10:31:05] INFO 192.168.1.101 Request processed',
'[2024-01-15 10:32:18] WARNING 192.168.1.102 Disk usage high',
'[2024-01-15 10:33:45] ERROR 192.168.1.100 Connection timeout',
'[2024-01-15 10:35:00] INFO 192.168.1.103 User login'
]
})
# 1. 提取時間、級別、IP、消息
parsed = df['日志'].str.extract(
r'\[(?P<時間>[\d-]+ [\d:]+)\]\s+(?P<級別>\w+)\s+(?P<IP>[\d.]+)\s+(?P<消息>.+)'
)
print("解析結果:")
print(parsed)
# 2. 統(tǒng)計各錯誤級別數(shù)量
print("\n錯誤級別統(tǒng)計:")
print(parsed['級別'].value_counts())
# 3. 統(tǒng)計每個 IP 的錯誤次數(shù)
error_df = parsed[parsed['級別'] == 'ERROR']
print("\n各IP錯誤次數(shù):")
print(error_df['IP'].value_counts())
練習 3:商品信息提取
題目:從商品描述中提取關鍵信息。
# 參考答案
import pandas as pd
df = pd.DataFrame({
'商品描述': [
'Apple iPhone 15 Pro 256GB 深空黑色 ¥8999',
'華為 Mate 60 Pro 512GB 雅丹黑 ¥6999',
'小米14 12GB+256GB 黑色 ¥3999',
'Samsung Galaxy S24 128GB ¥5499',
'OPPO Find X7 Ultra 16GB+512GB ¥5999'
]
})
# 提取品牌(第一個英文單詞或中文字)
df['品牌'] = df['商品描述'].str.extract(r'^([A-Za-z]+|[\u4e00-\u9fa5]{1,4})')
# 提取價格
df['價格'] = df['商品描述'].str.extract(r'¥(\d+)').astype(int)
# 提取存儲容量
df['存儲'] = df['商品描述'].str.extract(r'(\d+GB)')
# 提取型號關鍵詞
df['型號'] = df['商品描述'].str.extract(r'(?:iPhone|Mate|Galaxy|Find|小米|華為)\s*(\w+)')
print(df[['品牌', '型號', '存儲', '價格']])
總結
本節(jié)我們系統(tǒng)學習了 Pandas 中的字符串處理與正則匹配:
str 訪問器常用方法:
str.upper/lower/title—— 大小寫轉(zhuǎn)換str.strip/lstrip/rstrip—— 空白處理str.split(expand=True)—— 分割為多列str.contains/startswith/endswith—— 條件判斷str.replace—— 替換str.extract—— 正則提取str.pad/zfill—— 對齊填充
正則表達式核心:
- 元字符:
\d、\w、\s、.、^、$ - 量詞:
*、+、?、{n}、{n,m} - 分組:
()、命名分組(?P<name>...) - 在 Pandas 中的
str.extract()、str.contains()、str.replace()
到此這篇關于Pandas中字符串處理的核心方法與正則匹配實戰(zhàn)教學的文章就介紹到這了,更多相關Pandas字符串處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python中語音轉(zhuǎn)文字相關庫介紹(最新推薦)
Python的speech_recognition庫是一個用于語音識別的Python包,它可以使Python程序能夠識別和翻譯來自麥克風、音頻文件或網(wǎng)絡流的語音,這篇文章主要介紹了Python中語音轉(zhuǎn)文字相關庫介紹,需要的朋友可以參考下2023-05-05
Python 數(shù)據(jù)庫操作 SQLAlchemy的示例代碼
這篇文章主要介紹了Python 數(shù)據(jù)庫操作 SQLAlchemy的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02
pandas修改DataFrame列名的實現(xiàn)方法
這篇文章主要介紹了pandas修改DataFrame列名的實現(xiàn)方法, 文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-02-02
Transpose 數(shù)組行列轉(zhuǎn)置的限制方式
今天小編就為大家分享一篇Transpose 數(shù)組行列轉(zhuǎn)置的限制方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
python3中的eval和exec的區(qū)別與聯(lián)系
這篇文章主要介紹了python3中的eval和exec的區(qū)別與聯(lián)系,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
Python中的np.random.seed()隨機數(shù)種子問題及解決方法
隨機數(shù)種子,相當于我給接下來需要生成的隨機數(shù)一個初值,按照我給的這個初值,按固定順序生成隨機數(shù),接下來通過本文給大家介紹Python中的np.random.seed()隨機數(shù)種子問題,需要的朋友可以參考下2022-04-04

