使用 Python 读取大型 csv 文件
Posted
技术标签:
【中文标题】使用 Python 读取大型 csv 文件【英文标题】:Read large csv files with Python 【发布时间】:2021-09-02 08:47:31 【问题描述】:我使用 Dask 读取 2.5GB 的 csv 文件,Python 给了我错误。这是我写的代码:
import pandas as pd
import numpy as np
import time
from dask import dataframe as df1
s_time_dask = time.time()
dask_df = df1.read_csv('3SPACK_N150_7Ah_PressureDistributionStudy_Data_Matrix.csv')
e_time_dask = time.time()
以下是我从 Python 得到的错误:
dask_df = df1.read_csv('3SPACK_N150_7Ah_PressureDistributionStudy_Data_Matrix.csv')
文件“C:\ProgramData\Anaconda3\lib\site-packages\dask\dataframe\io\csv.py”,第 645 行,正在读取 返回 read_pandas(
文件“C:\ProgramData\Anaconda3\lib\site-packages\dask\dataframe\io\csv.py”,第 525 行,在 read_pandas head = reader(BytesIO(b_sample), **kwargs)
文件“C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\parsers.py”,第 686 行,在 read_csv 中 return _read(filepath_or_buffer, kwds)
文件“C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\parsers.py”,第 458 行,在 _read 数据 = parser.read(nrows)
文件“C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\parsers.py”,第 1196 行,正在读取 ret = self._engine.read(nrows)
文件“C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\parsers.py”,第 2155 行,正在读取 数据 = self._reader.read(nrows)
文件“pandas_libs\parsers.pyx”,第 847 行,在 pandas._libs.parsers.TextReader.read 中
文件“pandas_libs\parsers.pyx”,第 862 行,在 pandas._libs.parsers.TextReader._read_low_memory
文件“pandas_libs\parsers.pyx”,第 918 行,在 pandas._libs.parsers.TextReader._read_rows 中
文件“pandas_libs\parsers.pyx”,第 905 行,在 pandas._libs.parsers.TextReader._tokenize_rows
文件“pandas_libs\parsers.pyx”,第 2042 行,在 pandas._libs.parsers.raise_parser_error 中
ParserError:标记数据时出错。 C 错误:第 43 行中应有 1 个字段,看到 9
你能帮我解决这个问题吗?
谢谢
【问题讨论】:
【参考方案1】:如果您确实需要打开所有数据,可以分块进行,这样就不会占用您所有的内存:read_csv()
有一个名为 chunksize 的属性。
你可以看看它是如何工作的at kite.com。
您也可以查看pandas documentation。
【讨论】:
【参考方案2】:您的错误与内存无关。 Dask 通过选择固定的字节偏移量然后从每个偏移量扫描到最近的换行符来分块加载文本文件(如 CSV)。这样您就可以从多个进程甚至多台机器访问同一个文件,并且一次只能处理与工作线程一样多的块。
不幸的是,换行符并不总是意味着一行的结束,因为它们可能出现在某些文本字段的带引号的字符串中。这意味着您基本上无法使用 dask 的 read_csv 读取文件,除非您抢先找到一组字节偏移量,以保证干净的分区而不会中断带引号的字符串。
【讨论】:
谢谢。我终于通过使用块解决了这个问题。另一个原因是我使用的数据混合了数值和字符串。所以我使用skiprow来跳过数据的标题,它变得比以前快得多。感谢您的帮助。【参考方案3】:简而言之:您的内存不足。您正在尝试将更多的数据加载到 python 中,而不是机器中的内存(python 的内存使用率高于 C/C++/等,但您仍然会遇到这些语言的限制)。
要解决此问题,您可能需要使用csvreader
来读取文件,您可以在其中逐行读取它。然后处理该行以仅获取您想要的列或逐行启动您想要执行的任何聚合。如果您无法做到这一点,那么您要么需要使用较小的数据集(如果您确实需要一次将所有数据存储在内存中),要么使用具有更多内存的系统。
如果您的文件是 2.5G,如果您的系统需要大约 20GB 内存,我不会感到惊讶。但是正确的估计方法是加载固定数量的行,计算出你的进程正在使用多少,然后读取两倍的行数并再次查看内存使用情况。从较高的数字中减去较低的数字,这可能是您需要多少内存(大约)来保存那么多行。然后,您可以计算出所有数据需要多少。
【讨论】:
谢谢。我尝试了这种方法,但失败了。我终于发现我使用的CSV数据是混有字符串和数值的。我用skirows跳过了header的前几行,代码比以前快了很多。以上是关于使用 Python 读取大型 csv 文件的主要内容,如果未能解决你的问题,请参考以下文章