是否可以将打开的文件传递给pandas read_csv

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以将打开的文件传递给pandas read_csv相关的知识,希望对你有一定的参考价值。

我的csv文件太大,无法一次全部读入内存(〜46 GB),并且我希望该数据的一部分可以放入内存。我能够读取文件的一部分,通过使用先前创建的过滤索引进行内部联接来过滤掉我不想要的内容,然后继续进行文件的下一部分,如下所示:

    with open('Filtered_By_Month/all_data.csv','r') as f:
        cols=np.array(f.readline().strip('
').split(','))#column names
        data=[]
        df=None
        for i in f:
            data.append(i.strip('
').split(',')
            if len(data)==1000000:
                df_sub=pd.DataFrame(data,columns=cols).set_index('KEY_')
                df_sub=df_sub.join(filtered_keys,how='inner')
                data=[]
                if df is None:
                    df=df_sub
                else:
                    df=pd.concat([df,df_sub])

这似乎很有效,除了它非常慢。一种替代方法是将pandas read_csv函数与nrows和skip_rows参数一起使用,但是,这也变得非常慢,因为每次我调用read_csv方法时,都会重新打开文件,并且光标位于第一行,因此我必须遍历所有行,直到我走过skip_rows。是否可以结合使用这两种方法,以便将文件传递给已经打开的read_csv,因此不需要使游标重新开始。

答案

狭窄的回答:是

您可以提供engine='python'nrows=N参数以选择熊猫阅读器在文本文件中的保留位置,或对单个打开的文件对象多次使用pd.read_csv

Pandas在文件中搜索分隔符,例如逗号换行符。默认情况下(根据您提供的参数),pandas使用经过优化的C编译器,速度更快,但功能较少。使用此读取器,游标对象并不总是保留在最后读取的行的末尾,有时会耗尽文件读取器,而其他时候则留在下一行的中间。

使用具有两列和10,000,000行的简单〜200MB文本文件:

In [10]: # create some data
    ...: pd.DataFrame(
    ...:     {'A': np.arange(0, 1e7), 'B': np.arange(1e7, 0, -1)}
    ...: ).to_csv('sample.csv', index=False)

我们可以看到,使用engine='C'解析器读取最后两行以外的所有内容,会将光标留在文件的末尾(什么都没有打印出来:]

In [11]: %%time
    ...: with open('sample.csv', 'r') as f:
    ...:     top = pd.read_csv(f, nrows=9999998, header=0, engine='c')
    ...:     print(f.read())

CPU times: user 130 ms, sys: 2.99 ms, total: 133 ms
Wall time: 132 ms

[使用engine='python',文件对象留在该行的末尾,我们可以读取文件的其余部分,或进行另一个pd.read_csv调用:

In [12]: %%time
    ...: with open('sample.csv', 'r') as f:
    ...:     top = pd.read_csv(f, nrows=999998, header=0, engine='python')
    ...:     print(f.read())
999998,2
999999,1

CPU times: user 2.86 s, sys: 150 ms, total: 3.01 s
Wall time: 2.96 s

但是,Python阅读器的速度明显慢。

更好的答案:不要

chunksize提供为pd.read_csv的参数将返回迭代器。

摘自IO tools: Iterating through files chunk by chunk上的熊猫文档:

通过指定chunksizeread_csv,返回值将是TextFileReader类型的可迭代对象>

使用此分块读取模式使我们可以返回使用C引擎。上面的例子:

In [13]: %%time
    ...: reader = pd.read_csv('sample.csv', chunksize=100000, header=0, engine='c')
    ...: for chunk in reader:
    ...:     tail = chunk.iloc[-2:]
    ...: print(tail)
             A  B
999998  999998  2
999999  999999  1
CPU times: user 136 ms, sys: 9.86 ms, total: 146 ms
Wall time: 146 ms

现在,即使在一个很小的文件上进行10次迭代,我们也几乎不比没有分块的C解析器慢。随着该文件变得大于内存,使用分块读取将大大胜过任何纯Python文件的处理。

您可以使用此分块读取方法来过滤数据:

reader = pd.read_csv('Filtered_By_Month/all_data.csv', chunksize=1000000)

chunks = []

for chunk in reader:
    # filter data
    filtered = do_something(chunk)
    chunks.append(filtered)

df = pd.concat(chunks)

替代:并行框架

如果您使用的文件明显大于内存,则可能需要查看诸如Dask之类的并行计算库。

Dask使用多个线程,处理器甚至服务器使用tools for reading in CSV data。与跨处理器或通过网络分散任务相关的性能开销很大,但是对于足够大的任务,值得这样做。还有一条学习曲线,但是在使dask对齐方面有一些很棒的工作。DataframeAPI与pandas的连接使学习曲线下降了,因此,遵循dask网站上的教程应该可以使您快速启动并运行。

以上是关于是否可以将打开的文件传递给pandas read_csv的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 pandas 的 read_csv 读取分类列?

Python:Pandas read_excel 无法打开 .xls 文件,不支持 xlrd

如何将 dryRun 参数发送到 pandas.read_gbq 函数

将参数中的字段传递给外部方法调用是不是违反了打开/关闭原则?

Pandas库read_excel()参数详解

50_Pandas读取 Excel 文件 (xlsx, xls)