【问题标题】:Creating tooltip for svg linechart using matplotlib使用 matplotlib 为 svg 折线图创建工具提示
【发布时间】:2015-07-16 01:16:22
【问题描述】:

我想为使用 matplotlib 创建的 SVG 折线图创建工具提示(显示数据值)。这将使用户能够单击或将鼠标悬停在显示该特定点值的折线图中的每个标记上。

为了能够做到这一点,我需要访问 Line2D 对象的标记元素并向每个此类元素添加一个 gid。

http://matplotlib.org/examples/user_interfaces/svg_histogram.html,有一个如何为直方图完成此操作的示例。

H = plt.hist([r,r1], label=labels)
containers = H[-1]
hist_patches = {}
for ic, c in enumerate(containers):
    hist_patches['hist_%d'%ic] = []
    for il, element in enumerate(c):
        element.set_gid('hist_%d_patch_%d'%(ic, il))
        hist_patches['hist_%d'%ic].append('hist_%d_patch_%d'%(ic,il))

但是,如果我尝试使用折线图执行此操作,我会发现 Line2D 对象不可迭代——可能是因为它不是像直方图条这样的补丁集合。

H = plt.plot([1,2,3,4],[1,4,9,16], 'ro')
containers = H[-1]
enumerate(containers)

这会导致:“TypeError: 'Line2D' object is not iterable”

问题是如何从 Line2D 访问单个标记

有一些方法可以使用 matplotlib 的交互式后端来做到这一点。但我需要为非交互式 SVG 实现这一点。

【问题讨论】:

  • 尝试遍历您传递给plot(或zip(x,y))的xy 向量。无论如何,这些都是您想要添加 gid 的点,是吗?
  • 我知道这可以在交互式 matplotlib 图上完成。如何在 SVG 中做到这一点?你能举个例子吗?

标签: python svg matplotlib linechart


【解决方案1】:

我修改了 OPs linked code snippet中的代码

这至少对我有用。但是,我还没有找到区分单个标记的方法

import matplotlib.pyplot as plt
import numpy as np
import xml.etree.ElementTree as ET
from io import BytesIO

plt.rcParams['svg.fonttype'] = 'none'
_ , ax = plt.subplots(figsize=(14,8))

Rand_Values = []
Rand_Values.append(np.random.rand(20)) 
Rand_Values.append(np.random.rand(20)) 
x_axis = range(20)

for i in range(2):
    H = ax.plot(x_axis, Rand_Values[i] , label= "data set %i" % (i+1))  
    ThisContainer = H[-1]                                     
    ThisContainer.set_gid('hist_%i' % i )

plt.xlabel("x-axis label") 
plt.ylabel("random data") 
plt.title( "Interactive chart" )  

leg = ax.legend(loc='upper left', bbox_to_anchor=(0, 1), ncol=1, fancybox=True, shadow=True)

for i, t in enumerate(leg.get_texts()):
    t.set_gid('leg_text_%d' % i)

# Save SVG in a fake file object.
f = BytesIO()
plt.savefig(f, format="svg")

# Create XML tree from the SVG file.
ET.register_namespace("", "http://www.w3.org/2000/svg")
tree, xmlid = ET.XMLID(f.getvalue())

# --- Add interactivity ---
# Add attributes to the text objects.
for i, t in enumerate(leg.get_texts()):
    el = xmlid['leg_text_%d' % i]
    el.set('cursor', 'pointer')
    el.set('onclick', "toggle_hist(this)")

# Create script defining the function `toggle_hist`.
script = """
<script type="text/ecmascript">
<![CDATA[

function toggle(oid, attribute, values) {
    /* Toggle the style attribute of an object between two values.

    Parameters
    ----------
    oid : str
      Object identifier.
    attribute : str
      Name of style attribute.
    values : [on state, off state]
      The two values that are switched between.
    */
    var obj = document.getElementById(oid);
    var a = obj.style[attribute];

    a = (a == values[0] || a == "") ? values[1] : values[0];
    obj.style[attribute] = a;
    }

function toggle_hist(obj) {
    var num = obj.id.replace( /^\D+/g, '');
    toggle( 'leg_text_' + num, 'opacity', [1, 0.5]);
    toggle( 'hist_'+ num  , 'opacity', [1,0]);
    }
]]>
</script>
""" 

# Add a transition effect
css = tree.getchildren()[0][0]

css.text = css.text + "g {-webkit-transition:opacity 0.4s ease-out;" + \
    "-moz-transition:opacity 0.4s ease-out;}"


# Insert the script and save to file.
tree.insert(0, ET.XML(script))

ET.ElementTree(tree).write("svg_lineChart.svg")

【讨论】:

    【解决方案2】:

    Charts 库可能会更好地解决您的问题。它使您能够使用出色的Highcharts javascript 库来制作精美的交互式绘图。 Highcharts 使用 HTML svg 标签。

    默认情况下,所有图表都会有交互式工具提示!

    免责声明:我是该库的开发者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2019-11-25
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多