2016-08-17 14 views
2

我正在做一對具有奇怪距離度量的東西的成對距離。我有一個像{(key_A, key_B):distance_value}這樣的詞典,我想像距離矩陣一樣對稱pd.DataFrame將字典轉換成大熊貓的對稱/距離矩陣的最有效方法

什麼是最有效的方法來做到這一點?我找到了一種方法,但它似乎不是最好的方式來做到這一點。執行此類操作的NumPyPandas中是否有任何內容?或只是一個更快的方法?我的方法是1.46 ms per loop

np.random.seed(0) 
D_pair_value = dict() 
for pair in itertools.combinations(list("ABCD"),2): 
    D_pair_value[pair] = np.random.randint(0,5) 
D_pair_value 
# {('A', 'B'): 4, 
# ('A', 'C'): 0, 
# ('A', 'D'): 3, 
# ('B', 'C'): 3, 
# ('B', 'D'): 3, 
# ('C', 'D'): 1} 
D_nested_dict = defaultdict(dict) 
for (p,q), value in D_pair_value.items(): 
    D_nested_dict[p][q] = value 
    D_nested_dict[q][p] = value 

# Fill diagonal with zeros 
DF = pd.DataFrame(D_nested_dict) 
np.fill_diagonal(DF.values, 0) 
DF 

enter image description here

回答

8

您可以使用scipy.spatial.distance.squareform,它轉換距離計算的載體,即[d(A,B), d(A,C), ..., d(C,D)],爲您尋找距離矩陣。

方法1:在列出存儲的距離

如果你計算你的距離,從而,就像在你的示例代碼,並在我的例子距離向量,我會避免使用字典和公正店結果在一個列表,這樣做:

from scipy.spatial.distance import squareform 

df = pd.DataFrame(squareform(dist_list), index=list('ABCD'), columns=list('ABCD')) 

方法2:在字典

存儲如果你計算距離THI NGS出的秩序和一本字典是必需的,你只需要獲得已正確排序的距離向量:

from scipy.spatial.distance import squareform 

dist_list = [dist[1] for dist in sorted(D_pair_value.items())] 
df = pd.DataFrame(squareform(dist_list), index=list('ABCD'), columns=list('ABCD')) 

方法3:如果需要字典的排序字典

存儲的距離,請注意,有一個名爲sortedcontainers的軟件包,它有一個SortedDict,它基本上可以解決您的排序問題。要使用它,你需要改變的只是將D_pair_value初始化爲SortedDict()而不是dict。使用您的示例設置:

from scipy.spatial.distance import squareform 
from sortedcontainers import SortedDict 

np.random.seed(0) 
D_pair_value = SortedDict() 
for pair in itertools.combinations(list("ABCD"),2): 
    D_pair_value[pair] = np.random.randint(0,5) 

df = pd.DataFrame(squareform(D_pair_value.values()), index=list('ABCD'), columns=list('ABCD')) 

所有上述方法得到的輸出:給定鍵的字典(單個字符)和距離

 A B C D 
A 0.0 4.0 0.0 3.0 
B 4.0 0.0 3.0 3.0 
C 0.0 3.0 0.0 1.0 
D 3.0 3.0 1.0 0.0 
+3

謝謝!我今天學到了一些新東西:'scipy.spatial.distance.squareform' – MaxU

+0

方法2:是的!很好的一個,非常感謝'root' –

1

,這裏是一個基於NumPy的方法 -

def dict2frame(D_pair_value): 
    # Extract keys and values 
    k = np.array(D_pair_value.keys()) 
    v = np.array(D_pair_value.values()) 

    # Get row, col indices from keys 
    idx = (np.fromstring(k.tobytes(),dtype=np.uint8)-65).reshape(-1,2) 

    # Setup output array and using row,col indices set values from v 
    N = idx.max()+1 
    out = np.zeros((N,N),dtype=v.dtype) 
    out[idx[:,0],idx[:,1]] = v 
    out[idx[:,1],idx[:,0]] = v 

    header = list("".join([chr(item) for item in np.arange(N)+65])) 
    return pd.DataFrame(out,index=header, columns=header) 

採樣運行 -

In [166]: D_pair_value 
Out[166]: 
{('A', 'B'): 4, 
('A', 'C'): 0, 
('A', 'D'): 3, 
('B', 'C'): 3, 
('B', 'D'): 3, 
('C', 'D'): 1} 

In [167]: dict2frame(D_pair_value) 
Out[167]: 
    A B C D 
A 0 4 0 3 
B 4 0 3 3 
C 0 3 0 1 
D 3 3 1 0 
相關問題