在python中以曲线形式向和弦图添加颜色条

时间:2017-08-24 14:13:56

标签: python plotly colorbar chord-diagram

我需要帮助找出如何在我制作的和弦图中添加彩条。我想添加一个颜色条,例如在heat map但在chord diagram中,不要与python中的填充和弦图混淆。

我试图添加更多链接和图片,但我想我需要更多声望:(热图链接是plot.ly/python/heatmaps。和弦图是plot.ly/python/chord-diagram。填充的和弦图位于plot.ly/python/filled-chord-diagram。

我计划使用热图的方法是让和弦图上的每一行都是基于数据的特定颜色。例如,如果数据显示该行的值为80,那么它就像热图中的红色一样。如果数据表示50,那将是橙色黄色,就像在热图中一样。

非常感谢你!

1 个答案:

答案 0 :(得分:1)

假设您的颜色值存储在名为my_weights的列表中。

my_weights = [random.random() for _ in E]

其中E是边缘列表。

然后我们可以添加仅用于绘制颜色条的迹线。它的标记隐藏在其中一个节点后面。

color_trace = plotly.graph_objs.Scatter(x=[0 for _ in my_weights],
                                        y=[0 for _ in my_weights],
                                        mode='markers',
                                        marker=plotly.graph_objs.Marker(
                                            colorscale=[
                                                [c / 100.0, 'rgba({}, {}, {}, {})'.format(*color_range(c / 100.0))] for
                                                c in range(101)],
                                            size=1,
                                            color=my_weights,
                                            showscale=True,
                                            )
                                        )

对于色阶,我们可以使用matplotlib获取custom color generator

color_range = plt.get_cmap('OrRd')

完整代码基于示例here并生成以下图表。

enter image description here

import igraph as ig
import numpy as np
import plotly
import matplotlib.pyplot as plt
import random

color_range = plt.get_cmap('OrRd')


def dist(a, b):
    return np.linalg.norm(np.array(a) - np.array(b))


def get_idx_interv(d, D):
    k = 0
    while d > D[k]:
        k += 1
    return k - 1


def deCasteljau(b, t):
    n = len(b)
    a = np.copy(b)  # shallow copy of the list of control points
    for r in range(1, n):
        a[:n - r, :] = (1 - t) * a[:n - r, :] + t * a[1:n - r + 1, :]
    return a[0, :]


def bezierCv(b, nr=5):
    t = np.linspace(0, 1, nr)
    return np.array([deCasteljau(b, t[k]) for k in range(nr)])


G = ig.Graph.Read_GML('Eurovision15.gml')

V = list(G.vs)
G.vs.attributes()
labels = [v['label'] for v in V]
E = [e.tuple for e in G.es]
ContestantLst = [G.vs[e[2]] for e in E]
Contestant = list(set([v['label'] for v in ContestantLst]))
layt = G.layout('circular')
Weights = map(int, G.es["weight"])

Dist = [0, dist([1, 0], 2 * [np.sqrt(2) / 2]), np.sqrt(2),
        dist([1, 0], [-np.sqrt(2) / 2, np.sqrt(2) / 2]), 2.0]
params = [1.2, 1.5, 1.8, 2.1]

node_color = ['rgba(0,51,181, 0.85)' if v['label'] in Contestant else '#CCCCCC' for v in G.vs]
line_color = ['#FFFFFF' if v['label'] in Contestant else 'rgb(150,150,150)' for v in G.vs]
edge_colors = ['#d4daff', '#84a9dd', '#5588c8', '#6d8acf']

L = len(layt)

Xn = [layt[k][0] for k in range(L)]
Yn = [layt[k][2] for k in range(L)]

lines = list()
edge_info = list()
my_weights = [random.random() for _ in E]

for j, e in enumerate(E):
    A = np.array(layt[e[0]])
    B = np.array(layt[e[2]])
    d = dist(A, B)
    K = get_idx_interv(d, Dist)
    b = [A, A / params[K], B / params[K], B]
    color = edge_colors[K]
    pts = bezierCv(b)
    text = V[e[0]]['label'] + ' to ' + V[e[2]]['label'] + ' ' + str(Weights[j]) + ' pts'
    mark = deCasteljau(b, 0.9)
    edge_info.append(plotly.graph_objs.Scatter(x=mark[0],
                                               y=mark[2],
                                               mode='markers',
                                               marker=plotly.graph_objs.Marker(size=0.5, color=edge_colors),
                                               text=text,
                                               hoverinfo='text'
                                               )
                     )

    lines.append(plotly.graph_objs.Scatter(x=pts[:, 0],
                                           y=pts[:, 1],
                                           mode='lines',
                                           line=plotly.graph_objs.Line(
                                               color='rgba({}, {}, {}, {})'.format(*color_range(my_weights[j])),
                                               shape='spline',
                                               width=Weights[j] / 5),
                                           hoverinfo='none')
                 )

trace2 = plotly.graph_objs.Scatter(x=Xn,
                                   y=Yn,
                                   mode='markers',
                                   marker=plotly.graph_objs.Marker(symbol='dot',
                                                                   size=15,
                                                                   color=node_color,
                                                                   line=plotly.graph_objs.Line(color=line_color,
                                                                                               width=0.5)
                                                                   ),
                                   text=labels,
                                   hoverinfo='text'
                                   )

color_trace = plotly.graph_objs.Scatter(x=[0 for _ in my_weights],
                                        y=[0 for _ in my_weights],
                                        mode='markers',
                                        marker=plotly.graph_objs.Marker(
                                            colorscale=[
                                                [c / 100.0, 'rgba({}, {}, {}, {})'.format(*color_range(c / 100.0))] for
                                                c in range(101)],
                                            size=1,
                                            color=my_weights,
                                            showscale=True,
                                            )
                                        )

axis = dict(showline=False,
            zeroline=False,
            showgrid=False,
            showticklabels=False,
            title=''
            )

layout = plotly.graph_objs.Layout(showlegend=False,
                                  autosize=False,
                                  width=800,
                                  height=850,
                                  xaxis=plotly.graph_objs.XAxis(axis),
                                  yaxis=plotly.graph_objs.YAxis(axis),
                                  margin=plotly.graph_objs.Margin(l=40,
                                                                  r=40,
                                                                  b=85,
                                                                  t=100,
                                                                  ),
                                  hovermode='closest')

data = plotly.graph_objs.Data([color_trace] + lines + edge_info + [trace2])
fig = plotly.graph_objs.Figure(data=data, layout=layout)
plotly.offline.plot(fig, filename='Eurovision-15.html')