使用Pandas读取含嵌套结构的CSV:正则分隔符问题排查
解决Pandas解析含列表的CSV列分隔问题
首先来说说你那个正则表达式的问题:
你的表达式[,](?!(.+)?\])逻辑走偏了。你想匹配的是用来分隔列的、不在方括号内部的逗号,但这个表达式的判断条件是“逗号后面不跟着任意字符+]”——可实际上,几乎所有列分隔的逗号后面的文本里都会包含](比如你行里最后那个[14,7]的]),导致这个负向前瞻几乎总是不成立,自然匹配不到任何需要的分隔符。
接下来给你两个靠谱的解决方案,从简便到灵活:
方案1:用正确的正则作为分隔符(最直接)
我们需要匹配的是不在方括号内部的逗号,可以用这个正则:,(?=(?:[^[]*\])*[^[]*$)。它的逻辑是:确保逗号后面的所有内容里,方括号都是成对闭合的,也就是说这个逗号不在任何未闭合的[...]块里。
在Pandas里这样用:
import pandas as pd # 注意要指定engine='python',因为默认的c引擎不支持复杂正则分隔符 df = pd.read_csv('your_file.csv', sep=r',(?=(?:[^[]*\])*[^[]*$)', engine='python', skipinitialspace=True)
skipinitialspace=True是用来去掉逗号后面的空格,让列内容更干净。
方案2:先替换内部逗号再分隔(更易理解)
如果你对正则有点头疼,可以换个思路:先把方括号里的逗号替换成其他临时字符(比如分号),然后按普通逗号分隔,最后再替换回来:
import pandas as pd import re # 读取文件内容 with open('your_file.csv', 'r') as f: content = f.read() # 替换所有方括号内的逗号为分号 modified_content = re.sub(r'\[([^\]]+)\]', lambda match: match.group(0).replace(',', ';'), content) # 用StringIO把修改后的内容转成可读取的对象,按逗号分隔 df = pd.read_csv(pd.io.common.StringIO(modified_content), sep=',\s*') # 把分号替换回逗号,还原列表格式 df.iloc[:, 3:] = df.iloc[:, 3:].apply(lambda col: col.str.replace(';', ','))
额外优化:把列表字符串转成实际Python列表
如果你还想把[12,5]这种字符串直接转成Python列表,可以用ast.literal_eval来解析:
import ast # 对需要的列应用解析 df['col4'] = df['col4'].apply(ast.literal_eval) df['col5'] = df['col5'].apply(ast.literal_eval)
这样之后,你就可以直接像操作列表一样操作这些列的内容了。
内容的提问来源于stack exchange,提问作者Jannik
相关产品推荐
相关产品推荐

