You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效拆分Pandas DataFrame中含转义逗号的分隔值?

问题

我从API获取CSV格式的数据并读取为Pandas DataFrame,代码如下:

import io
import requests
import pandas as pd
response = requests.get(url, params=params, headers=headers)
df = pd.read_csv(io.StringIO(response.content.decode("utf-8")))

检查后发现DataFrame中大量单元格包含长度不一的逗号分隔值,这些值未被引号包裹,部分值还包含反斜杠转义的逗号。示例数据如下:

eg = pd.DataFrame({"a": ["A single value", "Three,separate,values", "This value contains a \\,, and so does\\, this one", pd.NA], "b": ["", pd.NA, "2,3,4","12,17"]})

我需要将这些单元格拆分为单元格内的列表或单独列,目前用逐单元格处理的方式实现,代码如下:

import csv
def to_list_of_strings(cell):
    if pd.isnull(cell):
        return []
    elif "," in cell:
        return next(csv.reader(io.StringIO(cell), escapechar="\\"))
    else:
        return [cell]

result = eg.a.apply(to_list_of_strings)

(使用csv模块是为了处理引号等其他可能的解析需求)
期望结果(list(result)的输出):

[['A single value'],
 ['Three', 'separate', 'values'],
 ['This value contains a ,', ' and so does, this one'],
 []]

但这种逐单元格处理的方式在处理多列及数千行数据时速度较慢,请问是否存在更快的矢量化实现方式?

优化方案

方法1:正则表达式结合str.split实现矢量化拆分

利用正则匹配未被反斜杠转义的逗号作为分隔符,直接调用Pandas的矢量化字符串方法,避免逐行循环:

import pandas as pd

# 正则匹配:匹配不是由反斜杠前置的逗号
pattern = r'(?<!\\),'

def split_with_escape(col):
    # 标记空值和空字符串
    mask = col.isna() | (col == "")
    # 对非空值按正则拆分
    split_col = col.str.split(pattern)
    # 将空值/空字符串对应位置替换为空列表
    split_col = split_col.where(~mask, pd.Series([[]]*len(col), index=col.index))
    # 还原转义的逗号:把\\,替换为,
    split_col = split_col.apply(lambda lst: [s.replace(r'\,', ',') for s in lst])
    return split_col

# 处理目标列
result = split_with_escape(eg['a'])

这种方式完全基于Pandas原生矢量化操作,速度比apply逐行处理快数倍,数据量越大优势越明显。

方法2:批量调用csv.reader提升解析效率

如果需要保留csv模块的完整解析能力(比如处理引号、复杂转义场景),可以将整列数据拼接成标准CSV多行文本,一次性交给csv.reader解析,减少重复IO操作的开销:

import io
import csv
import pandas as pd

def batch_csv_parse(col):
    # 空值替换为空白字符串,避免csv解析报错
    processed_col = col.fillna("")
    # 将列中每个元素转为一行,拼接成CSV格式文本
    csv_text = '\n'.join(processed_col)
    # 一次性解析所有行
    parsed_rows = list(csv.reader(io.StringIO(csv_text), escapechar='\\'))
    # 将解析出的[""](对应原空字符串/空值)转为空列表
    parsed_rows = [row if row != [""] else [] for row in parsed_rows]
    return pd.Series(parsed_rows, index=col.index)

# 处理目标列
result = batch_csv_parse(eg['a'])

这种方法通过批量处理减少了多次创建io.StringIO和调用csv.reader的开销,效率比逐单元格处理提升显著,同时保留csv模块的解析兼容性。

方法3:用numpy.vectorize封装原函数(折中方案)

如果不想修改原有解析逻辑,可以用numpy.vectorize对原函数进行矢量化封装,虽然底层仍是循环,但内部优化比Pandas的apply更高效,适合快速改造原有代码:

import numpy as np
import csv
import io
import pandas as pd

def to_list_of_strings(cell):
    if pd.isnull(cell) or cell == "":
        return []
    elif "," in cell:
        return next(csv.reader(io.StringIO(cell), escapechar="\\"))
    else:
        return [cell]

# 矢量化封装原函数
vectorized_parse = np.vectorize(to_list_of_strings, otypes=[object])
# 应用到目标列
result = pd.Series(vectorized_parse(eg['a']), index=eg.index)

内容的提问来源于stack exchange,提问作者Stuart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:53:19