使用to_csv时如何处理pandas内存错误?
Posted
技术标签:
【中文标题】使用to_csv时如何处理pandas内存错误?【英文标题】:How to deal with pandas memory error when using to_csv? 【发布时间】:2019-11-11 05:18:49 【问题描述】:我目前正在 linux 系统中运行一个脚本。该脚本读取大约 6000 行的 csv 作为数据帧。脚本的工作是转换一个数据框,例如:
name children
Bob [Jeremy, Nancy, Laura]
Jennifer [Kevin, Aaron]
到:
name children childName
Bob [Jeremy, Nancy, Laura] Jeremy
Bob [Jeremy, Nancy, Laura] Nancy
Bob [Jeremy, Nancy, Laura] Laura
Jennifer [Kevin, Aaron] Kevin
Jennifer [Kevin, Aaron] Aaron
并将其写入另一个文件(原始 csv 保持不变)。
基本上添加一个新列并为列表中的每个项目创建一行。 请注意,我正在处理一个包含 7 列的数据框,但出于演示目的,我使用了一个较小的示例。我的实际 csv 中的列都是字符串,除了两个是列表。
这是我的代码:
import ast
import os
import pandas as pd
cwd = os.path.abspath(__file__+"/..")
data= pd.read_csv(cwd+"/folded_data.csv", sep='\t', encoding="latin1")
output_path = cwd+"/unfolded_data.csv"
out_header = ["name", "children", "childName"]
count = len(data)
for idx, e in data.iterrows():
print("Row ",idx," out of ",count)
entry = e.values.tolist()
c_lst = ast.literal_eval(entry[1])
for c in c_lst :
n_entry = entry + [c]
if os.path.exists(output_path):
output = pd.read_csv(output_path, sep='\t', encoding="latin1")
else:
output = pd.DataFrame(columns=out_header)
output.loc[len(output)] = n_entry
output.to_csv(output_path, sep='\t', index=False)
但我收到以下错误:
Traceback (most recent call last):
File "fileUnfold.py", line 31, in <module>
output.to_csv(output_path, sep='\t', index=False)
File "/usr/local/lib/python3.5/dist-packages/pandas/core/generic.py", line 3020, in to_csv
formatter.save()
File "/usr/local/lib/python3.5/dist-packages/pandas/io/formats/csvs.py", line 172, in save
self._save()
File "/usr/local/lib/python3.5/dist-packages/pandas/io/formats/csvs.py", line 288, in _save
self._save_chunk(start_i, end_i)
File "/usr/local/lib/python3.5/dist-packages/pandas/io/formats/csvs.py", line 315, in _save_chunk
self.cols, self.writer)
File "pandas/_libs/writers.pyx", line 75, in pandas._libs.writers.write_csv_rows
MemoryError
还有其他方法可以在不出现此错误的情况下做我想做的事情吗?
编辑:如果你想看一下 csv 文件https://media.githubusercontent.com/media/lucas0/Annotator/master/annotator/data/folded_snopes.csv
EDIT2:我目前正在使用
with open(output_path, 'w+') as f:
output.to_csv(f, index=False, header=True, sep='\t')
在第 98 行左右,程序开始显着减速。我很确定这是因为随着文件变大,我会一遍又一遍地阅读文件。我怎样才能在文件中追加一行而不读取它?
EDIT3:这是我用来处理第一次编辑中链接的数据的实际代码。这可能会更容易回答。
import ast
import os
import pandas as pd
cwd = os.path.abspath(__file__+"/..")
snopes = pd.read_csv(cwd+"/folded_snopes.csv", sep='\t', encoding="latin1")
output_path = cwd+"/samples.csv"
out_header = ["page", "claim", "verdict", "tags", "date", "author","source_list","source_url"]
count = len(snopes)
for idx, e in snopes.iterrows():
print("Row ",idx," out of ",count)
entry = e.values.tolist()
src_lst = ast.literal_eval(entry[6])
for src in src_lst:
n_entry = entry + [src]
if os.path.exists(output_path):
output = pd.read_csv(output_path, sep='\t', encoding="latin1")
else:
output = pd.DataFrame(columns=out_header)
output.loc[len(output)] = n_entry
with open(output_path, 'w+') as f:
output.to_csv(f, index=False, header=True, sep='\t')
【问题讨论】:
7 列和 6000 行现在应该不会在任何合理的 PC 上引起内存问题。你没有给出一个容易测试的例子,但如果它像n_entry = entry + [c]
这样的东西在列表中的列表结束时会炸毁内存,我不会感到惊讶
@roganjosh 我添加了一个指向数据的链接,如果你想看看
这里有什么真正的理由使用熊猫吗?您可以使用标准库 csv
模块非常有效地完成此任务。
@juanpa.arrivillaga 一些数据本身有标签。我是一名实习生,我的主管(谁给了我这些数据)告诉我只使用 pandas,因为它可以处理这些问题。我使用的是正常的打开和写入,但由于第 1000 行周围的数据格式不正确,因此无法正常工作。
@MohamadMoustafa 您能否在 df = df[:-1] 的帮助下将最后一行作为临时解决方案删除并检查我的答案?
【参考方案1】:
我停止读取输出文件,并停止为每个源写入。相反,我为输入数据的每一行创建了一个包含新行的数据框,然后将其附加到 samples.csv。
代码:
import ast
import os
import pandas as pd
cwd = os.path.abspath(__file__+"/..")
snopes = pd.read_csv(cwd+"/folded_snopes.csv", sep='\t', encoding="latin1")
output_path = cwd+"/samples.csv"
out_header = ["page", "claim", "verdict", "tags", "date", "author","source_list","source_url"]
count = len(snopes)
is_first = True
for idx, e in snopes.iterrows():
print("Row ",idx," out of ",count)
entry = e.values.tolist()
src_lst = ast.literal_eval(entry[6])
output = pd.DataFrame(columns=out_header)
for src in src_lst:
n_entry = entry + [src]
output.loc[len(output)] = n_entry
output.to_csv(output_path, sep='\t', header=is_first, index=False, mode='a')
is_first = False
【讨论】:
【参考方案2】:尝试打开以便记忆,也许可以解决它。
我怎样才能在文件中追加一行而不读取它?
from pathlib import Path
output_path= Path("/yourfolder/path")
with open(path1, 'w', newline='') as f1, open(path2, 'r') as f2:
file1= csv.writer(f1)
#output.to_csv(f, header=False, sep=';')
file2 = csv.reader(f4)
i = 0
for row in file2:
row.insert(1,output[i])
file1.writerow(row)
i += 1
【讨论】:
什么是df?和test.csv?请编辑您对此方案的答案(使用适当的名称) 当然,df 是你的数据框,test.csv 是你的 output_path。 在这里使用a+
是不正确的,因为我们正在读取、添加然后覆盖 csv 文件。不附加。以上是关于使用to_csv时如何处理pandas内存错误?的主要内容,如果未能解决你的问题,请参考以下文章