2015-11-13 60 views
1

我有一个30GB的csv文件,2列,80M行。一列有80M独特元素(电子邮件),另一列5M独特(匿名发件人),80M地图多对一。我想输出,只有5M行的CSV:发件人,邮件发送者这8行python + pandas需要1个月执行,帮助我加快速度?

此代码工作在理论派,在实践中它会带约1个月期100%

与至强CPU核心来完成
df = pd.read_csv('emails.csv') 
uni = df.sender_id.unique() 
grouped = ((i, ' '.join(df.text[df.sender_id == i])) for i in uni) 
with open('/storage/test.csv', 'w') as csvfile: 
    test_writer = csv.writer(csvfile) 
    for i in grouped: 
     test_writer.writerow(i) 
csvfile.close() 

任何想法如何使这个更快?我试着用joblib并行化,但是内存不足。

+1

也许进入RDBMS并从那里查询? – JimmyB

+1

我建议使用线剖析器来分析您的代码,查看哪些线路正在占用大部分时间,然后从此处继续。 – jme

+3

如果内存使用是主要问题,您可以尝试使用['dask.dataframe''](http://dask.pydata.org/en/latest/dataframe.html),它可以自动并行化类似熊猫的操作。另外,是否有任何理由你手动分组而不是使用“groupby”? – jakevdp

回答

2

我看到在这行代码问题:

grouped = ((i, ' '.join(df.text[df.sender_id == i])) for i in uni) 

这需要O(80M X 5M)来执行。对于每个发件人,它会遍历所有80M邮件以匹配发件人,并加入匹配的电子邮件。

相反,您可以通过电子邮件重复一次:

from collections import defaultdict 

df = pd.read_csv('emails.csv') 
grouped = defaultdict(str) 
for i, text in zip(df.sender_id, df.text): 
    grouped[i] += text + ' ' 

with open('/storage/test.csv', 'w') as csvfile: 
    test_writer = csv.writer(csvfile) 
    for i in grouped.items(): # use iteritems in Python2 
     test_writer.writerow(i) 

我不认为你需要明确地接近cvsfile如果它来自“与”语句。感谢njzk2提供的defaultdict。

+0

'grouped.get(i,'')'也可以工作,就像'grouped = defaultdict(str)'然后'grouped [i] + = text +''一样' – njzk2

1

我得到的〜5的速度提高的因素在一个简单的N = 10,000个测试案例用大熊猫GROUPBY /应用,并从所得到的数据框写入CSV:

df = pd.read_csv('emails.csv') 
grouped = df.groupby('sender_id').apply(lambda group: ' '.join(group.text)) 
grouped.to_csv('/storage/test.csv') 

我开始与此,如果不够用,继续从那里进行优化。如果内存是一个问题,你可以转向dask.dataframe,它提供了一个类似于熊猫的接口,用于在数据帧上直接进行核心/分布式计算。