python - 有效地将数据从 CSV 读取到具有多个分隔符的数据框中

标签 python pandas performance csv dataframe

我有一个笨拙的 CSV 文件,它有多个分隔符:非数字部分的分隔符是 ',',数字部分的分隔符是 ';'。我想尽可能高效地仅从数字部分构建数据框。

我做了 5 次尝试:其中,利用 pd.read_csvconverters 参数,使用正则表达式和 engine='python' ,使用 str.replace。它们都比读取没有转换的整个 CSV 文件慢 2 倍以上。这对我的用例来说太慢了。

我知道这种比较不是对等的,但它确实表明整体性能不佳不是由 I/O 驱动的。有没有更有效的方法将数据读入数字 Pandas 数据框?或者等效的 NumPy 数组?

以下字符串可用于基准测试目的。

# Python 3.7.0, Pandas 0.23.4

from io import StringIO
import pandas as pd
import csv

# strings in first 3 columns are of arbitrary length
x = '''ABCD,EFGH,IJKL,34.23;562.45;213.5432
MNOP,QRST,UVWX,56.23;63.45;625.234
'''*10**6

def csv_reader_1(x):
    df = pd.read_csv(x, usecols=[3], header=None, delimiter=',',
                     converters={3: lambda x: x.split(';')})
    return df.join(pd.DataFrame(df.pop(3).values.tolist(), dtype=float))

def csv_reader_2(x):
    df = pd.read_csv(x, header=None, delimiter=';',
                     converters={0: lambda x: x.rsplit(',')[-1]}, dtype=float)
    return df.astype(float)

def csv_reader_3(x):
    return pd.read_csv(x, usecols=[3, 4, 5], header=None, sep=',|;', engine='python')

def csv_reader_4(x):
    with x as fin:
        reader = csv.reader(fin, delimiter=',')
        L = [i[-1].split(';') for i in reader]
        return pd.DataFrame(L, dtype=float)

def csv_reader_5(x):
    with x as fin:
        return pd.read_csv(StringIO(fin.getvalue().replace(';',',')),
                           sep=',', header=None, usecols=[3, 4, 5])

检查:

res1 = csv_reader_1(StringIO(x))
res2 = csv_reader_2(StringIO(x))
res3 = csv_reader_3(StringIO(x))
res4 = csv_reader_4(StringIO(x))
res5 = csv_reader_5(StringIO(x))

print(res1.head(3))
#        0       1         2
# 0  34.23  562.45  213.5432
# 1  56.23   63.45  625.2340
# 2  34.23  562.45  213.5432

assert all(np.array_equal(res1.values, i.values) for i in (res2, res3, res4, res5))

基准测试结果:

%timeit csv_reader_1(StringIO(x))  # 5.31 s per loop
%timeit csv_reader_2(StringIO(x))  # 6.69 s per loop
%timeit csv_reader_3(StringIO(x))  # 18.6 s per loop
%timeit csv_reader_4(StringIO(x))  # 5.68 s per loop
%timeit csv_reader_5(StringIO(x))  # 7.01 s per loop
%timeit pd.read_csv(StringIO(x))   # 1.65 s per loop

更新

作为最后的手段,我愿意使用命令行工具。就此而言,我已经包含了这样一个答案。我希望有一个效率相当的纯 Python 或 Pandas 解决方案。

最佳答案

使用命令行工具

到目前为止,我发现的最有效的解决方案是使用专业的命令行工具将 ";" 替换为 ","then 读入 Pandas。 Pandas 或纯 Python 解决方案在效率方面并不接近。

本质上,使用 CPython 或用 C/C++ 编写的工具可能优于 Python 级别的操作。

例如,使用 Find And Replace Text :

import os

os.chdir(r'C:\temp')                       # change directory location
os.system('fart.exe -c file.csv ";" ","')  # run FART with character to replace

df = pd.read_csv('file.csv', usecols=[3, 4, 5], header=None)  # read file into Pandas

关于python - 有效地将数据从 CSV 读取到具有多个分隔符的数据框中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54044022/

相关文章:

python - python中循环的向量化

java - 应用程序性能和 CLI

python - 使用多重处理构建 Pandas 数据框会导致错误

python - 从滚动总和中排除最近一天

Python Pandas group by 然后根据条件进行过滤

mysql - 生产环境创建MySQL数据表即可

Python 任意列的矩阵和

python - 从python中的数组制作数组

python - 无法解析列名称 Spark

python - 如果 token 存在于数据框中,则分配 True/False