Python中对DataFrame应用函数触发ValueError的解决方法
问题原因分析
你遇到的ValueError核心原因是:apply是逐行传递单个手机号值给函数,但你的vanity_def函数却一直在操作整个DataFrame的列。
vanity_class.MNM_MOBILE_NUMBER.astype(str).str.match(...)返回的是一个布尔Series,而if语句无法直接判断Series的真假(pandas不知道你要判断any()还是all()),因此抛出"真值歧义"的错误。同时,函数里直接修改整个DataFrame列的逻辑也是错误的——apply不需要你全局赋值,只需要返回当前行的分类结果即可。
修正方案
1. 核心调整方向
- 函数接收单个手机号值,先转为字符串
- 使用Python标准库
re对单个字符串做正则匹配 - 函数仅返回当前手机号对应的分类标签,不全局修改DataFrame
2. 修正后的完整代码
import pandas as pd import re # 创建原始DataFrame numbers = [539249751,530246444,539246655,539209759,538849098] vanity_class = pd.DataFrame(numbers, columns=['MNM_MOBILE_NUMBER']) # 重写分类函数 def vanity_def(mobile_num): num_str = str(mobile_num) # Diamond 分类规则 diamond_patterns = [ r'^5(\d)\1{7}', r'^5(?!(\d)\1)\d(\d)\2{6}$', r'.{2}(?!(\d)\1)\d(\d)\2{5}$', r'^\d*(\d)(\d)(?:\1\2){3}\d*$', r'^5((\d)\2{3})((\d)\4{3})$', r'.{3}(1234567$)' ] if any(re.match(p, num_str) for p in diamond_patterns): return 'Diamond' # Gold 分类规则 gold_patterns = [ r'.{3}(?!(\d)\1)\d(\d)\2{4}$', r'^(?!(\d)\1)\d((\d)\3{6})(?!\3)\d$', r'\d(\d)\1(\d)\2(\d)\3(\d)\4' ] if any(re.match(p, num_str) for p in gold_patterns): return 'Gold' # Silver 分类规则 silver_patterns = [ r"^5(?!(\d)\1)\d((\d)\3{5})(?!\3)\d", r"\b\d\d(\d)(?!\1)(\d)\2\2(\d)\3\3\b" ] if any(re.match(p, num_str) for p in silver_patterns): return 'Silver' # Bronze 分类规则 bronze_patterns = [ r'.{3}(123456$)', r'^5.{3}(?!(\d)\1)\d(\d)\2{3}$', r'\d\d(?!(\d)\1)\d((\d)\3{4})(?!\3)\d', r'\b\d\d(\d)(\d(00))\2', r'^5(\d(000))(\d(000))' ] if any(re.match(p, num_str) for p in bronze_patterns): return 'Bronze' # Special 分类规则 special_patterns = [ r"\d\d(?!(\d)\1)\d((\d)\3{3})(?!\3)\d", r"\d\d\d(\d\d)(?!\1)(\d)\2(\d)\3\b", r"^\d*(\d)(\d)(?:\1\2){2}\d*$" ] if any(re.match(p, num_str) for p in special_patterns): return 'Special' # Economy 分类规则 economy_patterns = [ r'.{4}(45678$)', r'.{5}(?!(\d)\1)\d(\d){3}', r'.{5}(1234$)', r'(?!.*(\d)\1(\d)\2(\d)\3).{4}\d(\d)\4(\d)\5', r'^\d*(\d)(\d)(?:\1\2){1}\d*$' ] if any(re.match(p, num_str) for p in economy_patterns): return 'Economy' return 'Non Classified' # 应用函数生成新列 vanity_class['MNC_New_Class'] = vanity_class['MNM_MOBILE_NUMBER'].apply(vanity_def)
3. 关键优化点
- 把同分类的正则整理成列表,用
any()实现"或"逻辑,和你原代码的|效果一致 - 使用
re.match和pandas的str.match行为对齐(从字符串开头匹配),如果需要任意位置匹配,可替换为re.search - 函数仅返回当前行的结果,由
apply自动组合成新列,避免全局修改DataFrame的错误逻辑
内容的提问来源于stack exchange,提问作者Leena
相关产品推荐
相关产品推荐

