假设我有两个形状相同的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
相同的索引对应的行编入索引。
答案 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的回答。我在另外两个数据框df1
和df2
之间提出了另一个问题:
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