在python中按列的值拆分大csv文件
我有一个csv大文件,无法用python在内存中处理。在按照特定列的值进行分组后,我使用以下逻辑将其拆分为多个块:在python中按列的值拆分大csv文件,python,pandas,Python,Pandas,我有一个csv大文件,无法用python在内存中处理。在按照特定列的值进行分组后,我使用以下逻辑将其拆分为多个块: def splitDataFile(self, data_file): self.list_of_chunk_names = [] csv_reader = csv.reader(open(data_file, "rb"), delimiter="|") columns = csv_reader.next() for key,rows in gr
def splitDataFile(self, data_file):
self.list_of_chunk_names = []
csv_reader = csv.reader(open(data_file, "rb"), delimiter="|")
columns = csv_reader.next()
for key,rows in groupby(csv_reader, lambda row: (row[1])):
file_name = "data_chunk"+str(key)+".csv"
self.list_of_chunk_names.append(file_name)
with open(file_name, "w") as output:
output.write("|".join(columns)+"\n")
for row in rows:
output.write("|".join(row)+"\n")
print "message: list of chunks ", self.list_of_chunk_names
return
逻辑在起作用,但速度很慢。我想知道如何优化这个?比如说熊猫
编辑
进一步解释:我不想简单地拆分为相同大小的块(比如每个块有1000行),我想按列的值拆分,这就是我使用groupby的原因 通过使用pandas的内置分块功能(从
chunksize
关键字arg到read\u csv
),您可能会获得最佳性能
比如说,
reader = pd.read_table('my_data.csv', chunksize=4)
for chunk in reader:
print(chunk)
编辑:
这可能会让你有所收获
import pandas as pd
group_col_indx = 1
group_col = pd.read_csv('test.csv', usecols=[group_col_indx])
keys = group_col.iloc[:,0].unique()
for key in keys:
df_list = []
reader = pd.read_csv('test.csv', chunksize=2)
for chunk in reader:
good_rows = chunk[chunk.iloc[:,group_col_indx] == key]
df_list.append(good_rows)
df_key = pd.concat(df_list)
使用此程序:
将其另存为split csv.py
,并从资源管理器或命令运行它
线路
例如,根据第1列拆分superuser.csv
,并写入
dstdir下的输出文件使用:
python split-csv.py data.csv 1 dstdir
如果您在没有参数的情况下运行它,基于Tkinter的GUI将提示您
要选择输入文件,请选择列(基于1的索引)和
目标目录
我怀疑最大的瓶颈是每次处理新行块时打开和关闭文件句柄。一个更好的方法是,只要您写入的文件数量不太多,就保持所有文件都处于打开状态。这里有一个提纲:
def splitDataFile(self, data_file):
open_files = dict()
input_file = open(data_file, "rb")
try:
...
csv_reader = csv.reader(input_file, ...)
...
for key, rows in groupby(csv_reader, lambda row: (row[1])):
...
try:
output = open_files[key]
except KeyError:
output = open(file_name, "w")
output.write(...)
...
finally:
for open_file in open_files.itervalues():
open_file.close()
input_file.close()
当然,如果您只有一个组具有任何给定的密钥,这将没有帮助。(事实上,这可能会让事情变得更糟,因为你最终会不必要地打开一堆文件。)你越是频繁地向一个文件写入,你就越能从这一改变中获益
如果需要,您可以将其与pandas结合使用,并使用read\u csv
或read\u table
的分块功能来处理输入处理。我将使用以下类似的方法,迭代要拆分的列的唯一值,以过滤数据分块
def splitWithPandas(data_file, split_by_column):
values_to_split_by = pd.read_csv(data_file, delimiter="|", usecols=[split_by_column])
values_to_split_by.drop_duplicates()
values_to_split_by = pd.unique(values_to_split_by.values.ravel())
for i in values_to_split_by:
iter_csv = pd.read_csv(data_file, delimiter="|", chunksize=100000)
df = pd.concat([chunk[chunk[split_by_column] == i] for chunk in iter_csv])
df.to_csv("data_chunk_"+i, sep="|", index=False)
谢谢你的反馈。我不是在寻找简单的相同行数的分块。我正在寻找csv文件中给定列的值进行拆分。您可以对要分组的每个列值的块进行循环。是否可以在内存中设置要按其分组的单个列(这将允许您发现列中的唯一值)?是的,我可以在内存中设置要按其分组的单个列的大小。
def splitWithPandas(data_file, split_by_column):
values_to_split_by = pd.read_csv(data_file, delimiter="|", usecols=[split_by_column])
values_to_split_by.drop_duplicates()
values_to_split_by = pd.unique(values_to_split_by.values.ravel())
for i in values_to_split_by:
iter_csv = pd.read_csv(data_file, delimiter="|", chunksize=100000)
df = pd.concat([chunk[chunk[split_by_column] == i] for chunk in iter_csv])
df.to_csv("data_chunk_"+i, sep="|", index=False)