making matplotlib graphs look like R by default?

后端 未结 8 1733
自闭症患者
自闭症患者 2021-01-29 23:02

Is there a way to make matplotlib behave identically to R, or almost like R, in terms of plotting defaults? For example R treats its axes pretty differently from

8条回答
  •  野的像风
    2021-01-29 23:38

    # # # # # #

    EDIT 10/14/2013: For information, ggplot has now been implemented for python (built on matplotlib).

    See this blog or go directly to the github page of the project for more information and examples.

    # # # # # #

    To my knowledge, there is no built-in solution in matplotlib that will directly give to your figures a similar look than the ones made with R.

    Some packages, like mpltools, adds support for stylesheets using Matplotlib’s rc-parameters, and can help you to obtain a ggplot look (see the ggplot style for an example).

    However, since everything can be tweaked in matplotlib, it might be easier for you to directly develop your own functions to achieve exactly what you want. As an example, below is a snippet that will allow you to easily customize the axes of any matplotlib plot.

    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: for non touching spines, see the function below which induces a 10 pts displacement of the spines (taken from this example on the matplotlib website).

    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
    

    For example, the code and the two plots below show you the default output from matplotib (on the left), and the output when the functions are called (on the right):

    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

    Of course, it will take time for you to figure out which parameters have to be tweaked in matplotlib to make your plots look exactly like the R ones, but I am not sure there are other options right now.

提交回复
热议问题