根据条件从超大(48GB)CSV文件中提取行

时间:2016-08-01 12:56:28

标签: python csv for-loop conditional-statements extraction

我有一个非常大的CSV文件,其行数超过5亿。

根据某种情况,我只需要几千行。 我现在正在使用:

with open('/home/Documents/1681.csv', 'rb') as f:
    reader = csv.DictReader(f)
    rows = [row for row in reader if row['flag_central'] == 1]

这里的条件是如果flag_central == 1,我需要行。

但是,由于文件非常庞大,我无法执行上述代码。我相信这是因为我使用的for循环,这导致了这个麻烦。

我是否可以根据上述条件从CSV文件中提取这些特定行?

4 个答案:

答案 0 :(得分:3)

您可以使用pandas

执行此操作
import pandas as pd

chunk_list=[]
for chunk in pd.read_csv('/home/Documents/1681.csv', chunksize=10000):
    chunk_list.append(chunk[chunk['flag_central'] == 1]`

final_df = pd.concat(chunk_list)

基本上,这将一次读取10000行并过滤掉不符合条件的行,这些行会附加到列表中,完成后会将块连接成最终的数据帧

答案 1 :(得分:2)

您可以使用Pandas。我唯一需要注意的是,如果需要这么大的文件,你需要分批导入文件。

    Document doc = Jsoup.connect(url).get();

    for (Element img : doc.select("img:not([alt])"))
        System.out.println("img does not have alt: " + img);

然后,您可以从中提取您感兴趣的行:

import pandas as pd
tp = pd.read_csv('/home/Documents/1681.csv', iterator=True, chunksize=10000)
df = pd.concat(tp, ignore_index=True)

如果您想将其返回到csv文件,则可以使用to_csv:

rows = df[df['flag-central'] == 1]

答案 2 :(得分:2)

如果这是一次性任务,我建议先使用unix命令,然后处理提取:

cat file | awk -F , '{ if ($5 == "1") print $0 }' > extract.csv

其中-F指定列分隔符,5是列号。

首先计算出来
cat file | head -n 1 | tr ',' '\n' | nl | grep flag_central
=>
5   flag_central
^ this is the field number ($5)

这样您就不会产生将csv文件首先转换为python对象的成本。根据您的使用案例YMMV。

答案 3 :(得分:1)

如果这是一个重复的过程和/或你有更复杂的条件来处理,这里有一个快速,低内存的方法在Python中将快速到达那里:

#!/usr/bin/env python
# put this in parsecsv.py, then chmod +x parsecsv.py
import sys
output = lambda l: sys.stdout.write(l)
for line in sys.stdin:
    fields = line.split(',')
    # add your conditions below
    # call output(line) to output
    if fields[0] == "foo":
         output(line)

这可以从命令行用作管道过滤器:

$ cat file | parsecsv > extract.csv

实际上我写了一些你可能觉得有用的generic & maintainable template