Python ETL处理亚马逊评论数据遇类型错误,手动循环性能堪忧
解决DataFrame.apply()正则报错及性能优化问题
问题原因
报错expected string or bytes-like object, got 'float'是因为目标数据列中存在非字符串类型的值,最常见的是NaN(pandas中缺失值默认以float类型的NaN存储),而正则表达式函数只能处理字符串/字节对象,遇到float类型时就会触发错误。
手动遍历每行数据性能极差,是因为Python循环本身效率低,没有利用pandas的矢量化优化能力。
解决方案
1. 先处理数据类型与缺失值
先把目标列统一转为字符串,并填充缺失值,从根源避免类型错误:
import pandas as pd # 加载数据集 df = pd.read_csv('amazon_reviews.csv') # 填充NaN为空字符串,再强制转为字符串类型 df['review_body'] = df['review_body'].fillna('').astype(str)
2. 用矢量化str方法替代apply(性能最优)
pandas的str属性提供了一系列矢量化的字符串处理方法,底层用C实现,比逐行的apply快数倍甚至数十倍,完全避免手动遍历的性能问题。
示例:正则替换特殊字符
原来的apply写法(易报错+性能差):
import re df['clean_review'] = df['review_body'].apply(lambda x: re.sub(r'[^\w\s]', '', x))
替换为矢量化str.replace:
df['clean_review'] = df['review_body'].str.replace(r'[^\w\s]', '', regex=True)
示例:正则提取数字
原来的apply写法:
df['review_numbers'] = df['review_body'].apply(lambda x: re.findall(r'\d+', x))
替换为矢量化str.findall:
df['review_numbers'] = df['review_body'].str.findall(r'\d+')
3. 复杂逻辑用swifter加速apply
如果处理逻辑过于复杂,无法用str方法实现,可借助swifter库自动优化apply的执行效率——它会自动判断是否可以矢量化执行,不行则用Dask进行并行处理。
步骤:
- 安装库:
pip install swifter - 使用示例:
import swifter import re def complex_cleaning(text): # 自定义复杂处理逻辑,比如多步正则+长度判断 text = re.sub(r'\s+', ' ', text) text = text.strip().lower() if len(text) < 10: return None return text # 自动优化执行 df['clean_review'] = df['review_body'].swifter.apply(complex_cleaning)
性能对比
- 矢量化
str方法:性能最优,比手动遍历快10~100倍 swifter优化的apply:性能接近矢量化方法,适合复杂逻辑- 原生
apply:性能中等,比手动遍历快2~5倍 - 手动遍历:性能最差,完全不推荐
内容的提问来源于stack exchange,提问作者Filipy
相关产品推荐
相关产品推荐

