Mpld3: ENH : twinx/twiny ne fonctionne pas.

Créé le 7 mai 2014  ·  17Commentaires  ·  Source: mpld3/mpld3

twinx/twiny ne fonctionnent pas comme prévu. Je sais que cela figure sur la liste TODO, mais il n'y a pas encore de problème ouvert pour cela.

Il semble que seul le dernier ensemble de données soit tracé. Voici l'exemple officiel.

mpld3 renvoie :
image

tk-agg renvoie :
image

Code à reproduire

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import mpld3
mpld3.enable_notebook()

fig, ax1 = plt.subplots()
t = np.arange(0.01, 10.0, 0.01)
s1 = np.exp(t)
ax1.plot(t, s1, 'b-')
ax1.set_xlabel('time (s)')
# Make the y-axis label and tick labels match the line color.
ax1.set_ylabel('exp', color='b')
for tl in ax1.get_yticklabels():
    tl.set_color('b')


ax2 = ax1.twinx()
s2 = np.sin(2*np.pi*t)
ax2.plot(t, s2, 'r.')
ax2.set_ylabel('sin', color='r')
for tl in ax2.get_yticklabels():
    tl.set_color('r')
plt.show()

Commentaire le plus utile

J'ai évité le problème en définissant un alpha sur l'arrière-plan du deuxième axe.

ax2.patch.set_alpha(0.0)

Tous les 17 commentaires

PS sous Fonctionnalités, le dernier point "des outils d'interactivité supplémentaires, tels que le brushing et le box-zoom" peuvent probablement être supprimés, car le box-zoom et le brusing sont tous deux implémentés.

Merci - j'imagine que ce sera un problème ouvert pendant un bon bout de temps... le résoudre impliquerait des changements très fondamentaux dans le package.

Par curiosité : le problème est-il dans d3.js, mplexporter ou mpld3 ?

Peut-être un avertissement pourrait-il être ajouté? (Twinx x pas encore implémenté)

Hmm, ou mieux encore, puisque les coches du cadre à droite sont captées, je pourrais peut-être faire semblant en traçant une ligne bleue à l'échelle sur le premier (axes de gauche). J'essaierai demain...

Un avertissement serait une bonne idée. Cela devrait arriver dans mplexporter/exporter.py . Je ne sais pas comment détecter au mieux cela dans l'objet Axes. La première étape pour déterminer comment mettre en œuvre cela est probablement de savoir comment déclencher un avertissement lorsqu'il existe !

twinx() et twiny() entraînent la création d'axes supplémentaires qui ont le même emplacement que les axes d'origine. Détecter si deux axes sont jumeaux n'est pas trop difficile :

import numpy as np
import matplotlib.pyplot as plt


fig = plt.figure()
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)

t = np.arange(0.01, 10.0, 0.01)
s1 = np.exp(t)
ax1.plot(t, s1, 'b-')
ax1.set_xlabel('time (s)')
# Make the y-axis label and tick labels match the line color.
ax1.set_ylabel('exp', color='b')
for tl in ax1.get_yticklabels():
    tl.set_color('b')


ax3 = ax1.twinx()
s2 = np.sin(2*np.pi*t)
ax3.plot(t, s2, 'r.')
ax3.set_ylabel('sin', color='r')
for tl in ax3.get_yticklabels():
    tl.set_color('r')

print ax1.get_shared_x_axes().joined(ax1, ax2)
print ax1.get_shared_x_axes().joined(ax1, ax3)

print ax2.get_shared_x_axes().joined(ax2, ax1)
print ax2.get_shared_x_axes().joined(ax2, ax3)

print ax3.get_shared_x_axes().joined(ax3, ax1)
print ax3.get_shared_x_axes().joined(ax3, ax2)

plt.show()

Étant donné que les deux axes sont simplement empilés, j'ai supposé que tout est passé à D3, qui dessine simplement les deux axes l'un sur l'autre. J'ai vérifié cela avec un simple plugin et c'est bien le cas. L'exponentielle Line2D et le sin Line2D sont présents du côté D3. En fait, la figure du côté D3 a deux axes. Cela explique également pourquoi les ticks sont rendus correctement. Il n'y a rien des seconds axes tracés sur eux.

OK, donc les deux axes sont dessinés, mais l'un est au-dessus de l'autre. Comme ils ont un fond blanc opaque, le contenu des axes inférieurs est masqué. De plus, étant donné que les événements de souris ne se propagent pas à travers les éléments axes, seuls les axes supérieurs répondent au zoom.

