大家好,我是正在实战各种AI项目 的程序员晚枫。
今天学习Pandas中的字符串处理 ,这是清洗文本数据的必备技能。
无论是处理用户输入、解析日志文件,还是提取关键信息,掌握这些技巧都能让你事半功倍。
.str访问器 Pandas为Series提供了.str访问器,可以像操作Python字符串一样处理整列数据。
1 2 3 4 5 6 7 8 import pandas as pddf = pd.DataFrame({ '姓名' : [' 张三 ' , '李四' , '王五' ], '邮箱' : ['zhangsan@example.com' , 'LiSi@test.COM' , 'wangwu@company.cn' ], '电话' : ['138-0013-8000' , '13900138001' , '137 0013 7000' ], '地址' : ['北京市朝阳区' , '上海市浦东新区' , '广州市天河区' ] })
1. 大小写转换 1 2 3 4 5 6 7 8 df['邮箱_小写' ] = df['邮箱' ].str .lower() df['邮箱_大写' ] = df['邮箱' ].str .upper() df['姓名_规范' ] = df['姓名' ].str .title()
2. 去除空白字符 1 2 3 4 5 6 7 8 9 10 11 df['姓名_去空格' ] = df['姓名' ].str .strip() df['姓名' ] = df['姓名' ].str .lstrip() df['姓名' ] = df['姓名' ].str .rstrip() df['电话_纯数字' ] = df['电话' ].str .replace(' ' , '' ).str .replace('-' , '' )
3. 字符串替换 1 2 3 4 5 6 7 8 df['电话_标准' ] = df['电话' ].str .replace('-' , ' ' ) df['电话_数字' ] = df['电话' ].str .replace(r'\D' , '' , regex=True ) df['地址_简写' ] = df['地址' ].str .replace('市' , '' ).str .replace('区' , '' )
4. 分割与提取 1 2 3 4 5 6 7 8 9 10 11 df[['城市' , '区县' ]] = df['地址' ].str .split('市' , expand=True ) df['邮箱域名' ] = df['邮箱' ].str .split('@' ).str [1 ] df['区号' ] = df['电话_数字' ].str [:3 ] df['运营商' ] = df['电话_数字' ].str .extract(r'(1[38]\d)' )
5. 包含与匹配 1 2 3 4 5 6 7 8 9 10 11 df['是移动' ] = df['电话' ].str .contains('138|139' ) df['是北京' ] = df['地址' ].str .startswith('北京' ) df['是com邮箱' ] = df['邮箱' ].str .endswith('.com' ) df['有效邮箱' ] = df['邮箱' ].str .match (r'^[\w\.-]+@[\w\.-]+\.\w+$' )
6. 查找与计数 1 2 3 4 5 6 7 8 df['@位置' ] = df['邮箱' ].str .find('@' ) df['e的数量' ] = df['邮箱' ].str .count('e' ) df['邮箱长度' ] = df['邮箱' ].str .len ()
7. 填充对齐 1 2 3 4 5 6 7 8 9 df['订单号' ] = df['订单号' ].str .zfill(8 ) df['姓名_居中' ] = df['姓名' ].str .center(10 , '*' ) df['姓名_左对齐' ] = df['姓名' ].str .ljust(10 ) df['姓名_右对齐' ] = df['姓名' ].str .rjust(10 )
8. 条件筛选 1 2 3 4 5 6 7 8 gmail_users = df[df['邮箱' ].str .contains('gmail' , na=False )] beijing_mobile = df[ (df['地址' ].str .contains('北京' )) & (df['电话' ].str .contains('138' )) ]
9. 高级提取 1 2 3 4 5 6 texts = pd.Series(['订单A123金额¥500' , '订单B456金额¥800' ]) orders = texts.str .extractall(r'订单(\w+)金额¥(\d+)' ) df[['用户名' , '域名' ]] = df['邮箱' ].str .extract(r'(?P<user>[\w\.]+)@(?P<domain>[\w\.]+)' )
10. 实战: messy 数据清洗 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import pandas as pdimport remessy_data = pd.DataFrame({ '客户信息' : [ ' 张三 | zhangsan@EXAMPLE.com | 138-0013-8000 | 北京 朝阳 ' , '李四,lisi@test.COM,13900138001,上海浦东' , '王五 | wangwu@Company.cn | 137 0013 7000 | 广州-天河' ] }) print ("原始数据:" )print (messy_data)def clean_customer_info (info ): """清洗客户信息""" info = re.sub(r'[,|]' , ' ' , info) parts = info.split() cleaned = [] for part in parts: part = part.strip() if '@' in part: part = part.lower() elif part.replace('-' , '' ).replace(' ' , '' ).isdigit(): part = re.sub(r'\D' , '' , part) cleaned.append(part) return cleaned expanded = messy_data['客户信息' ].apply(clean_customer_info) messy_data[['姓名' , '邮箱' , '电话' , '地址' ]] = pd.DataFrame(expanded.tolist()) print ("\n清洗后:" )print (messy_data[['姓名' , '邮箱' , '电话' , '地址' ]])
性能对比:向量化的str方法 vs apply 1 2 3 4 5 6 7 8 9 10 11 12 13 import pandas as pdimport numpy as nps = pd.Series(['Hello World' ] * 100000 ) %timeit s.str .lower() %timeit s.apply(lambda x: x.lower()) %timeit pd.Series([x.lower() for x in s])
进阶用法 正则提取与替换 1 2 3 4 5 6 7 8 9 10 11 12 13 df = pd.DataFrame({ 'text' : ['订单#12345金额¥500' , '订单#67890金额¥1200' , '订单#11111金额¥300' ] }) df['order_id' ] = df['text' ].str .extract(r'#(\d+)' ) df['amount' ] = df['text' ].str .extract(r'¥(\d+)' ).astype(float ) df[['prefix' , 'number' ]] = df['text' ].str .extract(r'(订单)#(\d+)' )
文本清洗流水线 1 2 3 4 5 6 7 8 df['address_clean' ] = (df['address' ] .str .strip() .str .replace(r'\s+' , ' ' , regex=True ) .str .replace('省' , '' , regex=False ) .str .replace('市' , '' , regex=False ) .str .lower() )
避坑指南 ❌ 坑1:NaN和str方法 1 2 3 4 5 6 s = pd.Series(['hello' , np.nan, 'WORLD' ]) s.str .lower() s.str .contains('hello' ) s.str .contains('hello' , na=False )
❌ 坑2:正则特殊字符 1 2 3 4 5 text = 'price: $100.00' text.str .contains('$100' ) text.str .contains('$100' , regex=False ) text.str .contains(r'\$100' )
实战案例:清洗用户评论数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import pandas as pdimport numpy as npnp.random.seed(42 ) n = 5000 comments = pd.DataFrame({ 'user' : [f'@用户{i:04d} ' for i in range (n)], 'comment' : [ f'这个产品{np.random.choice(["真的很好用" , "还不错" , "一般般" , "太差了" ])} !' f'评分:{np.random.randint(1 , 6 )} 星 ' f'#{np.random.choice(["推荐" , "不推荐" , "回购" , "踩雷" ])} ' for i in range (n) ], 'date' : pd.date_range('2025-01-01' , periods=n, freq='30min' ) }) comments['rating' ] = comments['comment' ].str .extract(r'评分:(\d)' ).astype(int ) comments['tag' ] = comments['comment' ].str .extract(r'#(\w+)' ) def classify_sentiment (text ): if any (w in text for w in ['很好' , '不错' , '推荐' , '回购' ]): return '正面' elif any (w in text for w in ['差' , '踩雷' , '不推荐' ]): return '负面' return '中性' comments['sentiment' ] = comments['comment' ].apply(classify_sentiment) print ("=== 评论分析 ===" )print (f"评分分布:\n{comments['rating' ].value_counts().sort_index()} " )print (f"\n情感分布:\n{comments['sentiment' ].value_counts()} " )print (f"\n标签分布:\n{comments['tag' ].value_counts()} " )
文本分析实战技巧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 df['has_discount' ] = df['comment' ].str .contains('打折|优惠|折扣|促销' , regex=True ) df['has_complaint' ] = df['comment' ].str .contains('差|烂|退款|投诉' , regex=True ) df['comment_length' ] = df['comment' ].str .len () df['word_count' ] = df['comment' ].str .split().str .len () df['phone_masked' ] = df['phone' ].str .replace(r'(\d{3})\d{4}(\d{4})' , r'****' , regex=True ) df['city' ] = df['address' ].str .extract(r'(北京|上海|广州|深圳|成都|重庆|杭州|武汉)' ) df['email_domain' ] = df['email' ].str .split('@' ).str [1 ] from pypinyin import pin, lazy_pinyindf['pinyin' ] = df['name' ].apply(lambda x: '' .join(lazy_pinyin(x)))
文本清洗checklist 在处理实际文本数据时,按这个checklist逐一检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def clean_text_column (s ): '''文本列清洗标准流程''' s = s.str .strip() s = s.str .lower() s = s.str .replace(r'\s+' , ' ' , regex=True ) s = s.str .replace(r'[^\w\s]' , '' , regex=True ) s = s.str .replace(',' , ',' ).str .replace('。' , '.' ) s = s.fillna('' ) return s df['clean_name' ] = clean_text_column(df['name' ])
常见文本处理场景 1 2 3 4 5 6 7 8 9 10 11 12 df['phone' ] = df['text' ].str .extract(r'(1[3-9]\d{9})' ) df['email' ] = df['text' ].str .extract(r'([\w.]+@[\w.]+)' ) df['amount' ] = df['text' ].str .extract(r'(\d+\.?\d*)[元万]' ).astype(float ) from difflib import SequenceMatcherdf['similarity' ] = df.apply(lambda r: SequenceMatcher(None , r['text_a' ], r['text_b' ]).ratio(), axis=1 )
下节预告 下一课我们将学习高效数据处理技巧 ,掌握优化Pandas性能的方法。
👉 继续阅读:Pandas高效数据处理技巧
💬 加入学习交流群 扫码加入Python学习交流群 ,和数千名同学一起进步:
👉 点击加入交流群
群里不定期分享:
数据分析实战案例 Python学习资料 求职面试经验 行业最新动态 推荐:AI Python数据分析实战营 🎁 限时福利 :送《利用Python进行数据分析》实体书
👉 点击了解详情
课程导航 上一篇: Pandas数据变换-时间序列处理
下一篇: Pandas高效数据处理技巧
PS:文本数据清洗占数据分析工作的很大一部分。熟练掌握.str访问器,效率提升10倍。
📚 推荐教材 主教材 :《Excel+Python 飞速搞定数据分析与处理(图灵出品)》
💬 联系我 主营业务 :AI 编程培训、企业内训、技术咨询
🎓 AI 编程实战课程 想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!