将np.dot应用于两个数据框的每一行

3
假设我有两个形状相同的Pandas数据框,我想生成一个系列,该系列是两个数据框行向(考虑使用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并定义一些自定义函数?我认为这很困难,因为我无法隐式地索引与df1相同索引对应的df2行。

2个回答

8

您可以将这两个数据框相乘,然后沿着axis=1求和:

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

注意,当你把两个数据框相乘时,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) 返回一个一维的NumPy数组。要创建一个与df1具有相同索引的Series,您可以使用

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

1

我喜欢unutbu的答案。我还想到了另一个方法,可以在两个数据帧df1df2之间进行:

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

如果df1中的列名与df2不同,可以使用.values快速解决问题,例如:

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

这是一种不需要导入numpy的变体:

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

我喜欢这种方式,因为它在代码中保留了“dot”函数(我试图使我的代码意图清晰),并且是矢量化的,并且绘制在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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接