从熊猫/字典创建交互式层次结构图

时间:2020-03-10 20:57:48

标签: python python-3.x pandas graph tree

我有数据显示每个员工与其经理(Person:Manager)的关系-

data = {'PersonX':'Person1', 'PersonY':'Person1', 'PersonZ':'Person 2', 'Person1':'Person100','Person2':'Person100' }

我正在尝试以干净的图表形式显示上述数据中的层次结构图,并且是否可以在可视化本身中过滤该数据,这是一个奖励。

我获取的数据有时可能包含5个人,有时记录数量会超过5000。

我已经尝试了这些方法,但是它们离生成任何交互式图形都不远。

代码-

尝试1-

import pandas as pd
import networkx as nx

d = {'PersonX': 'Person1', 'PersonY': 'Person1', 'PersonZ': 'Person2', 'Person1': 'Person100', 'Person2': 'Person100'}
df = pd.DataFrame(d.items(), columns=['Person', 'Manager'])
G = nx.from_pandas_edgelist(df,  source='Person', target='Manager')
nx.draw(G, with_labels=True)
plt.show()

Network X graph

尝试2-

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from scipy.cluster import hierarchy
df2 = df.apply(LabelEncoder().fit_transform)
df2.set_index('Manager', inplace=True)
Z = hierarchy.linkage(df2, 'ward')
hierarchy.dendrogram(hierarchy.linkage(df2, method='ward'))
plt.show()

Attempt 2nd

尝试3-

print('strict digraph tree {')
for row in d.items():
    print('    {0} -> {1};'.format(*row))
print('}')

然后运行

test.py |点-Tpng -otree.png

GraphViz

2 个答案:

答案 0 :(得分:4)

我用下面的代码创建了一个交互式的图形,这是一个正在进行的工作,但是我想发布它,以便人们在需要时可以使用它。

import pandas as pd
import dash
import dash_html_components as html
import dash_cytoscape as cyto
from matplotlib import colors as mcolors
from itertools import zip_longest
from ast import literal_eval

colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS)
# Sort colors by hue, saturation, value and name.
by_hsv = sorted((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name)
                for name, color in colors.items())
sorted_names = [name for hsv, name in by_hsv]

app = dash.Dash(__name__)
# colors = ['red', 'blue', 'green', 'yellow', 'pink']

# stylesheet for the web page generated

default_stylesheet = [
    {
        "selector": 'node',
        'style': {
            "opacity": 0.9,
            'height': 15,
            'width': 15,
            'background-color': '#222222',
            'label': 'data(label)'
        }
    },
    {
        "selector": 'edge',
        'style': {
            "curve-style": "bezier",
            "opacity": 0.3,
            'width': 2
        }
    },
    *[{
        "selector": '.' + color,
        'style': {'line-color': color}
    } for color in sorted_names]
]

# Example data for illustration
# My actual data was in the excel file with two columns Managers and Person

managers = ['Person A',
            'Person A',
            'Person A',
            'Person A',
            'Person A',
            'Person A',
            'Person B',
            'Person B',
            'Person B',
            'Person B',
            'Person B',
            'Person B',
            'Person C',
            'Person C',
            'Person C',
            'Person C',
            'Person C',
            'Person C',
            'Person V',
            'Person V',
            'Person V',
            'Person V',
            'Person V']

person = ['Person D',
          'Person E',
          'Person F',
          'Person G',
          'Person H',
          'Person I',
          'Person J',
          'Person K',
          'Person L',
          'Person M',
          'Person N',
          'Person O',
          'Person P',
          'Person Q',
          'Person R',
          'Person S',
          'Person T',
          'Person U',
          'Person A',
          'Person W',
          'Person X',
          'Person B',
          'Person C']

# Creating a dataframe with the illustration data
df = pd.DataFrame(list(zip(person, managers)), columns=['Person', 'Manager'])
# Giving colors to each managers in the dataframe
df['colors'] = df['Manager'].map(dict(zip_longest(list(set(managers)), sorted_names)))
# Creating the nodes within the dataframe
df['y_node_target'] = "{\"data\": {\"id\": \"" + df['Person'] + "\", \"label\":\""+df['Person']+"\"}, \"classes\": \"" + df['colors'] + "\"}"
df['y_node'] = "{\"data\": {\"id\": \"" + df['Manager'] + "\", \"label\":\""+df['Manager']+"\"}, \"classes\": \"" + df['colors'] + "\"}"
nodes = list(set(pd.concat([df['y_node'], df['y_node_target']]).to_list()))
df['Edges'] = "{\'data\': {\'source\':\"" + df['Manager'] + "\", \'target\': \"" + df[
    'Person'] + "\"},\'classes\': \"" + df['colors'] + "\"}"


# Converting the strings to dictionaries and assigning them to variables
edges = list(set(df['Edges'].astype(str).to_list()))
edges = list(map(literal_eval, edges))
nodes = list(map(literal_eval, nodes))

app.layout = html.Div([
    cyto.Cytoscape(
        id='cytoscape',
        elements=edges + nodes,
        stylesheet=default_stylesheet,
        layout={
            'name': 'breadthfirst'
        },
        style={'height': '95vh', 'width': '100%'}
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

输出是一个网页-

enter image description here

答案 1 :(得分:3)

您可以尝试使用Plotly为图形创建交互式图。这是他们的文档中的一个示例:

创建随机图

import plotly.graph_objects as go

import networkx as nx

G = nx.random_geometric_graph(200, 0.125)

创建边缘

edge_x = []
edge_y = []
for edge in G.edges():
    x0, y0 = G.nodes[edge[0]]['pos']
    x1, y1 = G.nodes[edge[1]]['pos']
    edge_x.append(x0)
    edge_x.append(x1)
    edge_x.append(None)
    edge_y.append(y0)
    edge_y.append(y1)
    edge_y.append(None)

edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='none',
    mode='lines')

node_x = []
node_y = []
for node in G.nodes():
    x, y = G.nodes[node]['pos']
    node_x.append(x)
    node_y.append(y)

node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers',
    hoverinfo='text',
    marker=dict(
        showscale=True,
        # colorscale options
        #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |
        #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |
        #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |
        colorscale='YlGnBu',
        reversescale=True,
        color=[],
        size=10,
        colorbar=dict(
            thickness=15,
            title='Node Connections',
            xanchor='left',
            titleside='right'
        ),
        line_width=2))

颜色节点点

node_adjacencies = []
node_text = []
for node, adjacencies in enumerate(G.adjacency()):
    node_adjacencies.append(len(adjacencies[1]))
    node_text.append('# of connections: '+str(len(adjacencies[1])))

node_trace.marker.color = node_adjacencies
node_trace.text = node_text

网络图

fig = go.Figure(data=[edge_trace, node_trace],
             layout=go.Layout(
                title='<br>Network graph made with Python',
                titlefont_size=16,
                showlegend=False,
                hovermode='closest',
                margin=dict(b=20,l=5,r=5,t=40),
                annotations=[ dict(
                    text="Python code: <a href='https://plot.ly/ipython-notebooks/network-graphs/'> https://plot.ly/ipython-notebooks/network-graphs/</a>",
                    showarrow=False,
                    xref="paper", yref="paper",
                    x=0.005, y=-0.002 ) ],
                xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
                yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
                )
fig.show()

这将创建一个交互式图表,如:

enter image description here

来源:Network graphs

相关问题