web-dev-qa-db-fra.com

faire des graphes matplotlib ressembler à R par défaut?

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 enter image description here

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: enter image description here

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.

58
user248237

Modifier 1 an plus tard:

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.

Message d'origine:

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.

R-style bar plot in python

Donc voilà. Ce n'est pas vraiment trivial, mais vous pouvez vous en approcher.

44
Paul H

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]: 
...

enter image description here

33
bmu

# # # # # #

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

image

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.

28
gcalmettes

Je voudrais vérifier Bokeh qui vise à "fournir un équivalent Python équivalent de ggplot dans R". Exemple ici

EDIT: Consultez également Seaborn , qui tente de reproduire le style visuel et la syntaxe de ggplot2.

10
Brian Keegan

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.

Density Plots

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.

4
hernamesbarbara

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
2
JaminSore

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

enter image description here

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

enter image description here

1
altroware

import matplotlib.pyplot as plt plt.style.use('ggplot')

faire quelque chose ici et en profiter

0
afternone