2016-03-29 54 views
2

我有一个非常大的数据帧的大数据帧列乘

in>> all_data.shape 
out>> (228714, 436) 

我想什么有效牙缝做的是乘法多列在一起。我开始用一个for循环和列的列表 - 我已经找到了最effcient方式是

from itertools import combinations 
newcolnames=list(all_data.columns.values) 
newcolnames=newcolnames[0:87] 
#make cross products (the columns I want to operate on are the first 87) 
for c1, c2 in combinations(newcolnames, 2): 
    all_data['{0}*{1}'.format(c1,c2)] = all_data[c1] * all_data[c2] 

的问题,因为人们可以猜测是我有87列,这将使3800个新列的顺序(是的这是我的意图)。我的jupyter笔记本和ipython shell在这个计算上都会窒息。我需要找出一个更好的方法来进行这种增殖。

是否有更高效的矢量化和/或处理方式?也许使用numpy数组(我的数据帧已经被处理,现在只包含数字和NAN,它以分类变量开始)。

回答

0

你可以试试df.eval()方法:

for c1, c2 in combinations(newcolnames, 2): 
    all_data['{0}*{1}'.format(c1,c2)] = all_data.eval('{} * {}'.format(c1, c2)) 
+0

似乎并没有太大的改变 - 它仍然会采取多小时,我的所有系统内存(8GB)。这很奇怪,如果我把这个过程分解成块(比如说前5列)。当我继续时,尽管需要做更少的计算,但这个过程变慢了。列1的第一个“轮”应该进行86列计算,而大约40我应该减少到40列。事实上,第一部分是在几秒钟内跑完的,而第40-45列则花了一个多小时。很奇怪。 – RDS

+1

恐怕一个228714行和3800+列的数据框会占用8GB内存,假设你的df中的16位数是双倍,228714 * 3800 * 16/1024 ** 3 = 12.95 GB – cncggvg

1

正如你在问题中提到NumPy的,这可能是一个可行的选择,在这里,特别是因为你可能想在NumPy的二维空间的工作1D代替柱状加工熊猫。要开始了,你可以通过调用数据帧转换为NumPy的阵列np.array,像这样 -

arr = np.array(df) # df is the input dataframe 

现在,你可以得到列ID的配对组合,然后索引中的列,柱-wise乘法和所有这一切都将在一个量化的方式来完成,像这样 -

idx = np.array(list(combinations(newcolnames, 2))) 
out = arr[:,idx[:,0]]*arr[:,idx[:,1]] 

采样运行 -

In [117]: arr = np.random.randint(0,9,(4,8)) 
    ...: newcolnames = [1,4,5,7] 
    ...: for c1, c2 in combinations(newcolnames, 2): 
    ...:  print arr[:,c1] * arr[:,c2] 
    ...:  
[16 2 4 56] 
[64 2 6 16] 
[56 3 0 24] 
[16 4 24 14] 
[14 6 0 21] 
[56 6 0 6] 

In [118]: idx = np.array(list(combinations(newcolnames, 2))) 
    ...: out = arr[:,idx[:,0]]*arr[:,idx[:,1]] 
    ...: 

In [119]: out.T 
Out[119]: 
array([[16, 2, 4, 56], 
     [64, 2, 6, 16], 
     [56, 3, 0, 24], 
     [16, 4, 24, 14], 
     [14, 6, 0, 21], 
     [56, 6, 0, 6]]) 

最后,您可以创建ŧ他的输出数据帧与propers列标题(如果需要),像这样 -

>>> headers = ['{0}*{1}'.format(idx[i,0],idx[i,1]) for i in range(len(idx))] 
>>> out_df = pd.DataFrame(out,columns = headers) 
>>> df 
    0 1 2 3 4 5 6 7 
0 6 1 1 6 1 5 6 3 
1 6 1 2 6 4 3 8 8 
2 5 1 4 1 0 6 5 3 
3 7 2 0 3 7 0 5 7 
>>> out_df 
    1*4 1*5 1*7 4*5 4*7 5*7 
0 1 5 3 5 3 15 
1 4 3 8 12 32 24 
2 0 6 3 0 0 18 
3 14 0 14 0 49 0