根据条件从超大 (48GB) CSV 文件中提取行
Extracting rows from an extremely large (48GB) CSV file based on condition
我有一个非常大的 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 文件中提取这些特定行?
您可以使用 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 行并过滤不符合您条件的行,这些行将附加到列表中,完成后这些块将连接到最终数据帧中
您可以使用 Pandas。我唯一要注意的是,对于如此大的文件,您需要分段导入文件。
import pandas as pd
tp = pd.read_csv('/home/Documents/1681.csv', iterator=True, chunksize=10000)
df = pd.concat(tp, ignore_index=True)
然后您可以从那里提取您感兴趣的行:
rows = df[df['flag-central'] == 1]
如果您想将此 return 转换为 csv 文件,您可以使用 to_csv:
rows.to_csv('filename.csv')
如果这是一次性任务,我建议先使用 unix 命令,然后再处理提取物:
cat file | awk -F , '{ if ( == "1") print [=10=] }' > extract.csv
其中 -F 指定列分隔符,5 是列号。首先通过
解决这个问题
cat file | head -n 1 | tr ',' '\n' | nl | grep flag_central
=>
5 flag_central
^ this is the field number ()
这样您就不会产生先将 csv 文件转换为 python 对象的成本。取决于您的用例 YMMV。
如果这是一个重复的过程and/or您有更复杂的条件要处理,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。
我有一个非常大的 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 文件中提取这些特定行?
您可以使用 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 行并过滤不符合您条件的行,这些行将附加到列表中,完成后这些块将连接到最终数据帧中
您可以使用 Pandas。我唯一要注意的是,对于如此大的文件,您需要分段导入文件。
import pandas as pd
tp = pd.read_csv('/home/Documents/1681.csv', iterator=True, chunksize=10000)
df = pd.concat(tp, ignore_index=True)
然后您可以从那里提取您感兴趣的行:
rows = df[df['flag-central'] == 1]
如果您想将此 return 转换为 csv 文件,您可以使用 to_csv:
rows.to_csv('filename.csv')
如果这是一次性任务,我建议先使用 unix 命令,然后再处理提取物:
cat file | awk -F , '{ if ( == "1") print [=10=] }' > extract.csv
其中 -F 指定列分隔符,5 是列号。首先通过
解决这个问题cat file | head -n 1 | tr ',' '\n' | nl | grep flag_central
=>
5 flag_central
^ this is the field number ()
这样您就不会产生先将 csv 文件转换为 python 对象的成本。取决于您的用例 YMMV。
如果这是一个重复的过程and/or您有更复杂的条件要处理,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。