Corriger cela nécessitera un certain remaniement de la mise en page mpld3. Je me demande comment matplotlib lui-même gère cela?

Exactement.

Il semble que axes._frameon soit utilisé pour contrôler le dessin du patch d'arrière-plan ainsi que le cadre autour du patch. Frameon est vrai pour les premiers axes et faux pour les seconds axes. Si nous définissons maintenant frameon sur True, nous ne voyons plus la ligne appartenant aux premiers axes :

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

t = np.arange(0.01, 10.0, 0.01)
s1 = np.exp(t)
ax1.plot(t, s1, 'b-')
ax1.set_xlabel('time (s)')
# Make the y-axis label and tick labels match the line color.
ax1.set_ylabel('exp', color='b')
for tl in ax1.get_yticklabels():
    tl.set_color('b')

ax2 = ax1.twinx()
s2 = np.sin(2*np.pi*t)
sin = ax2.plot(t, s2, 'r.')
ax2.set_ylabel('sin', color='r')
for tl in ax2.get_yticklabels():
    tl.set_color('r')

print ax1.get_frame_on()
print ax2.get_frame_on()

ax2.set_frame_on(True)

plt.show()

Cela suggère que ce problème est lié à #186 et que s'attaquer à l'un devrait également aider à s'attaquer à l'autre.

Ah - c'est super ! Merci d'avoir creusé ça.

Comment voudriez-vous aborder ce problème? La solution la plus évidente serait de transmettre frame_on et de modifier la méthode de dessin de mpld3_Axes pour prendre en compte si frame_on est True ou False.

En parcourant le code, cela entraînerait des changements dans mplexporter et MPD3Renderer, côté python, et un changement dans mpld3Axes côté javascript.

Oui : mplexporter devrait être mis à jour pour passer par frame_on , et si c'est False, les lignes associées et la couleur de remplissage devraient être transparentes.

J'ai évité le problème en définissant un alpha sur l'arrière-plan du deuxième axe.

ax2.patch.set_alpha(0.0)
ax2.patch.set_alpha(0.0)

permet aux lignes d'apparaître, mais les outils de survol, de panoramique et de zoom ne fonctionnent toujours pas sur les axes inférieurs. Existe-t-il un moyen de permettre aux outils de travailler sur tous les axes ?

A moins que je ne me trompe, c'est toujours un problème. En utilisant ax2.patch.set_alpha(0.0) je peux voir mes deux tracés jumeaux, mais le zoom/panoramique ne fonctionne toujours que pour les axes supérieurs. Les deux graphiques changent, mais seuls l'axe x et l'axe y secondaire répondent à la nouvelle mise à l'échelle.

Un autre problème que j'ai trouvé est si vous essayez d'utiliser trois axes x. Le troisième devrait être à droite comme décrit dans cet exemple , mais il ne fonctionne pas comme il est censé l'être. Le troisième l'emporte sur le second. L'outil de zoom ne fonctionne toujours pas avec la méthode twinx() pour moi. J'espère que vous pourrez le réparer bientôt (si j'ai du temps libre, j'essaierai de le faire).

captura de tela de 2017-09-10 01-21-32

@fronchetti ce projet n'est plus maintenu, et ce depuis quelques années. Dans le fichier README :

Remarque : mpld3 n'est plus activement maintenu : les demandes de fonctionnalités et les rapports de bogues sont susceptibles de rester sans réponse. Si vous souhaitez maintenir ce projet, veuillez contacter l'un des propriétaires du référentiel.

Il existe de nombreuses autres options de traçage Web/notebook pour Python : altair, bokeh, bqplot, pour n'en nommer que quelques-unes. [divulgation : je suis un développeur principal de Bokeh] Ou si vous souhaitez vous approprier ce projet, je vous suggère d'envoyer un e-mail à Jake.

Aie! Je n'ai pas vu cette information sur leur site. Je suis juste venu ici à la recherche de problèmes qui pourraient résoudre mon problème. Merci @bryevdv , je vais essayer une autre option de traçage.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

sheldonpark picture sheldonpark  ·  7Commentaires

pranet picture pranet  ·  6Commentaires

edvakf picture edvakf  ·  29Commentaires

jakevdp picture jakevdp  ·  4Commentaires

arnaudrenaud picture arnaudrenaud  ·  4Commentaires