【问题标题】:MPLD3: label information of barplotMPLD3:条形图的标签信息
【发布时间】:2014-12-01 19:30:56
【问题描述】:

我正在尝试扩展here提供的示例:

from mpld3 import utils

class ClickInfo(plugins.PluginBase):
    """Plugin for getting info on click"""

    JAVASCRIPT = """
    mpld3.register_plugin("clickinfo", ClickInfo);
    ClickInfo.prototype = Object.create(mpld3.Plugin.prototype);
    ClickInfo.prototype.constructor = ClickInfo;
    ClickInfo.prototype.requiredProps = ["id"];
    function ClickInfo(fig, props){
        mpld3.Plugin.call(this, fig, props);
    };

    ClickInfo.prototype.draw = function(){
        var obj = mpld3.get_element(this.props.id);
        obj.elements().on("mousedown",
                          function(d, i){alert("clicked on points[" + i + "]");});
    }
    """
    def __init__(self, points):
        self.dict_ = {"type": "clickinfo",
                      "id": utils.get_id(points)}

fig, ax = plt.subplots()
points = ax.scatter(np.random.rand(50), np.random.rand(50),
                    s=500, alpha=0.3)

plugins.connect(fig, ClickInfo(points))

我的目的是做同样的事情(单击对象时显示标签)但使用条形图而不是散点图。

它不适用于相同的 Javascript 代码:

from mpld3 import utils

class ClickInfo(plugins.PluginBase):
    """Plugin for getting info on click"""

    JAVASCRIPT = """
    mpld3.register_plugin("clickinfo", ClickInfo);
    ClickInfo.prototype = Object.create(mpld3.Plugin.prototype);
    ClickInfo.prototype.constructor = ClickInfo;
    ClickInfo.prototype.requiredProps = ["id"];
    function ClickInfo(fig, props){
        mpld3.Plugin.call(this, fig, props);
    };

    ClickInfo.prototype.draw = function(){
        var obj = mpld3.get_element(this.props.id);
        obj.elements().on("mousedown",
                          function(d, i){alert("clicked on bar[" + i + "]");});
    }
    """
    def __init__(self, bars):
        self.dict_ = {"type": "clickinfo",
                      "id": utils.get_id(bars)}
x = range(0,10)
y = np.random.rand(10)

fig, ax = plt.subplots()
bars = ax.bar(x, y)

plugins.connect(fig, ClickInfo(bars))

但是,我可以获得其中一个栏的工作行为。例如,plugins.connect(fig, ClickInfo(bars[0])),点击第一个栏将触发警报 Javascript 代码。

问题:

我怎样才能让每个条的行为都相同?

此外,由于我对 D3 和 Javascript 缺乏经验,因此对代码如何工作的简短说明将非常有帮助。也欢迎任何学习资源,因为我找不到 MPLD3 教程。

【问题讨论】:

    标签: javascript python django d3.js mpld3


    【解决方案1】:

    我遇到了同样的问题,我扩展了带有浮动标签的堆叠条形图的答案,您可以在此处找到:

    http://nbviewer.ipython.org/gist/Iggam/416520098460b057c208

    代码可以在这里找到:

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import mpld3
    from mpld3 import plugins, utils
    
    class BarLabelToolTip(plugins.PluginBase):    
        JAVASCRIPT = """
        mpld3.register_plugin("barlabeltoolTip", BarLabelToolTip);
        BarLabelToolTip.prototype = Object.create(mpld3.Plugin.prototype);
        BarLabelToolTip.prototype.constructor = BarLabelToolTip;
        BarLabelToolTip.prototype.requiredProps = ["ids","labels"];
        BarLabelToolTip.prototype.defaultProps = {
            hoffset: 0,
            voffset: 10,
            location: 'mouse'
        };
        function BarLabelToolTip(fig, props){
            mpld3.Plugin.call(this, fig, props);
        };
    
        BarLabelToolTip.prototype.draw = function(){
            var svg = d3.select("#" + this.fig.figid);
            var objs = svg.selectAll(".mpld3-path");
            var loc = this.props.location;
            var labels = this.props.labels
    
            test = this.fig.canvas.append("text")
                .text("hello world")
                .style("font-size", 72)
                .style("opacity", 0.5)
                .style("text-anchor", "middle")
                .attr("x", this.fig.width / 2)
                .attr("y", this.fig.height / 2)
                .style("visibility", "hidden");
    
            function mousemove(d) {
                if (loc === "mouse") {
                    var pos = d3.mouse(this.fig.canvas.node())
                    this.x = pos[0] + this.props.hoffset;
                    this.y = pos[1] - this.props.voffset;
                }
    
                test
                    .attr("x", this.x)
                    .attr("y", this.y);
            };
    
            function mouseout(d) {
                test.style("visibility", "hidden")
            };
    
            this.props.ids.forEach(function(id, i) {
    
    
                var obj = mpld3.get_element(id);
    
                function mouseover(d) {
                    test.style("visibility", "visible")
                        .style("font-size", 24)
                        .style("opacity", 0.7)
                        .text(labels[i])
                };
    
                obj.elements().on("mouseover", mouseover.bind(this))
    
            });
    
           objs.on("mousemove", mousemove.bind(this)) 
               .on("mouseout", mouseout.bind(this));     
    
        }       
        """
        def __init__(self, ids, labels=None, location="mouse"):
    
            self.dict_ = {"type": "barlabeltoolTip",
                          "ids": ids,
                          "labels": labels,
                          "location": location}
    
    fig, ax = plt.subplots()
    x = range(0,10)
    y = np.random.rand(10)
    bars = ax.bar(x, y)
    
    labels = [round(bar.get_height(),2) for bar in bars]
    ids = [utils.get_id(bar) for bar in bars]
    
    plugins.connect(fig, BarLabelToolTip(ids, labels))
    

    【讨论】:

    • 嗨罗伯特,虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。请看这里:Why and how are some answers deleted?
    【解决方案2】:

    你在正确的轨道上。这是一种让你拥有的东西发挥作用的方法:

    from mpld3 import utils, plugins
    
    class ClickInfo(plugins.PluginBase):
        """Plugin for getting info on click"""
    
        JAVASCRIPT = """
        mpld3.register_plugin("clickinfo", ClickInfo);
        ClickInfo.prototype = Object.create(mpld3.Plugin.prototype);
        ClickInfo.prototype.constructor = ClickInfo;
        ClickInfo.prototype.requiredProps = ["ids"];
        function ClickInfo(fig, props){
            mpld3.Plugin.call(this, fig, props);
        };
    
        ClickInfo.prototype.draw = function(){
            this.props.ids.forEach(function(id, i) {
                var obj = mpld3.get_element(id);
                obj.elements().on("mousedown",
                                  function(d){alert("clicked on bar[" + i + "]");});
                                  });
        }
        """
        def __init__(self, bars):
            self.dict_ = {"type": "clickinfo",
                          "ids": [utils.get_id(bar) for bar in bars]}
    x = range(0,10)
    y = np.random.rand(10)
    
    fig, ax = plt.subplots()
    bars = ax.bar(x, y)
    
    plugins.connect(fig, ClickInfo(bars))
    

    您可以see it in action here。也许其他人有时间通过​​更多地解释代码的工作原理来扩展这个答案。

    【讨论】:

    • 谢谢!我了解 python 部分,但对this.props.ids.forEach(function(id, i) { 感到困惑。不过,答案是完美的!
    • 这里是这种函数式编程的更 Pythonic 版本:map(lambda id: (...), [id1,id2,id3])
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多