La question:
J'essaie de saisir le concept de monkey patching et en même temps créer une fonction pour produire le tracé chronologique parfait. Comment puis-je inclure la fonctionnalité matplotlib suivante dans les pandas pandas.DataFrame.plot () ?
# imports import pandas as pd import numpy as np from jupyterthemes import jtplot # Sample data np.random.seed(123) rows = 50 dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable Y']) dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=[' Variable X']) df = pd.concat([dfx,dfy], axis = 1) jtplot.style() # Plot with default settings df.plot() # Wrap df.plot() and matplotlib spine in a function def plotPerfect(df, spline): ax = df.plot() if not spline: ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False) return(ax) # Plot the perfect time-series plot plotPerfect(df = df, spline = False)
code complet à la fin de la question
Les détails:
Je pense que les paramètres par défaut dans df.plot ()
sont assez soignés , surtout si vous exécutez un bloc-notes Jupyter avec un thème sombre comme chesterish de dunovank :
Et j'aimerais l'utiliser autant que possible pour mon flux de travail d'analyse de données, mais j'aimerais vraiment pour supprimer le cadre (ou ce qu'on appelle les épines) comme ceci:
C'est peut-être le moment idéal- tracé de série. Mais df.plot ()
n'a pas d'argument intégré pour cela. La chose la plus proche semble être grid = False
, mais cela enlève toute la grille dans la même exécution:
Ce que j'ai essayé
Je sais que je peux envelopper l'extrait de code spine
dans une fonction avec df.plot ()
donc je me retrouve avec ceci:
Extrait 1:
def plotPerfect(df, spline): ax = df.plot() if not spline: ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False) return(ax) plotPerfect(df = df, spline = False)
Sortie 1:
Mais est-ce la "meilleure" façon de le faire en ce qui concerne à la flexibilité et à la lisibilité des futurs amendements? Ou même le plus rapide en termes de temps d'exécution si nous parlons de centaines de tracés?
Je sais comment je peux obtenir le df.plot ()
source , mais tout me quitte déconcerté. Alors, comment faire inclure ces paramètres dans df.plot
? Et peut-être que l'approche de la fonction encapsulée est aussi bonne que le patching de singe?
Extrait de code complet et exemples de données:
reproduisez l'exemple à 100%, collez-le dans une cellule Jupyter Notebook avec le thème chesterish
activé:
ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.spines['left'].set_visible(False)
3 Réponses :
Je répondrais en partie à votre partie de personnalisation de la question: au lieu de masquer chaque spline par une commande séparée, vous pouvez les placer dans une boucle for
comme suit.
def plotPerfect(df, spline): ax = df.plot() if not spline: for i in ax.spines.values(): i.set_visible(False) return(ax)
Si vous voulez masquer les quatre épines et ne voulez pas spécifier manuellement le haut, la droite, etc., vous pouvez le faire de manière plus automatisée comme suit. Le premier vous permet de choisir ceux à masquer.
def plotPerfect(df, spline): ax = df.plot() if not spline: for i in ['top', 'right', 'bottom', 'left']: ax.spines[i].set_visible(False) return(ax) # Plot the perfect time-series plot plotPerfect(df = df, spline = False)
Des solutions alternatives à l'autre réponse consisteraient à utiliser plt .box (False)
ou ax.set_frame_on (False)
, ces deux masquent le patch rectangle des axes.
def plotPerfect(df, spline): ax = df.plot() if not spline: ax.set_frame_on(False) # plt.box(False) # another possible option return ax
Notez que set_frame_on (Faux)
supprime l'arrière-plan en le rendant transparent, ce qui pourrait ne pas être souhaité
Cela ressemble à un xyproblem .
Le question demande la fonction de tracé de pandas de patching de singe pour ajouter des fonctionnalités supplémentaires. Cela peut dans ce cas être fait en remplaçant la fonction pandas.plotting._core.plot_frame
par une version personnalisée de celle-ci.
plt.rcParams.update(mystyle)
Ensuite, utilisez-la comme
import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0) df.plot() ## Normal Plot with plt.style.context(mystyle): df.plot() ## "Despined" Plot
Notez que si dans le notebook jupyter, la cellule avec le patch monkey ne peut pas être s'exécuter plus d'une fois, sinon cela finirait par récurer.
Ce qui précède est assez exagéré pour changer le style d'un tracé. Il faut plutôt utiliser les options de style de matplotlib .
mystyle = {"axes.spines.left" : False, "axes.spines.right" : False, "axes.spines.bottom" : False, "axes.spines.top" : False, "axes.grid" : True, "xtick.bottom" : False, "ytick.left" : False,}
Ensuite, pour appliquer ceci à certains tracés du notebook, utilisez le gestionnaire plt.style.context
,
df = pd.DataFrame([[0.1, 0.1], [0.9, 0.9]]).set_index(0) df.plot() ## Normal Plot df.plot(spline=False) ## "Despined" Plot
Ou, si vous souhaitez appliquer ce style globalement, mettez à jour le rcParams
. p>
import pandas as pd import pandas.plotting._core orginal = pandas.plotting._core.plot_frame def myplot(*args, **kwargs): spline = kwargs.pop("spline", True) ax = orginal(*args, **kwargs) ax.set_frame_on(spline) ax.grid(not spline) ax.tick_params(left=spline, bottom=spline) return ax pandas.plotting._core.plot_frame = myplot
@ ImportanceOfBeingErnest Merci! Vous illustrez également quelques autres aspects qui m'intéressaient, c'est encore plus que ce que j'espérais! Je suis également émerveillé par le fait que "cela semble être un xyproblem" et le libellé de votre lien est une manière élégante et subtile d'appeler quelqu'un un n00b ignorant. Au début, je pensais que vous parliez de Python (x, y) dont j'avais à peine entendu parler mais avait hâte d'en savoir plus.
Personnellement je regarde les choses d'une autre manière: j'essaye de trouver une solution (spline, ou X) que je pense qu'il serait possible de résoudre d'une autre manière (peut-être même plus "pythonique") (singe patching, ou Y). Et je pense que c'est une excellente façon d'apprendre de nouvelles choses. J'ai l'impression de travailler avec plusieurs pièces d'un puzzle en même temps. Quoi qu'il en soit, merci encore!
Vous avez suffisamment de détails sur ce que vous voulez faire dans votre question (le X), donc pas de soucis - comme vous pouvez le voir, on peut parfaitement y répondre.
Je viens de réaliser comment j'aurais dû poser la question: est-il possible de prendre df.plot () et d'inclure spines = False comme argument? Tout comme box ou kind est un argument en soi? Et remplacer MY df.plot () avec le df.plot original ()? Peut-être utiliser des patchs de singe?
Cela fait un an que vous avez répondu à cette question, mais auriez-vous une question complémentaire? J'essaie d'appliquer ce que vous avez montré ici à d'autres scénarios. Donc, ce que je voudrais faire, c'est soulever une autre question dans laquelle je pose des questions sur les détails de la solution que vous suggérez ici. Serait-ce OK?
Êtes-vous intéressé par le patching de singe ou customizong les tracés ? Cela me semble tout à fait sans rapport avec moi.
@Goyo Mon principal objectif est de modifier efficacement un tas de tracés. Et j'avais l'impression (vague) que cela pourrait être un bon cas d'utilisation pour le patching de singe.