python - 使用 matplotlib 为 svg 线图创建工具提示

标签 python svg matplotlib linechart

我想为使用 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’对象不可迭代”

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

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

最佳答案

我修改了 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")

关于python - 使用 matplotlib 为 svg 线图创建工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30067642/

相关文章:

python - 如何在 Canvas 上从上到下绘制一段?

python - 将 python 代码优化为一个 return 语句

javascript - 以编程方式在 SVG 中添加 SVG

python - 获取掩码条件后的二维数组

python - matplotlib 中绘图点的标签

javascript - SVG 外来对象在更改之前不会显示

java - 在 JPanel 上绘制 SVG 图像

python - MatPlotLib绕固定轴旋转3D图

Python - 绘制周分布

python - Matplotlib:季度小刻度标签