2015-10-29 2 views
0

У меня есть следующий кросс-табличные данные:Визуальной кластеризации на основе сходства оценки

  biz user1 user2 user3 user4 
    user 
    A   1  1  0  0 
    B   1  1  0  0 
    C   1  1  1  0 
    D   1  0  0  0 
    E   0  0  1  1 
    F   0  0  1  1 
    G   0  0  1  1 
    J   0  0  0  1 
    M   0  1  0  0 

и с помощью ковариации превратить его в:

[ 1. , 0.75, 0.25, 0. ], 
    [ 0.75, 1. , 0.25, 0. ], 
    [ 0.25, 0.25, 1. , 0.75], 
    [ 0. , 0. , 0.75, 1. ] 

Используя следующий код, я пытаюсь построить график этих данных :

import pandas as pd 
    import numpy as np 
    import networkx as nx 

    users=[] 
    user_s=[(x+',')*4 for x in ['user1', 'user2', 'user3', 'user4']] 
    for s in user_s: 
     users.extend([e for e in s.split(',') if e!='']) 

    X=[] 
    user_s=[(x+',')*4 for x in ['32.5', '32.2', '30.4', '31.5']] 
    for s in user_s: 
     X.extend([float(e) for e in s.split(',') if e!='']) 

    Y=[] 
    user_s=[(x+',')*4 for x in ['-110', '-110', '-115', '-114']] 
    for s in user_s: 
     Y.extend([float(e) for e in s.split(',') if e!=''])  

    dat=pd.DataFrame({'user':users, 
     'biz':['A', 'B', 'C', 'D', 'A', 'B', 'C', 'M', 'C', 'E', 'F', 'G', 'E', 'F', 'G', 'J'], 
     'X':X, 'Y':Y}) 

    rel=pd.crosstab(dat.user, dat.biz, rownames=['biz'], colnames=['user']).transpose() 
    cov=np.dot(rel.transpose(), rel)/np.diag(np.dot(rel.transpose(), rel)) 
    dat.groupby('user').mean()[['X', 'Y']] 
    dat.groupby('user').mean()[['X', 'Y']] 
    G=nx.Graph() 
    for i in rel.columns.tolist(): 
     G.add_node(i, X=dat.loc[dat.user==i, 'X'].mean(), Y=dat.loc[dat.user==i, 'Y'].mean()) 


    for i in np.arange(0, cov.shape[0]): 
     idx=np.where(cov[i,]>.0)[0].tolist() ##for column i, get index of cov values above quantile p 
     for j in idx: 
      if i!=j: #eliminates (0,0) as an edge bc its redundant 
       G.add_edge(rel.columns[i], 
       rel.columns[j],weight=cov[i,j],length=1/cov[i,j], width=cov[i,j]) 

    centrality=nx.degree_centrality(G)  
    pos=nx.spring_layout(G) 
    nx.draw(G,pos, node_size=[centrality[key]*500 for key in centrality.keys()], 
     cm=plt.cm.Spectral,edge_cm=plt.cm.Blues, 
     width=[(x[2]['width']*2)**2 for x in G.edges(data=True)], alpha=.5) 
    nx.draw_networkx_labels(G,pos,fontsize=16) 

graph produced by above code

Обратите внимание, что user1 и user2 сильно коррелированы, как и user3 и user4; в то время как связь между двумя кластерами слаба.

Я хочу сделать две вещи:

  • Есть две группы имеют один и тот же цвет (сказать членство кластера)
  • Есть расстояние между user1 & user2 быть меньше, чем между user1 и user3. Аналогично для user3 и user4.

Я новичок в графическом дизайне, поэтому, если вы можете предложить алгоритм, который поможет в кластеризации, я был бы очень благодарен.

Моя главная цель состоит в том, чтобы представить себе это в гораздо большем наборе данных (10k пользователей)

ответ

0

В графике на вопрос, в связи определяются ненулевых весов между пользователями; поэтому, чтобы проверить для очень подобных групп, я определил вес, необходимый для подсчета в качестве соединения, как с корреляцией выше .75. Это создает острова и могут быть нанесены в виде различных групп, используя функцию ниже:

G=nx.Graph() 
    G.add_nodes_from(['u1', 'u2', 'u3', 'u4', 'u5', 'u6', 'u7', 'u8']) 
    G.add_edges_from([ 
    ('u1', 'u2', {'weight':.75}), ('u1','u5', {'weight':1}),('u2', 'u5', {'weight':.75}), 
    ('u3', 'u6', {'weight':.8}), ('u4', 'u6', {'weight':.65}),('u3', 'u4', {'weight':.75}), 
    #('u3', 'u7', {'weight':.5}), 
    #('u2', 'u4', {'weight':.3}), 
    ('u7', 'u8', {'weight':.9})]) 

    def draw_group_graph(graph, edge_cmap=plt.cm.Blues,node_cmap=plt.cm.jet, w_pwr=3): 
     plt.figure() 
     pos=nx.spring_layout(graph) 

     nx.draw_networkx_edges(graph,pos, 
     width=[nx.get_edge_attributes(graph,'weight')[i]*w_pwr for i in G.edges()], 
     edge_cmap=edge_cmap, 
     edge_color=[nx.get_edge_attributes(graph,'weight')[i] for i in G.edges()]) 

     nx.draw_networkx_edge_labels(G, pos, labels=[str(i) for i in weights]) 

     g_list=[j for j in nx.connected_component_subgraphs(graph) if len(j.edges())>0] 

     col_val=np.linspace(0,1,num=len(g_list)).tolist() 
     i=0; print(len(g_list)) 
     for g in g_list: 
      print(i, "color:",node_cmap(col_val[i])) 
      nx.draw_networkx_nodes(g, pos, node_color=node_cmap(col_val[i]), alpha=.6, 
      node_size=[nx.degree_centrality(g)[i]*1000 for i in g.nodes()]) 
      nx.draw_networkx_labels(g, pos, fontsize=16) 
      i=i+1 

Above defined graph plotted using different groups

+0

где вы получаете «веса»? – ethanenglish

+0

@ethanenglish Весы исходят из нормализованной матрицы ковариации; выше приведен взвешенный граф. –

0

Вы также можете рассмотреть dendrogram.

Вы можете использовать scipy для его создания.

Смежные вопросы