Why is matplotlib plot produced from ipython notebook slightly different from terminal version?

后端 未结 3 1735
慢半拍i
慢半拍i 2020-12-15 11:56

I have a strange issue. Using IPython Notebook, I created a quite extensive script using pandas and matplotlib to create a number of charts. When my tinkering was finished,

相关标签:
3条回答
  • 2020-12-15 11:59

    To complete Joe answer, the inlinebackend (IPython/kernel/zmq/pylab/backend_inline.py) have some default matplotlib parameters :

    # The typical default figure size is too large for inline use,
    # so we shrink the figure size to 6x4, and tweak fonts to
    # make that fit.
    rc = Dict({'figure.figsize': (6.0,4.0),
        # play nicely with white background in the Qt and notebook frontend
        'figure.facecolor': 'white',
        'figure.edgecolor': 'white',
        # 12pt labels get cutoff on 6x4 logplots, so use 10pt.
        'font.size': 10,
        # 72 dpi matches SVG/qtconsole
        # this only affects PNG export, as SVG has no dpi setting
        'savefig.dpi': 72,
        # 10pt still needs a little more room on the xlabel:
        'figure.subplot.bottom' : .125
        }, config=True,
        help="""Subset of matplotlib rcParams that should be different for the
        inline backend."""
    )
    

    As this is not obvious to everyone, you can set it in config through c.InlineBackend.rc.

    [Edit] precise info about configurability.

    IPython have the particularity that most of the classes have properties which default values can be configured. Those are often refered as Configurable (uppercase C), those property can easily be recognize in the code as they are declared like so before __init__:

    property = A_Type( <default_value>, config=True , help="a string")
    

    You can overwrite those properties in IPython configuration files (which one depends on what you want to do) by doing

    c.ClassName.propertie_name = value
    

    Here as it is a dict you could do

    #put your favorite matplotlib config here.
    c.InlineBackend.rc = {'figure.facecolor': 'black'}  
    

    I guess an empty dict would allow inline backend to use matplotlib defaults.

    0 讨论(0)
  • 2020-12-15 12:02

    Extending Matt's answer (lots of credit to him, but I think the answers can be less complex), this is how I eventually solved it.

    (a) I looked up ipython's default matplotlib settings in C:\Python27\Lib\site-packages\IPython\zmq\pylab\backend_inline.py (see Matt's answer).

    (b) and overwrote them with the values as set in the terminal version (I used print mpl.rcParams['figure.figsize'] etc. to find out) by inserting the following code in my script:

    import matplotlib as mpl
    
    #To make sure we have always the same matplotlib settings
    #(the ones in comments are the ipython notebook settings)
    
    mpl.rcParams['figure.figsize']=(8.0,6.0)    #(6.0,4.0)
    mpl.rcParams['font.size']=12                #10 
    mpl.rcParams['savefig.dpi']=100             #72 
    mpl.rcParams['figure.subplot.bottom']=.1    #.125
    
    0 讨论(0)
  • 2020-12-15 12:20

    The font size issues are due to differences in the dpi. I'd guess the slightly different size of the figure (in pixels) changes the "best" location for the legend, as well.

    The default dpi a figure is displayed at is 80, while savefig defaults to 100. This means that by default, matplotlib figures will look slightly different when saved compared to what's displayed on the screen.

    I don't know for sure, but I'm guessing that ipython notebooks set the dpi to something other than 100 (most likely 80) and use that when saving figures.

    Try doing savefig('filename.pdf', dpi=80) in your standalone script.

    0 讨论(0)
提交回复
热议问题