MEP28 : Supprimer la complexité de Axes.boxplot #
Statut #
Discussion
Branches et demandes d'extraction #
La liste suivante répertorie tous les PR ouverts ou les succursales liées à ce MEP :
Déprécier les kwargs statistiques redondants dans
Axes.boxplot: https://github.com/phobson/matplotlib/tree/MEP28-initial-deprecationsDéprécier les options de style redondantes dans
Axes.boxplot: https://github.com/phobson/matplotlib/tree/MEP28-initial-deprecationsDéprécier les passages de tableaux NumPy 2D en entrée : aucun
Ajoutez des options de pré- et post-traitement à
cbook.boxplot_stats: https://github.com/phobson/matplotlib/tree/boxplot-stat-transformsExposer
cbook.boxplot_statsà traversAxes.boxplotles kwargs : aucunSupprimer les kwargs statistiques redondants dans
Axes.boxplot: AucunSupprimer les options de style redondantes dans
Axes.boxplot: AucunAutres éléments soulevés lors de la discussion : aucun
Résumé #
Au cours des dernières versions, la Axes.boxplotméthode est devenue plus complexe pour prendre en charge un style d'artiste et un calcul statistique entièrement personnalisables. Cela a conduit à Axes.boxplotêtre divisé en plusieurs parties. Les statistiques nécessaires pour dessiner une boîte à moustaches sont calculées dans
cbook.boxplot_stats, tandis que les artistes réels sont dessinés par Axes.bxp. La méthode d'origine Axes.boxplotreste l'API la plus publique qui gère la transmission des données fournies par l'utilisateur à cbook.boxplot_stats, l'envoi des résultats à Axes.bxpet le prétraitement des informations de style pour chaque facette des tracés de boîtes à moustaches.
Ce MEP décrira une voie à suivre pour annuler la complexité supplémentaire et simplifier l'API tout en maintenant une rétrocompatibilité raisonnable.
Descriptif détaillé #
Actuellement, la Axes.boxplotméthode accepte des paramètres qui permettent aux utilisateurs de spécifier des médianes et des intervalles de confiance pour chaque boîte qui sera dessinée dans le tracé. Celles-ci ont été fournies afin que les utilisateurs avancés puissent fournir des statistiques calculées d'une manière différente de la méthode simple fournie par matplotlib. Cependant, la gestion de cette entrée nécessite une logique complexe pour s'assurer que les formes de la structure de données correspondent à ce qui doit être dessiné. Pour le moment, cette logique contient 9 instructions if/else séparées imbriquées jusqu'à 5 niveaux de profondeur avec une boucle for et peut générer jusqu'à 2 erreurs. Ces paramètres ont été ajoutés avant la création de la Axes.bxpméthode, qui dessine des boîtes à moustaches à partir d'une liste de dictionnaires contenant les statistiques pertinentes. Matplotlib fournit également une fonction qui calcule ces statistiques viacbook.boxplot_stats. Notez que les utilisateurs avancés peuvent désormais a) écrire leur propre fonction pour calculer les statistiques requises par
Axes.bxp, ou b) modifier la sortie renvoyée par cbook.boxplots_stats
pour personnaliser entièrement la position des artistes des tracés. Avec cette flexibilité, les paramètres permettant de spécifier manuellement uniquement les médianes et leurs intervalles de confiance restent pour une rétrocompatibilité.
À peu près au même moment où les deux rôles de Axes.boxplotont été divisés en
cbook.boxplot_statscalcul et Axes.bxpen dessin, les deux
Axes.boxplotet Axes.bxpont été écrits pour accepter des paramètres qui basculent individuellement le dessin de tous les composants des boîtes à moustaches, et des paramètres qui configurent individuellement le style de ces artistes. Cependant, pour maintenir la rétrocompatibilité, le symparamètre (précédemment utilisé pour spécifier le symbole des dépliants) a été conservé. Ce paramètre lui-même nécessite une logique assez complexe pour réconcilier les symparamètres avec le nouveau flierpropsparamètre au style par défaut spécifié par matplotlibrc.
Ce MEP vise à simplifier considérablement la création de boîtes à moustaches pour les utilisateurs novices et avancés. Il est important de noter que les modifications proposées ici seront également disponibles pour les packages en aval comme seaborn, car seaborn permet intelligemment aux utilisateurs de transmettre des dictionnaires arbitraires de paramètres via l'API seaborn aux fonctions matplotlib sous-jacentes.
Ceci sera réalisé de la manière suivante :
cbook.boxplot_statssera modifié pour permettre aux fonctions de transformation pré- et post-calcul d'être transmises (par exemple,np.logetnp.exppour les données distribuées log-normalement)
Axes.boxplotsera modifié pour les accepter également et les transmettre naïvement àcbook.boxplots_stats(Alt : transmettre la fonction stat et un dict de ses paramètres optionnels).Les paramètres obsolètes de
Axes.boxplotseront obsolètes et supprimés ultérieurement.
Importance #
Étant donné que les limites des moustaches sont calculées arithmétiquement, il existe une hypothèse implicite de normalité dans les diagrammes en boîte et moustaches. Cela affecte principalement les points de données classés comme valeurs aberrantes.
Autoriser les transformations des données et des résultats utilisés pour dessiner des boîtes à moustaches permettra aux utilisateurs de refuser cette hypothèse si les données sont connues pour ne pas correspondre à une distribution normale.
Vous trouverez ci-dessous un exemple de la manière dont Axes.boxplotles valeurs aberrantes des données log-normales sont classées différemment en fonction de ces types de transformations.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cbook
np.random.seed(0)
fig, ax = plt.subplots(figsize=(4, 6))
ax.set_yscale('log')
data = np.random.lognormal(-1.75, 2.75, size=37)
stats = cbook.boxplot_stats(data, labels=['arithmetic'])
logstats = cbook.boxplot_stats(np.log(data), labels=['log-transformed'])
for lsdict in logstats:
for key, value in lsdict.items():
if key != 'label':
lsdict[key] = np.exp(value)
stats.extend(logstats)
ax.bxp(stats)
fig.show()
( Code source , png )
Mise en œuvre #
Passer des fonctions de transformation à cbook.boxplots_stats#
Ce MEP propose que deux paramètres (par exemple, transform_inet
transform_outsoient ajoutés à la fonction de livre de recettes qui calcule les statistiques pour la fonction de boîte à moustaches. Ce seront des arguments facultatifs de mot-clé uniquement et peuvent facilement être définis comme non-op lorsqu'ils sont omis par l'utilisateur. La fonction sera appliquée aux données au fur et à mesure que la fonction parcourt chaque sous-ensemble des données qui lui sont transmises. Une fois la liste des dictionnaires de statistiques calculée, la
fonction est appliquée à chaque valeur des dictionnaires.lambda x: xtransform_inboxplot_statstransform_out
Ces transformations peuvent ensuite être ajoutées à la signature d'appel
Axes.boxplotavec peu d'impact sur la complexité de cette méthode. C'est parce qu'ils peuvent être directement passés à cbook.boxplot_stats. Alternativement, Axes.boxplotpourrait être modifié pour accepter une fonction statistique facultative kwarg et un dictionnaire de paramètres à lui transmettre directement.
À ce stade de l'implémentation, les utilisateurs et les bibliothèques externes comme seaborn auraient un contrôle total via la Axes.boxplotméthode. Plus important encore, à tout le moins, seaborn ne nécessiterait aucune modification de son API pour permettre aux utilisateurs de profiter de ces nouvelles options.
Simplifications de l' Axes.boxplotAPI et d'autres fonctions #
La simplification de la méthode du boxplot consiste principalement à déprécier puis à supprimer les paramètres redondants. Facultativement, une prochaine étape consisterait à rectifier les incohérences terminologiques mineures entre Axes.boxplot
et Axes.bxp.
Les paramètres à déconseiller et à supprimer incluent :
usermedians- traité par 10 SLOC, 3ifblocs, uneforboucle
conf_intervals- géré par 15 SLOC, 6ifblocs, uneforboucle
sym- traité par 12 SLOC, 4ifblocs
La suppression de l' symoption permet de déplacer tout le code de gestion des paramètres de style restants vers Axes.bxp. Cela ne supprime aucune complexité, mais renforce le principe de responsabilité unique entre Axes.bxp, cbook.boxplot_statset Axes.boxplot.
De plus, le notchparamètre peut être renommé shownotches
pour être cohérent avec Axes.bxp. Ce type de nettoyage pourrait être poussé plus loin et les whis, bootstrap, autorangepourraient être intégrés aux kwargs passés au nouveau statfxnparamètre.
Rétrocompatibilité #
La mise en œuvre de ce MEP entraînerait éventuellement l'obsolescence rétrocompatible, puis la suppression des paramètres de mot-clé
usermedians, conf_intervalset sym. Des recherches rapides sur GitHub ont indiqué que usermedians, conf_intervalssont utilisés par quelques utilisateurs, qui semblent tous avoir une très bonne connaissance de matplotlib. Un cycle de dépréciation robuste devrait laisser suffisamment de temps à ces utilisateurs pour migrer vers une nouvelle API.
symCependant, la dépréciation de peut avoir une portée beaucoup plus large dans la base d'utilisateurs de matplotlib .
Horaire #
Une chronologie accélérée pourrait ressembler à ceci :
v2.0.1 ajouter des transformations à
cbook.boxplots_stats, exposer dansAxes.boxplotv2.1.0 Dépréciations initiales et utilisation de tableaux NumPy 2D en entrée
Utilisation de tableaux NumPy 2D en entrée. La sémantique autour des tableaux 2D est généralement déroutante.
usermedians,conf_intervals,symparamètres
v2.2.0
supprimer les paramètres
usermedians,conf_intervals,symdéprécier
notchen faveur deshownotchespour être cohérent avec d'autres paramètres etAxes.bxp
- v2.3.0
supprimer le
notchparamètredéplacer tout le style et la logique de basculement de l'artiste vers
Axes.bxptelAxes.boxplotn'est guère plus qu'un courtier entreAxes.bxpetcbook.boxplots_stats
Impacts anticipés sur les utilisateurs #
Comme décrit ci-dessus, il est obsolète usermedianset conf_intervals
aura probablement un impact sur quelques utilisateurs. Ceux qui seront impactés sont presque certainement des utilisateurs avancés qui sauront s'adapter au changement.
L'abandon de l' symoption peut importer plus d'utilisateurs et des efforts doivent être faits pour recueillir les commentaires de la communauté à ce sujet.
Impacts anticipés sur les bibliothèques en aval #
Le code source (maître GitHub au 17/10/2016) a été inspecté pour seaborn et python-ggplot pour voir si ces changements auraient un impact sur leur utilisation. Aucun des paramètres désignés pour suppression dans ce MEP n'est utilisé par seaborn. Les API Seaborn qui utilisent la fonction boxplot de matplotlib permettent à l'utilisateur de passer arbitrairement **kwargsà l'API de matplotlib. Ainsi, les utilisateurs marins disposant d'installations matplotlib modernes pourront profiter pleinement de toutes les nouvelles fonctionnalités ajoutées à la suite de ce MEP.
Python-ggplot a implémenté sa propre fonction pour dessiner des boxplots. Par conséquent, aucun impact ne peut lui arriver à la suite de la mise en œuvre de ce PEM.
Alternatives #
Variations sur le thème #
Ce MEP peut être divisé en quelques composants faiblement couplés :
Permettre la fonction de transformation pré- et post-calcul dans
cbook.boxplot_statsExposer cette transformation dans l'
Axes.boxplotAPISuppression des options statistiques redondantes dans
Axes.boxplotDéplacement de tous les paramètres de style de traitement de
Axes.boxplotàAxes.bxp.
Avec cette approche, #2 dépend et #1, et #4 dépend de #3.
Il y a deux approches possibles pour #2. La première et la plus directe serait de refléter les nouveaux paramètres de
in transform_inet de les transmettre directement.transform_outcbook.boxplot_statsAxes.boxplot
La deuxième approche consisterait à ajouter statfxnet statfxn_args
des paramètres à Axes.boxplot. Dans cette implémentation, la valeur par défaut de statfxnserait cbook.boxplot_stats, mais les utilisateurs pourraient transmettre leur propre fonction. Alors transform_inet transform_outseraient alors passés en tant qu'éléments du statfxn_argsparamètre.
def boxplot_stats(data, ..., transform_in=None, transform_out=None):
if transform_in is None:
transform_in = lambda x: x
if transform_out is None:
transform_out = lambda x: x
output = []
for _d in data:
d = transform_in(_d)
stat_dict = do_stats(d)
for key, value in stat_dict.item():
if key != 'label':
stat_dict[key] = transform_out(value)
output.append(d)
return output
class Axes(...):
def boxplot_option1(data, ..., transform_in=None, transform_out=None):
stats = cbook.boxplot_stats(data, ...,
transform_in=transform_in,
transform_out=transform_out)
return self.bxp(stats, ...)
def boxplot_option2(data, ..., statfxn=None, **statopts):
if statfxn is None:
statfxn = boxplot_stats
stats = statfxn(data, **statopts)
return self.bxp(stats, ...)
Les deux cas permettraient aux utilisateurs d'effectuer les opérations suivantes :
fig, ax1 = plt.subplots()
artists1 = ax1.boxplot_optionX(data, transform_in=np.log,
transform_out=np.exp)
Mais la deuxième option permet à un utilisateur d'écrire une fonction statistique entièrement personnalisée (par exemple, my_box_stats) avec des intervalles de confiance BCA sophistiqués et des moustaches définies différemment en fonction de certains attributs des données.
Ceci est disponible sous l'API actuelle :
fig, ax1 = plt.subplots()
my_stats = my_box_stats(data, bootstrap_method='BCA',
whisker_method='dynamic')
ax1.bxp(my_stats)
Et serait plus concis avec l'option deux
fig, ax = plt.subplots()
statopts = dict(transform_in=np.log, transform_out=np.exp)
ax.boxplot(data, ..., **statopts)
Les utilisateurs peuvent également transmettre leur propre fonction pour calculer les statistiques :
fig, ax1 = plt.subplots()
ax1.boxplot(data, statfxn=my_box_stats, bootstrap_method='BCA',
whisker_method='dynamic')
D'après les exemples ci-dessus, l'option 2 semble n'avoir qu'un avantage marginal, mais dans le contexte des bibliothèques en aval comme seaborn, son avantage est plus apparent car ce qui suit serait possible sans aucun correctif pour seaborn :
import seaborn
tips = seaborn.load_data('tips')
g = seaborn.factorplot(x="day", y="total_bill", hue="sex", data=tips,
kind='box', palette="PRGn", shownotches=True,
statfxn=my_box_stats, bootstrap_method='BCA',
whisker_method='dynamic')
Ce type de flexibilité était l'intention derrière la division de l'API boxplot globale dans les trois fonctions actuelles. En pratique cependant, les bibliothèques en aval comme seaborn prennent en charge les versions de matplotlib datant bien avant la scission. Ainsi, ajouter un peu plus de flexibilité à
Axes.boxplotpourrait exposer toutes les fonctionnalités aux utilisateurs des bibliothèques en aval avec une installation moderne de matplotlib sans intervention des responsables de la bibliothèque en aval.
Faire moins #
Une autre alternative évidente consisterait à omettre la fonctionnalité de transformation pré- et post-calcul ajoutée dans cbook.boxplot_statset
Axes.boxplot, et à supprimer simplement les paramètres statistiques et de style redondants, comme décrit ci-dessus.
Ne rien faire #
Comme pour beaucoup de choses dans la vie, ne rien faire est une option ici. Cela signifie que nous préconisons simplement que les utilisateurs et les bibliothèques en aval profitent de la séparation entre cbook.boxplot_statset Axes.bxpet les laissent décider comment fournir une interface à cela.