大型数据帧列乘法

时间:2016-03-29 15:13:29

标签: python pandas memory vectorization

我有一个非常大的数据框

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

我想要做的有效的是将许多列加在一起。我开始使用for循环和列列表 - 我找到的最有效的方法是

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,它以分类变量开头)。

2 个答案:

答案 0 :(得分:1)

正如你在问题中提到NumPy,这可能是一个可行的选择,特别是因为你可能想要在NumPy的2D空间中工作而不是使用pandas进行一维柱状处理。首先,您可以通过调用np.array将数据帧转换为NumPy数组,如下所示 -

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

现在,您可以获得列ID的成对组合,然后将其索引到列中并执行逐列乘法,所有这些都将以矢量化方式完成,如下所示 -

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

答案 1 :(得分:0)

您可以尝试df.eval()方法:

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