我有一个3列的CSV文件,在其中我用python和panda执行简单的计算。
该文件非常大,略低于4Gb,经过大约1.9Gb 的计算
CSV文件为:
数据1、数据2、数据3
aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw97856521536521321112535aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw986521321112138aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw98856521536521321122135aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw995521321112132aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw998856521536521321212135
计算是一个微不足道的总和。如果列A相同,则添加B并重写CSV。示例结果:
数据1、数据2、数据3
aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw97856521536521321aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw98856521543042642aftqgdjqv0av3q56jvd82tkdjpy7gdp9ut8tlqmgrpmv24sq90ecnvqqjwvw998856521537042642
import pandas as pd
#Read csv
df = pd.read_csv('data.csv', sep=',' , engine='python')
# Groupby and sum
df_new = df.groupby(["data1"]).agg({"data2": "sum"}).reset_index()
# Save in new file
df_new.to_csv('data2.csv', encoding='utf-8', index=False)
如何改进代码以加快执行速度
目前在vps上大约需要7个小时才能完成的计算
添加信息
RAM资源几乎总是100%(8Gb(,而选择engine="python"是因为我使用了上已经存在的代码https://stackoverflow.com/,老实说,我不知道这个命令是否有用,但我已经看到计算是正确的。
Data3实际上对我没用(现在,将来可能有用(。
还有一个替代选项-使用convtools。它是一个纯python库,生成纯python代码来构建即席转换器。当然,光蟒蛇在速度上无法击败熊猫,但至少它不需要任何包装,而且它的工作原理就像你手工实现所有东西一样。
因此,通常情况下,以下内容适用于您:
from convtools import conversion as c
from convtools.contrib.tables import Table
# you can store the converter somewhere for further reuse
converter = (
c.group_by(c.item("data1"))
.aggregate({
"data1": c.item("data1"),
"data2": c.ReduceFuncs.Sum(c.item("data2"))
})
.gen_converter()
)
# this is an iterable (stream of rows), not the list
rows = Table.from_csv("tmp4.csv", header=True).into_iter_rows(dict)
Table.from_rows(converter(rows)).into_csv("out.csv")
JFYI:如果你手动运行脚本,那么你可以使用例如tqdm
来监控速度,只需用它包装一个你正在使用的迭代:
from tqdm import tqdm
# same code as above, except for the last line:
Table.from_rows(converter(tqdm(rows))).into_csv("out.csv")
但是:上面的解决方案不需要输入文件来放入内存,但结果应该是。在您的情况下,如果结果是1.9GB的csv文件,则不太可能将相应的python对象放入8GB的RAM中。
然后您可能需要:
- 删除标头:
tail -n +2 raw_file.csv > raw_file_no_header.csv
- 对文件
sort raw_file_no_header.csv > sorted_file.csv
进行预排序 - a然后:
from convtools import conversion as c
from convtools.contrib.tables import Table
converter = (
c.chunk_by(c.item("data1"))
.aggregate(
{
"data1": c.ReduceFuncs.First(c.item("data1")),
"data2": c.ReduceFuncs.Sum(c.item("data2")),
}
)
.gen_converter()
)
rows = Table.from_csv("sorted_file.csv", header=True).into_iter_rows(dict)
Table.from_rows(converter(rows)).into_csv("out.csv")
这只需要一个组就可以放入内存。
- 删除
engine='python'
没有好处 - 获得更多的RAM,8GB是不够的,你永远不应该达到100%(这是让你慢下来的原因(
- (现在已经太晚了(,但不要将
.csv
文件用于大型数据集。看看羽毛或镶木地板
如果你不能获得更多的RAM,那么@Afaq可能会详细说明文件分割方法。我看到的问题是,你没有太多地减少数据集,所以map reduce可能会阻塞reduce部分,除非你以这种方式分割文件,否则相同的data1字符串总是会进入同一个文件。