Existe-t-il un moyen de faire en sorte que matplotlib
se comporte de manière identique à R, ou presque comme R, en termes de traçage des valeurs par défaut? Par exemple, R traite ses axes assez différemment de matplotlib
. L'histogramme suivant
a des "axes flottants" avec des graduations vers l'extérieur, de sorte qu'il n'y a pas de graduations internes (contrairement à matplotlib
) et que les axes ne traversent pas "près" de l'origine. De plus, l'histogramme peut "déborder" sur des valeurs qui ne sont pas marquées par la coche - par ex. l'axe des x se termine à 3 mais les histogrammes s'étendent légèrement au-delà. Comment cela peut-il être réalisé automatiquement pour tous les histogrammes dans matplotlib
?
Question connexe: les nuages de points et les graphiques linéaires ont des paramètres d'axe par défaut différents dans R, par exemple:
Il n'y a plus de tiques intérieures et les tiques sont tournées vers l'extérieur. En outre, les tiques commencent légèrement après le point d'origine (où les axes y et x se croisent en bas à gauche des axes) et les tiques se terminent légèrement avant la fin des axes. De cette façon, les étiquettes de la graduation de l'axe x la plus basse et de la graduation de l'axe y la plus basse ne peuvent pas vraiment se croiser, car il y a un espace entre elles et cela donne aux tracés un aspect épuré très élégant. Notez qu'il y a également beaucoup plus d'espace entre les graduations des axes et les graduations elles-mêmes.
En outre, par défaut, il n'y a pas de graduations sur les axes x ou y non étiquetés, ce qui signifie que l'axe y sur la gauche qui est parallèle à l'axe y étiqueté sur la droite n'a pas de graduations, et même pour l'axe x, enlever à nouveau l'encombrement des parcelles.
Existe-t-il un moyen de faire ressembler matplotlib à ceci? Et en général pour regarder par défaut autant que les tracés R par défaut? J'aime beaucoup matplotlib
mais je pense que le comportement de tracé par défaut R/prêt à l'emploi a vraiment bien fait les choses et ses paramètres par défaut conduisent rarement à des étiquettes de ticks qui se chevauchent, à l'encombrement ou à des données écrasées, donc je le ferais comme les valeurs par défaut sont autant que possible comme ça.
Avec seaborn
, l'exemple ci-dessous devient:
import numpy as np
import matplotlib.pyplot as plt
import seaborn
seaborn.set(style='ticks')
# Data to be represented
X = np.random.randn(256)
# Actual plotting
fig = plt.figure(figsize=(8,6), dpi=72, facecolor="white")
axes = plt.subplot(111)
heights, positions, patches = axes.hist(X, color='white')
seaborn.despine(ax=axes, offset=10, trim=True)
fig.tight_layout()
plt.show()
Assez facile.
Ce billet de blog est le meilleur que j'ai vu jusqu'à présent. http://messymind.net/making-matplotlib-look-like-ggplot/
Il ne se concentre pas sur vos tracés R standard comme vous le voyez dans la plupart des exemples de type "mise en route". Au lieu de cela, il essaie d'imiter le style de ggplot2, qui semble être presque universellement annoncé comme élégant et bien conçu.
Pour obtenir les épines d'axe comme vous voyez le graphique en barres, essayez de suivre l'un des premiers exemples ici: http://www.loria.fr/~rougier/coding/gallery/
Enfin, pour que les graduations des axes pointent vers l'extérieur, vous pouvez modifier vos fichiers matplotlibrc
pour dire xtick.direction : out
et ytick.direction : out
.
En combinant ces concepts ensemble, nous obtenons quelque chose comme ceci:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# Data to be represented
X = np.random.randn(256)
# Actual plotting
fig = plt.figure(figsize=(8,6), dpi=72, facecolor="white")
axes = plt.subplot(111)
heights, positions, patches = axes.hist(X, color='white')
axes.spines['right'].set_color('none')
axes.spines['top'].set_color('none')
axes.xaxis.set_ticks_position('bottom')
# was: axes.spines['bottom'].set_position(('data',1.1*X.min()))
axes.spines['bottom'].set_position(('axes', -0.05))
axes.yaxis.set_ticks_position('left')
axes.spines['left'].set_position(('axes', -0.05))
axes.set_xlim([np.floor(positions.min()), np.ceil(positions.max())])
axes.set_ylim([0,70])
axes.xaxis.grid(False)
axes.yaxis.grid(False)
fig.tight_layout()
plt.show()
La position des épines peut être spécifiée de plusieurs façons. Si vous exécutez le code ci-dessus dans IPython, vous pouvez alors faire axes.spines['bottom'].set_position?
pour voir toutes vos options.
Donc voilà. Ce n'est pas vraiment trivial, mais vous pouvez vous en approcher.
matplotlib> = 1.4 prend en charge styles (et le style ggplot est intégré):
In [1]: import matplotlib as mpl
In [2]: import matplotlib.pyplot as plt
In [3]: import numpy as np
In [4]: mpl.style.available
Out[4]: [u'dark_background', u'grayscale', u'ggplot']
In [5]: mpl.style.use('ggplot')
In [6]: plt.hist(np.random.randn(100000))
Out[6]:
...
# # # # # #
EDIT 14/10/2013: Pour plus d'informations, ggplot a maintenant été implémenté pour python (construit sur matplotlib).
Voir ceci blog ou aller directement à la page github du projet pour plus d'informations et d'exemples.
# # # # # #
À ma connaissance, il n'y a pas de solution intégrée dans matplotlib qui donnera directement à vos figurines un look similaire à celles faites avec R.
Certains packages, comme mpltools , ajoutent la prise en charge des feuilles de style en utilisant les paramètres rc de Matplotlib, et peuvent vous aider à obtenir un aspect ggplot (voir style ggplot pour un exemple).
Cependant, comme tout peut être modifié dans matplotlib, il peut être plus facile pour vous de développer directement vos propres fonctions pour atteindre exactement ce que vous voulez. À titre d'exemple, voici un extrait qui vous permettra de personnaliser facilement les axes de n'importe quel tracé matplotlib.
def customaxis(ax, c_left='k', c_bottom='k', c_right='none', c_top='none',
lw=3, size=20, pad=8):
for c_spine, spine in Zip([c_left, c_bottom, c_right, c_top],
['left', 'bottom', 'right', 'top']):
if c_spine != 'none':
ax.spines[spine].set_color(c_spine)
ax.spines[spine].set_linewidth(lw)
else:
ax.spines[spine].set_color('none')
if (c_bottom == 'none') & (c_top == 'none'): # no bottom and no top
ax.xaxis.set_ticks_position('none')
Elif (c_bottom != 'none') & (c_top != 'none'): # bottom and top
ax.tick_params(axis='x', direction='out', width=lw, length=7,
color=c_bottom, labelsize=size, pad=pad)
Elif (c_bottom != 'none') & (c_top == 'none'): # bottom but not top
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(axis='x', direction='out', width=lw, length=7,
color=c_bottom, labelsize=size, pad=pad)
Elif (c_bottom == 'none') & (c_top != 'none'): # no bottom but top
ax.xaxis.set_ticks_position('top')
ax.tick_params(axis='x', direction='out', width=lw, length=7,
color=c_top, labelsize=size, pad=pad)
if (c_left == 'none') & (c_right == 'none'): # no left and no right
ax.yaxis.set_ticks_position('none')
Elif (c_left != 'none') & (c_right != 'none'): # left and right
ax.tick_params(axis='y', direction='out', width=lw, length=7,
color=c_left, labelsize=size, pad=pad)
Elif (c_left != 'none') & (c_right == 'none'): # left but not right
ax.yaxis.set_ticks_position('left')
ax.tick_params(axis='y', direction='out', width=lw, length=7,
color=c_left, labelsize=size, pad=pad)
Elif (c_left == 'none') & (c_right != 'none'): # no left but right
ax.yaxis.set_ticks_position('right')
ax.tick_params(axis='y', direction='out', width=lw, length=7,
color=c_right, labelsize=size, pad=pad)
EDIT: pour les épines non touchantes, voir la fonction ci-dessous qui induit un déplacement de 10 pts des épines (tiré de cet exemple sur le site de matplotlib).
def adjust_spines(ax,spines):
for loc, spine in ax.spines.items():
if loc in spines:
spine.set_position(('outward',10)) # outward by 10 points
spine.set_smart_bounds(True)
else:
spine.set_color('none') # don't draw spine
Par exemple, le code et les deux graphiques ci-dessous vous montrent la sortie par défaut de matplotib (à gauche), et la sortie lorsque les fonctions sont appelées (à droite):
import numpy as np
import matplotlib.pyplot as plt
fig,(ax1,ax2) = plt.subplots(figsize=(8,5), ncols=2)
ax1.plot(np.random.Rand(20), np.random.Rand(20), 'ok')
ax2.plot(np.random.Rand(20), np.random.Rand(20), 'ok')
customaxis(ax2) # remove top and right spines, ticks out
adjust_spines(ax2, ['left', 'bottom']) # non touching spines
plt.show()
Bien sûr, il vous faudra du temps pour déterminer quels paramètres doivent être modifiés dans matplotlib pour que vos tracés ressemblent exactement à ceux de R, mais je ne suis pas sûr qu'il existe d'autres options pour le moment.
Voici un article de blog qui pourrait vous intéresser:
Tracé pour Pandas GSoC2012
http://pandasplotting.blogspot.com/
Décidé d'essayer d'implémenter une interface de traçage de type ggplot2 ... Vous ne savez pas encore combien de fonctionnalités ggplot2 implémenter ...
L'auteur a créé pandas et construit ce qui ressemble à beaucoup de grammaire de style ggplot2 pour les pandas.
plot = rplot.RPlot(tips_data, x='total_bill', y='tip')
plot.add(rplot.TrellisGrid(['sex', 'smoker']))
plot.add(rplot.GeomHistogram())
plot.render(plt.gcf())
La fourche pandas est ici: https://github.com/orbitfold/pandas
On dirait que la viande du code pour faire les graphiques influencés par R est dans un fichier appelé rplot.py
qui se trouve dans une succursale du référentiel.
class GeomScatter(Layer):
"""
An efficient scatter plot, use this instead of GeomPoint for speed.
"""
class GeomHistogram(Layer):
"""
An efficient histogram, use this instead of GeomBar for speed.
"""
Lien vers l'agence:
https://github.com/orbitfold/pandas/blob/rplot/pandas/tools/rplot.py
Je pensais que c'était vraiment cool, mais je ne peux pas savoir si ce projet est maintenu ou non. Le dernier commit remonte à un certain temps.
Définition des épines dans matplotlibrc explique pourquoi il n'est pas possible de simplement modifier les valeurs par défaut de Matplotlib pour produire des histogrammes de style R. Pour les diagrammes de dispersion, tampon d'axe de données de style R dans matplotlib et dans matplotlib, comment dessinez-vous des graduations d'axe de style R qui pointent vers l'extérieur à partir des axes? affiche des valeurs par défaut qui peut être modifié pour donner un look plus R-ish. En s'appuyant sur certaines des autres réponses, la fonction suivante fait un travail décent pour imiter le style d'histogramme de R, en supposant que vous avez appelé hist()
sur votre Axes
instance avec facecolor='none'
.
def Rify(axes):
'''
Produce R-style Axes properties
'''
xticks = axes.get_xticks()
yticks = axes.get_yticks()
#remove right and upper spines
axes.spines['right'].set_color('none')
axes.spines['top'].set_color('none')
#make the background transparent
axes.set_axis_bgcolor('none')
#allow space between bottom and left spines and Axes
axes.spines['bottom'].set_position(('axes', -0.05))
axes.spines['left'].set_position(('axes', -0.05))
#allow plot to extend beyond spines
axes.spines['bottom'].set_bounds(xticks[0], xticks[-2])
axes.spines['left'].set_bounds(yticks[0], yticks[-2])
#set tick parameters to be more R-like
axes.tick_params(direction='out', top=False, right=False, length=10, pad=12, width=1, labelsize='medium')
#set x and y ticks to include all but the last tick
axes.set_xticks(xticks[:-1])
axes.set_yticks(yticks[:-1])
return axes
La bibliothèque de visualisation Seaborn peut le faire. Par exemple, pour reproduire le style de l'histogramme R, utilisez:
sns.despine(offset=10, trim=True)
comme dans https://seaborn.pydata.org/tutorial/aesthetics.html#removing-axes-spines
Pour reproduire le style du nuage de points R, utilisez:
sns.set_style("ticks")
comme indiqué dans https://seaborn.pydata.org/tutorial/aesthetics.html#seaborn-figure-styles
import matplotlib.pyplot as plt plt.style.use('ggplot')
faire quelque chose ici et en profiter