2014-12-01 3 views
0

Я пытаюсь расширить пример при условии here:MPLD3: информация этикетка barplot

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)) 

Моя цель состоит в том, чтобы сделать то же самое (отображение метки, когда объект будет нажата), но с barplot вместо рассеивания ,

Он не работает с тем же кодом 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.

ответ

3

Вы на правильном пути. Вот способ сделать то, что у вас есть работа:

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. Возможно, кто-то еще успеет продлить этот ответ, объяснив, как работает код.

+0

Спасибо! Я понимаю часть python, но остаюсь озадаченным 'this.props.ids.forEach (function (id, i) {'. Ответ является идеальным, хотя! – hhh

+0

Вот более питонная версия такого рода функционального программирования: 'map (lambda id: (...), [id1, id2, id3]) ' –

4

Я столкнулся с той же проблемой, и я расширил ответ на сложенной barplot с плавающей этикетки, которые вы можете найти здесь:

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)) 
+0

Привет, Роберт, хотя эта ссылка может ответить на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. Обратите внимание: [Почему и как удалены некоторые ответы?] (Http://stackoverflow.com/help/deleted-answers) – bummi

Смежные вопросы