Создание круговой диаграммы как узлов в Networkx

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

import pygraphviz as pgv
import networkx as nx
import matplotlib.pyplot as plt
import plotly.graph_objects as go

from pprint import pprint
from collections import OrderedDict


if __name__ == '__main__':

    tail = [1, 2, 3]
    head = [2, 3, 4]

    xpos = [0, 1, 2, 3]
    ypos = [0, 0, 0, 0]
    xpos_ypos = [(x, y) for x, y in zip(xpos, ypos)]

    ed_ls = [(x, y) for x, y in zip(tail, head)]
    G = nx.OrderedDiGraph()
    G.add_edges_from(ed_ls)

    # set node positions
    pos = OrderedDict(zip(G.nodes, xpos_ypos))
    nx.draw(G, pos=pos, with_labels=True)
    nx.set_node_attributes(G, pos, 'pos')

    # set node property 1
    prop1 = [0.1, 0.2, 0.3, 0.4]
    nx.set_node_attributes(G, prop1, 'prop1')

    # set node property 2
    prop2 = [0.5, 0.6, 0.4, 0.1]
    nx.set_node_attributes(G, prop2, 'prop2')

    # set node property 3
    prop3 = [20, 10, 5, 1]
    nx.set_node_attributes(G, prop3, 'prop3')

    # set node property 4
    prop4 = [24, 256, 2547, 101]
    nx.set_node_attributes(G, prop4, 'prop4')

    # create pie-chart in nodes
    H = nx.nx_agraph.to_agraph(G)


    H.node_attr['style'] = 'wedged'

    for i in H.nodes():
        n = H.get_node(i)
        n.attr['prop1'] = # Here, I want to convert this prop1 = [0.1, 0.2, 0.3, 0.4] to colormap and assign colors
    plt.show()

Узлам присвоены четыре свойства: prop1, prop2, prop3 и prop4. Я хочу создать 4 равные дроби на круговой диаграмме (аналогично this, но равные дроби) и раскрасить каждую дробь на основе значения хранятся в переменных prop1, prop2, prop3 и prop4.

Короче говоря, вместо того, чтобы назначать один цвет каждому узлу, здесь у меня есть круговая диаграмма с количеством фракций, равным количеству атрибутов / свойств узла. Значения, сохраненные для каждого свойства, будут использоваться для присвоения цветов фракциям, присутствующим на круговой диаграмме, расположенной в центре каждого узла.

Любые предложения о том, как это сделать, будут действительно полезны.


person Natasha    schedule 10.03.2020    source источник
comment
Скажем, свойство узла 1 имеет значение [1,1,1,1], а всего имеется 4 свойства. IIUC, вы хотите раскрасить одну четверть круговой диаграммы, но каким цветом? Как вы решаете, станет ли [0,0,0,1] цветом, отличным от цвета [0,0,1,0]?   -  person warped    schedule 13.03.2020
comment
@warped Большое спасибо за ответ. Я бы предпочел назначать шкалу цветов на основе максимального и минимального значения, вычисленного из диапазона значений всех узлов и всех свойств. Например, здесь min равно 0, а max равно 1. Таким образом, [0,0,0,1] будет иметь черный цвет в четвертой четверти и белый в остальном. Точно так же [0,0,1,0] будет закодирован черным цветом в третьем квартале.   -  person Natasha    schedule 13.03.2020


Ответы (1)


Для узлов: plt.pie принимает координаты для установки центра. Эти координаты могут быть сгенерированы с помощью netwrokx. Затем вы рисуете пироги вместо узлов.

Чтобы получить цвета, вы можете использовать тот факт, что подача значений с плавающей запятой в цветовую карту возвращает значения rgb, которые plt.pie принимает в качестве входных данных. Итак, если вы нормализуете свои данные, вы можете ввести отдельные значения в цветовую карту.

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np


# parameters for pie plot
radius = 0.2
cmap = plt.cm.viridis

# make graph
G = nx.Graph()
nodes = [1,2,3,4]
edges = ((1,2),(3,2),(1,4),(3,4))
G.add_nodes_from(nodes)
G.add_edges_from(edges)
pos = nx.spring_layout(G)


# storing attributes in a dict
attrs = {
    1:[1,1,1],
    2:[0.5, 1, 0],
    3:[0, 0.6, 0],
    4:[0.5, 1, 0.5],
}

# normalising data to make colors
a = np.array(list(attrs.values()))
maxes = np.max(a, axis=0) # note that this will throw an error if different nodes have different number of features. 


# collect colors in dictionary    
colors= {}

for key, val in attrs.items():
    colors[key] = list(np.array(val)/maxes)

# draw graph and draw pieplots instead of nodes

nx.draw_networkx_edges(G, pos=pos)
for node in G.nodes:

    attributes = attrs[node]

    a = plt.pie(
        [1]*len(attributes), # s.t. all wedges have equal size
        center=pos[node], 
        colors = [cmap(a) for a in colors[node]],
        radius=radius)

plt.ylim(-2,2)
plt.xlim(-2,2)

введите здесь описание изображения

person warped    schedule 13.03.2020