Python 熊猫获得最高点积指数

Python 熊猫获得最高点积指数,python,numpy,pandas,dot-product,Python,Numpy,Pandas,Dot Product,我有这样一个数据帧: df1 = pd.DataFrame({'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12]}) a b c 0 1 5 9 1 2 6 10 2 3 7 11 3 4 8 12 我想在这个数据框中创建另一个列,它为每一行存储数据,当对每一行执行点积运算时,另一行的得分最高 例如,对于第一行,我们将根据其他行计算点积: df1.drop(0).dot(df1.loc[0])

我有这样一个数据帧:

df1 = pd.DataFrame({'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12]})
    a   b   c
0   1   5   9
1   2   6   10
2   3   7   11
3   4   8   12
我想在这个数据框中创建另一个列,它为每一行存储数据,当对每一行执行点积运算时,另一行的得分最高

例如,对于第一行,我们将根据其他行计算点积:

df1.drop(0).dot(df1.loc[0]).idxmax()
output: 3
因此,我可以创建一个函数:

def get_highest(dataframe):
    lis = []
    for row in dataframe.index:
        temp = dataframe.drop(row).dot(dataframe.loc[row])
        lis.append(temp.idxmax())
    return lis
我可以通过以下方式得到我想要的:

df1['highest'] = get_highest(df1)
output: 
    a   b   c   highest
0   1   5   9   3
1   2   6   10  3
2   3   7   11  3
3   4   8   12  2
好的,这是可行的,但问题是它根本不可伸缩。以下是不同行数的
timeit
输出:

4 rows: 2.87 ms
40 rows: 77.1 ms
400 rows: 700 ms
4000 rows: 10.4s
我必须在一个大约有240k行和3.3k列的数据帧上执行这个操作。因此,我的问题是:有没有办法优化这个计算?(可能通过另一种方式解决)


提前谢谢。

使用转置进行矩阵乘法:

mat_mul = np.dot(df.values, df.values.T)
用一个小数字填充对角线,这样它们就不能是最大值(我假设全部为正值,所以用-1填充,但您可以更改此值):

现在获取阵列的argmax:

df['highest'] = mat_mul.argmax(axis=1)
10k乘4DF上的计时:

%%timeit
mat_mul = np.dot(df.values, df.values.T)
np.fill_diagonal(mat_mul, -1)
df['highest'] = mat_mul.argmax(axis=1)

1 loop, best of 3: 782 ms per loop

%timeit df['highest'] = get_highest(df)
1 loop, best of 3: 9.8 s per loop

由于点积在翻转成对时会重复,因此每一行相对于每一行的最终点积数组将是对称的。因此,我们可以计算下三角点积元素或上三角点积元素,然后使用。因此,我们将有一个这样的实现-

from scipy.spatial.distance import squareform

arr = df1.values
R,C = np.triu_indices(arr.shape[0],1)
df1['highest'] = squareform(np.einsum('ij,ij->i',arr[R],arr[C])).argmax(1)
样本箱的输出-

In [145]: df1
Out[145]: 
   a  b   c  highest
0  1  5   9        3
1  2  6  10        3
2  3  7  11        3
3  4  8  12        2

我添加了numpy标签,因为基于numpy的解决方案可能会更快,所以numpy的人也可以看一看。@ayhan好主意,谢谢。这可能会有所帮助。谢谢你的回复,事实上我已经试过了,但问题是大数据帧上的
np.dot
占用了大量内存,所以我立即得到了
MemoryError
。也许有方法来块数据帧?我对分块不太了解。老实说,我也不知道如何有效地逐块进行矩阵乘法。让我试试看。这是个好主意,在4k行之前它比我的代码要好,但当我尝试40k行时,它们似乎匹配,所以我倾向于认为在我的主数据帧上它会很好unfortunately@ysearka让我问你-你的数据框中有负数吗?另外,将
np.einsum('ij,ij->i',arr[R],arr[C])
替换为
(arr[R]*arr[C]).sum(1)
,看看是否仍然存在不匹配?非常抱歉,耽搁了,我一直在关注另一项紧急任务。我的数据帧中没有负数,它们实际上是数量(计数或体积)。遗憾的是,尝试替换并不能提高计算时间。@ysearka是否存在值不匹配或其速度较慢或两者兼而有之?它会产生相同的结果,但速度稍慢(例如,400行为+2ms,4000行为+100ms)。
In [145]: df1
Out[145]: 
   a  b   c  highest
0  1  5   9        3
1  2  6  10        3
2  3  7  11        3
3  4  8  12        2