How to make matplotlib graphs look professionally done like this?

前端 未结 4 1508
失恋的感觉
失恋的感觉 2021-01-30 23:56

Default matplotlib graphs look really unattractive and even unprofessional. I tried out couple of packages include seaborn as well as prettyplotlib but both of these just barely

相关标签:
4条回答
  • 2021-01-31 00:36

    This is really a matter of taste, and also a matter of target audience. matplotlib tries to produce clear illustrations for scientific purposes. This is - necessarily - a compromise, and the illustrations are not something you would print in a magazine or show in an advertisement.

    There are some good news and some bad news about matplotlib in this sense.

    Bad news:

    • There is no single magical command or package which would create beautiful plots with matplotlib.

    Good news:

    • There are simple ways to change the default settings, see: http://matplotlib.org/users/customizing.html
    • The object model enables the user to change almost everything and introduce complex new features.
    • The source code is available, and even it can be changed quite easily by the user.

    In my opinion the most difficult thing is to decide what you want. Then doing what you want is easier, even though there is a steepish learning curve in the beginning.

    Just as an example:

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    # create some fictive access data by hour
    xdata = np.arange(25)
    ydata = np.random.randint(10, 20, 25)
    ydata[24] = ydata[0]
    
    # let us make a simple graph
    fig = plt.figure(figsize=[7,5])
    ax = plt.subplot(111)
    l = ax.fill_between(xdata, ydata)
    
    # set the basic properties
    ax.set_xlabel('Time of posting (US EST)')
    ax.set_ylabel('Percentage of Frontpaged Submissions')
    ax.set_title('Likelihood of Reaching the Frontpage')
    
    # set the limits
    ax.set_xlim(0, 24)
    ax.set_ylim(6, 24)
    
    # set the grid on
    ax.grid('on')
    

    (Just a comment: The X-axis limits in the original image do not take the cyclicity of the data into account.)

    This will give us something like this:

    enter image description here

    It is easy to understand that we need to do a lot of changes in order to be able to show this to a less-engineering-minded audience. At least:

    • make the fill transparent and less offensive in colour
    • make the line thicker
    • change the line colour
    • add more ticks to the X axis
    • change the fonts of the titles

    # change the fill into a blueish color with opacity .3
    l.set_facecolors([[.5,.5,.8,.3]])
    
    # change the edge color (bluish and transparentish) and thickness
    l.set_edgecolors([[0, 0, .5, .3]])
    l.set_linewidths([3])
    
    # add more ticks
    ax.set_xticks(np.arange(25))
    # remove tick marks
    ax.xaxis.set_tick_params(size=0)
    ax.yaxis.set_tick_params(size=0)
    
    # change the color of the top and right spines to opaque gray
    ax.spines['right'].set_color((.8,.8,.8))
    ax.spines['top'].set_color((.8,.8,.8))
    
    # tweak the axis labels
    xlab = ax.xaxis.get_label()
    ylab = ax.yaxis.get_label()
    
    xlab.set_style('italic')
    xlab.set_size(10)
    ylab.set_style('italic')
    ylab.set_size(10)
    
    # tweak the title
    ttl = ax.title
    ttl.set_weight('bold')
    

    Now we have:

    enter image description here

    This is not exactly as in the question, but everything can be tuned towards that direction. Many of the things set here can be set as defaults for matplotlib. Maybe this gives an idea of how to change things in the plots.

    0 讨论(0)
  • 2021-01-31 00:39

    You can customize plots style as follow:

    import numpy as np
    import matplotlib.pyplot as plt
    plt.use_style('ggplot') # customize your plots style
    x = np.linspace(0,2*np.pi,100)
    y = np.sin(x)
    plt.fill_between(x,y)
    plt.show()
    
    0 讨论(0)
  • 2021-01-31 00:40

    To get closer to the style you prefer, you could use the whitegrid style in seaborn. As the other answers have noted, you control the transparency of the fill with the alpha parameter to fill_between.

    import numpy as np
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.set_style("whitegrid")
    
    blue, = sns.color_palette("muted", 1)
    
    x = np.arange(23)
    y = np.random.randint(8, 20, 23)
    
    fig, ax = plt.subplots()
    ax.plot(x, y, color=blue, lw=3)
    ax.fill_between(x, 0, y, alpha=.3)
    ax.set(xlim=(0, len(x) - 1), ylim=(0, None), xticks=x)
    

    enter image description here

    More information on seaborn styles can be found in the docs.

    0 讨论(0)
  • 2021-01-31 00:48

    matplotlib is almost infinitely flexible so you can do almost anything with it and if it doesn't exist you can write it yourself! Obviously the defaults are bland, this is because everyone has there own idea of what is "nice" so it is pointless to impose a predefined style.

    Here is a really simple example that addresses 4 of your points.

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.ticker import MultipleLocator, FormatStrFormatter
    
    x = np.linspace(-10, 10, 1000)
    y = 1+np.sinc(x)
    
    ax = plt.subplot(111)
    ax.plot(x, y, lw=2)
    ax.fill_between(x, 0, y, alpha=0.2)
    ax.grid()
    
    majorLocator   = MultipleLocator(1)
    ax.xaxis.set_major_locator(majorLocator)
    
    plt.show()
    

    enter image description here

    If your want to set defaults so all your plots look the same then you should generate a custom matplotlibrc file. A useful guide is here. To view a list of all the available options just call print plt.rcParams from an interactive terminal.

    Some of the other features such as filling will need to be done on a per plot basis. You can standardise this across your work by creating a function which adds the fill between given some input such as the axis instance and data.

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