凝聚矩阵函数找到对

Ηλί*_*ίας 10 python algorithm math statistics scipy

对于一组观察:

[a1,a2,a3,a4,a5]
Run Code Online (Sandbox Code Playgroud)

他们的成对距离

d=[[0,a12,a13,a14,a15]
   [a21,0,a23,a24,a25]
   [a31,a32,0,a34,a35]
   [a41,a42,a43,0,a45]
   [a51,a52,a53,a54,0]]
Run Code Online (Sandbox Code Playgroud)

以浓缩矩阵形式给出(上面的上三角形,由下式计算 scipy.spatial.distance.pdist):

c=[a12,a13,a14,a15,a23,a24,a25,a34,a35,a45]
Run Code Online (Sandbox Code Playgroud)

问题是,假设我在压缩矩阵中有索引,那么有一个函数(最好是在python中)f可以快速给出哪两个观察结果来计算它们?

f(c,0)=(1,2)
f(c,5)=(2,4)
f(c,9)=(4,5)
...
Run Code Online (Sandbox Code Playgroud)

我尝试了一些解决方案,但没有一个值得一提:(

fgr*_*egg 25

凝聚基质的指数的公式是

index = d*(d-1)/2 - (d-i)*(d-i-1)/2 + j - i - 1
Run Code Online (Sandbox Code Playgroud)

i行索引在哪里是j列索引,并且d是原始(d X d)上三角矩阵的行长度.

考虑当索引引用原始矩阵中某行的最左边非零条目时的情况.对于所有最左边的指数,

j == i + 1
Run Code Online (Sandbox Code Playgroud)

所以

index = d*(d-1)/2 - (d-i)*(d-i-1)/2 + i + 1 - i - 1
index = d*(d-1)/2 - (d-i)*(d-i-1)/2
Run Code Online (Sandbox Code Playgroud)

通过一些代数,我们可以将其重写为

i**2 + (1 - 2d)*i + 2*index == 0
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用二次公式来找到方程的根,我们只关心正根.

如果该索引确实对应于最左边的非零单元,那么我们得到一个正整数作为对应于行号的解.然后,找到列号只是算术.

j = index - d*(d-1)/2 + (d-i)*(d-i-1)/2 + i + 1
Run Code Online (Sandbox Code Playgroud)

如果索引不对应最左边的非零单元格,那么我们将找不到整数根,但我们可以将正根的最低点作为行号.

def row_col_from_condensed_index(d,index):
    b = 1 -2*d 
    i = math.floor((-b - math.sqrt(b**2 - 8*index))/2)
    j = index + i*(b + i + 2)/2 + 1
    return (i,j)  
Run Code Online (Sandbox Code Playgroud)

如果你不知道d,你可以从浓缩矩阵的长度来计算它.

((d-1)*d)/2 == len(condensed_matrix)
d = (1 + math.sqrt(1 + 8*len(condensed_matrix)))/2 
Run Code Online (Sandbox Code Playgroud)

  • 我不得不长时间搜索这个.你的答案值得更多关注.PS:如果你把`math`换成'numpy`,你的解决方案实际上是矢量化的. (4认同)
  • 我认为问题标题可能不是那么清楚.你对更好的头衔有什么建议吗? (2认同)

eat*_*eat 4

您可能会发现triu_indices很有用。喜欢,

In []: ti= triu_indices(5, 1)
In []: r, c= ti[0][5], ti[1][5]
In []: r, c
Out[]: (1, 3)
Run Code Online (Sandbox Code Playgroud)

请注意,索引从 0 开始。您可以根据需要调整它,例如:

In []: def f(n, c):
   ..:     n= ceil(sqrt(2* n))
   ..:     ti= triu_indices(n, 1)
   ..:     return ti[0][c]+ 1, ti[1][c]+ 1
   ..:
In []: f(len(c), 5)
Out[]: (2, 4)
Run Code Online (Sandbox Code Playgroud)

  • 毫无疑问,即使对于中等大小的“n”尺寸,该解决方案也是低效的。 (3认同)