将np.dot应用于两个DataFrame的每一行

时间:2015-09-29 17:43:53

标签: python pandas

假设我有两个形状相同的Pandas DataFrames,我想制作一个系列,它是两个DataFrames的行产品(思考使用pandas.DataFrame.apply)点积。

所以,例如:

df1 = pd.DataFrame(np.random.rand(1000,10))
df2 = pd.DataFrame(np.random.rand(1000,10))
df1.apply(np.dot, axis=1, args=[df2.ix[???]]

是否有一种紧凑的矢量化方法,无需连接到一个DataFrame并定义一些自定义函数?我认为这很难,因为我无法隐式地将df2中与df1相同的索引对应的行编入索引。

2 个答案:

答案 0 :(得分:4)

您可以将两个DataFrame相乘,然后与axis=1相加:

df1 = pd.DataFrame(np.random.rand(1000,10))
df2 = pd.DataFrame(np.random.rand(1000,10))
result = (df1*df2).sum(axis=1)

请注意,将两个DataFrame相乘时,Pandas会根据索引对齐行。这需要时间。如果值已经对齐,那么您可以下拉到NumPy并使用

result = (df1.values * df2.values).sum(axis=1)

result = np.einsum('ij,ij->i', df1.values, df2.values)

这更快,因为不需要首先根据索引对齐行。

In [10]: %timeit (df1*df2).sum(axis=1)
1000 loops, best of 3: 379 µs per loop

In [11]: %timeit (df1.values * df2.values).sum(axis=1)
10000 loops, best of 3: 49.8 µs per loop

In [14]: %timeit np.einsum('ij,ij->i', df1.values, df2.values)
10000 loops, best of 3: 30 µs per loop

(df1.values * df2.values).sum(axis=1)返回1D NumPy数组。要使与df1具有相同索引的系列,您将使用

pd.Series(np.einsum('ij,ij->i', df1.values, df2.values), index=df1.index)

答案 1 :(得分:0)

我喜欢unutbu的回答。我在另外两个数据框df1df2之间提出了另一个问题:

dot_prods = np.dot(df1, df2.transpose()).diagonal()

如果df1中的列名与df2中的列名不同,请使用.values快速解决方法,例如unutbu:

dot_prods = np.dot(df1.values, df2.transpose().values).diagonal()

这些变体不需要进行小块导入:

dot_prods = df1.values.dot(df2.values.transpose()).diagonal()

我喜欢这种方式,因为它会保持“点”状态。代码中的函数(我尝试使我的代码的意图清晰),它是矢量化和绘制pandas / numpy本机功能,但unutbu的方式更简洁。祝你好运!

修改

看起来我给出的方法表现得更快一点:

In [73]: %timeit df1.values.dot(df1.values.transpose()).diagonal()
10000 loops, best of 3: 19.7 µs per loop

In [74]: %timeit (df1.values * df1.values).sum(axis=1)
10000 loops, best of 3: 21.3 µs per loop