2017-01-30 54 views
0

我有一個第二陣列看起來如下:numpy的陣列列出的(行,列,距離)

[[ 0.   1.73205081 6.40312424 7.21110255 2.44948974] 
[ 1.73205081 0.   5.09901951 5.91607978 1.  ] 
[ 6.40312424 5.09901951 0.   1.   4.35889894] 
[ 7.21110255 5.91607978 1.   0.   5.09901951] 
[ 2.44948974 1.   4.35889894 5.09901951 0.  ]] 

此數組中的每個元素是一個距離和我需要變成一個名單與行,列,距離如下:

l = [(0,0,0),(0,1, 1.73205081),(0,2, 6.40312424),...,(1,0, 1.73205081),(1,1,0),...,(4,4,0)] 

此外,它會很酷去除對角線元素以及元素(J,I)爲(I,J)已經在那裏。本質上,是否有可能只取這個頂三角矩陣?

這可能有效地做到(沒有很多循環)嗎?我用squareform創建了這個數組,但找不到任何文檔來完成此操作。

+0

所有問題的答案都是肯定的。是的,這一切都有可能。開始工作。 – DyZ

+0

哈哈我得到它的工作,但它很慢。我有一個大小爲76800 x 3900的矩陣。剛剛看到是否有更快的實現,但我認爲約翰有一個很好的建議去嘗試 –

回答

2

如果您輸入x,首先生成指數:

i0,i1 = np.indices(x.shape) 

然後:

np.concatenate((i1,i0,x)).reshape(3,5,5).T 

這使你的第一個結果 - 爲整個矩陣。

至於只考慮上三角,你可能會考慮嘗試np.triu(),但我不確定你正在尋找什麼結果。你或許可以弄清楚如何掩蓋你現在不想要的部分。

+0

如果'x'在對角線上方不爲零,則以下方法將很好地工作:'i0, i1 = np.triu(x,k = 1).nonzero(); X = np.concatenate((i0,i1,x [i0,i1])).reshape(3,len(i0))。T'但注意'X'將是一個'float64'類型的數組, (例如,'X [0,0]',它等於'float(i0 [0])')需要稍後轉換爲'int'來訪問'x'。 –

0

你可以試試這個,

print([(x,y, value) for (x,y), value in np.ndenumerate(numpymatrixarray)]) 

output [(0, 0, 0.0), (0, 1, 1.7320508100000001), (0, 2, 6.4031242400000004), (0, 3, 7.2111025499999997), (0, 4, 2.4494897400000002), (1, 0, 1.7320508100000001), (1, 1, 0.0), (1, 2, 5.0990195099999998), (1, 3, 5.9160797799999996), (1, 4, 1.0), (2, 0, 6.4031242400000004), (2, 1, 5.0990195099999998), (2, 2, 0.0), (2, 3, 1.0), (2, 4, 4.3588989400000004), (3, 0, 7.2111025499999997), (3, 1, 5.9160797799999996), (3, 2, 1.0), (3, 3, 0.0), (3, 4, 5.0990195099999998), (4, 0, 2.4494897400000002), (4, 1, 1.0), (4, 2, 4.3588989400000004), (4, 3, 5.0990195099999998), (4, 4, 0.0)] 
+1

NumPy中的大循環不是很好的形式。 –

4

squareform做這一切。閱讀文檔和實驗。它可以在兩個方向上工作。如果你給它一個矩陣,它將返回上面的三角形值(濃縮形式)。如果你給它的值,它返回矩陣。

In [668]: M 
Out[668]: 
array([[ 0. , 0.1, 0.5, 0.2], 
     [ 0.1, 0. , 2. , 0.3], 
     [ 0.5, 2. , 0. , 0.2], 
     [ 0.2, 0.3, 0.2, 0. ]]) 
In [669]: spatial.distance.squareform(M) 
Out[669]: array([ 0.1, 0.5, 0.2, 2. , 0.3, 0.2]) 
In [670]: v=spatial.distance.squareform(M) 
In [671]: v 
Out[671]: array([ 0.1, 0.5, 0.2, 2. , 0.3, 0.2]) 
In [672]: spatial.distance.squareform(v) 
Out[672]: 
array([[ 0. , 0.1, 0.5, 0.2], 
     [ 0.1, 0. , 2. , 0.3], 
     [ 0.5, 2. , 0. , 0.2], 
     [ 0.2, 0.3, 0.2, 0. ]]) 

還可以指定一個forcechecks參數,但如果沒有這些,它只是由形狀去。

Indicies可以來自triu

In [677]: np.triu_indices(4,1) 
Out[677]: 
(array([0, 0, 0, 1, 1, 2], dtype=int32), 
array([1, 2, 3, 2, 3, 3], dtype=int32)) 

In [680]: np.vstack((np.triu_indices(4,1),v)).T 
Out[680]: 
array([[ 0. , 1. , 0.1], 
     [ 0. , 2. , 0.5], 
     [ 0. , 3. , 0.2], 
     [ 1. , 2. , 2. ], 
     [ 1. , 3. , 0.3], 
     [ 2. , 3. , 0.2]]) 

只是爲了檢查,我們可以在一個4x4矩陣填充這些值

In [686]: A=np.vstack((np.triu_indices(4,1),v)).T 
In [687]: MM = np.zeros((4,4)) 
In [688]: MM[A[:,0].astype(int),A[:,1].astype(int)]=A[:,2] 
In [689]: MM 
Out[689]: 
array([[ 0. , 0.1, 0.5, 0.2], 
     [ 0. , 0. , 2. , 0.3], 
     [ 0. , 0. , 0. , 0.2], 
     [ 0. , 0. , 0. , 0. ]]) 

那些triu指數也可以從M獲取值:

In [693]: I,J = np.triu_indices(4,1) 
In [694]: M[I,J] 
Out[694]: array([ 0.1, 0.5, 0.2, 2. , 0.3, 0.2]) 

squareform使用spatial.distance._distance_wrap中的編譯代碼,所以我預計它對於大型陣列來說會非常快。只有問題它只是返回壓縮的表單值,而不是索引。但考慮到形狀,指標總是可以計算的。他們不需要存儲值。

0

你真的想要一個[nxm]矩陣的頂三角矩陣,其中n>m?那會給你(nxn-n)/2元素並丟失所有的數據m⊖n

你可能想要的是下三角矩陣:

def tri_reduce(m): 
    n=m.shape 
    if n[0]>n[1]: 
     i=np.tril_indices(n[0],1,n[1]) 
    else: 
     i=np.triu_indices(n[0],1,n[1]) 
    return np.vstack((i,m[i])).T 

重建成元組的列表將需要一個循環,雖然我相信。 list(tri_reduce(m))會給出一個nd數組的列表。