Python 如何使 matplotlib 图形看起来像这样专业?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24547047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:46:44  来源:igfitidea点击:

How to make matplotlib graphs look professionally done like this?

pythonmatplotlibplotdata-visualization

提问by Shital Shah

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 improves the styles.

默认的 matplotlib 图形看起来真的没有吸引力,甚至不专业。我尝试了几个包,包括 seaborn 和 prettyplotlib,但这两个包都几乎没有改进样式。

So far I've gotten to following using seaborn package:

到目前为止,我已经开始使用 seaborn 包:

enter image description here

enter image description here

Below is the appearance I'm looking for which is far cry from above:

下面是我正在寻找的外观与上面相去甚远:

enter image description here

enter image description here

Notice the following niceness in the 2nd example:

请注意第二个示例中的以下优点:

  1. Area under the graph is filled with much more eye pleasing color.
  2. The graph line is thinker and nicely stands out.
  3. Axis lines are thinker and again nicely stands out.
  4. Area under the curve is transparent.
  5. X-Axis tick marks are more denser.
  1. 图表下方的区域充满了更令人赏心悦目的颜色。
  2. 图形线是思想家,很好地脱颖而出。
  3. 轴线是思想家,再次很好地脱颖而出。
  4. 曲线下的区域是透明的。
  5. X 轴刻度线更密集。

My questions are: Do you recognize above as some kind of popular theme or style that I can quickly use in matplotlib? Or if I can use from some package? Failing that, is there anyway to set this style as my global preference? Failing that, is it even possible to do this in matlibplot?

我的问题是:您是否认为以上是某种我可以在 matplotlib 中快速使用的流行主题或样式?或者如果我可以从某个包中使用?否则,是否可以将这种样式设置为我的全局偏好?如果做不到这一点,甚至可以在 matlibplot 中做到这一点吗?

Thanks!

谢谢!

采纳答案by DrV

This is really a matter of taste, and also a matter of target audience. matplotlibtries 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.

这真的是一个品味问题,也是一个目标受众的问题。matplotlib试图为科学目的制作清晰的插图。这 - 必然 - 妥协,插图不是你会在杂志上打印或在广告中展示的东西。

There are some good news and some bad news about matplotlibin this sense.

matplotlib从这个意义上说,有一些好消息和一些坏消息。

Bad news:

坏消息:

  • There is no single magical command or package which would create beautiful plots with matplotlib.
  • 没有一个神奇的命令或包可以用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.
  • 有一些简单的方法可以更改默认设置,请参阅:http: //matplotlib.org/users/customizing.html
  • 对象模型使用户能够更改几乎所有内容并引入复杂的新功能。
  • 源代码是可用的,用户甚至可以很容易地更改它。

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

(只是一个评论:原始图像中的X轴限制没有考虑数据的周期性。)

This will give us something like this:

这会给我们这样的东西:

enter image description here

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
  • 使填充透明且颜色不那么令人反感
  • 使线条更粗
  • 改变线条颜色
  • 向 X 轴添加更多刻度
  • 更改标题的字体


# 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

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.

这与问题中的不完全一样,但一切都可以朝着这个方向调整。此处设置的许多内容都可以设置为matplotlib. 也许这给出了如何改变情节中的东西的想法。

回答by Greg

matplotlibis 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.

matplotlib几乎无限灵活,因此您几乎可以用它做任何事情,如果它不存在,您可以自己编写!显然默认值是平淡的,这是因为每个人都有自己对什么是“好”的想法,所以强加​​预定义的风格是没有意义的。

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

这是一个非常简单的示例,可以解决您的 4 点。

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

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.rcParamsfrom an interactive terminal.

如果您想设置默认值以使所有图看起来都相同,那么您应该生成一个自定义matplotlibrc file. 有用的指南在这里。要查看所有可用选项的列表,只需print plt.rcParams从交互式终端调用即可。

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.

一些其他功能(例如填充)需要在每个图的基础上完成。您可以通过创建一个函数在给定的一些输入(例如轴实例和数据)之间添加填充,从而在您的工作中标准化这一点。

回答by mwaskom

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

为了更接近您喜欢的样式,您可以使用whitegridseaborn 中的样式。正如其他答案所指出的,您可以使用alphato 参数控制填充的透明度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

enter image description here

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

更多关于 seaborn 样式的信息可以在文档中找到。

回答by afternone

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