在python中顺序读取巨大的CSV文件

新手上路,请多包涵

我有一个 10gb 的 CSV 文件,其中包含一些我需要使用的信息。

由于我的电脑内存有限,我无法一次读取内存中的所有文件。相反,我只想迭代地读取此文件的某些行。

假设在第一次迭代中我想读取前 100 个,在第二次迭代中我想读取 101 到 200 等等。

有没有一种有效的方法可以在 Python 中执行此任务? Pandas 可以为此提供一些有用的东西吗?还是有更好的(在内存和速度方面)方法?

原文由 Ulderique Demoitre 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 695
1 个回答

这是简短的答案。

 chunksize = 10 ** 6
for chunk in pd.read_csv(filename, chunksize=chunksize):
    process(chunk)

这是很长的答案。

首先,您需要导入 pandas 和 sqlalchemy。下面的命令将执行此操作。

 import pandas as pd
from sqlalchemy import create_engine

接下来,设置一个指向您的 csv 文件的变量。这不是必需的,但它确实有助于重用。

 file = '/path/to/csv/file'

有了这三行代码,我们就可以开始分析我们的数据了。让我们看一下 csv 文件的“头部”,看看内容可能是什么样子。

 print pd.read_csv(file, nrows=5)

此命令使用 pandas 的“read_csv”命令仅读取 5 行 (nrows=5),然后将这些行打印到屏幕上。这可以让您了解 csv 文件的结构,并确保数据的格式对您的工作有意义。

在我们实际处理数据之前,我们需要对它做一些事情,这样我们才能开始过滤它以处理数据的子集。这通常是我使用 pandas 的数据框的目的,但是对于大型数据文件,我们需要将数据存储在其他地方。在这种情况下,我们将建立一个本地 sqllite 数据库,分块读取 csv 文件,然后将这些块写入 sqllite。

为此,我们首先需要使用以下命令创建 sqllite 数据库。

 csv_database = create_engine('sqlite:///csv_database.db')

接下来,我们需要分块遍历 CSV 文件并将数据存储到 sqllite 中。

 chunksize = 100000
i = 0
j = 1
for df in pd.read_csv(file, chunksize=chunksize, iterator=True):
      df = df.rename(columns={c: c.replace(' ', '') for c in df.columns})
      df.index += j
      i+=1
      df.to_sql('table', csv_database, if_exists='append')
      j = df.index[-1] + 1

使用此代码,我们将块大小设置为 100,000 以保持块的大小可管理,初始化几个迭代器(i=0,j=0),然后运行一个 for 循环。 for 循环从 CSV 文件中读取数据块,从任何列名中删除空格,然后将数据块存储到 sqllite 数据库中(df.to_sql(…))。

如果您的 CSV 文件足够大,这可能需要一段时间,但等待的时间是值得的,因为您现在可以使用 pandas ‘sql’ 工具从数据库中提取数据,而不必担心内存限制。

要立即访问数据,您可以运行如下命令:

 df = pd.read_sql_query('SELECT * FROM table', csv_database)

当然,使用’select *…’会将所有数据加载到内存中,这是我们试图避免的问题,因此您应该将过滤器从过滤器扔到您的选择语句中以过滤数据。例如:

 df = pd.read_sql_query('SELECT COl1, COL2 FROM table where COL1 = SOMEVALUE', csv_database)

原文由 ASH 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题