pandas 使用 Python 库绘制共享相同 y 轴的两个水平条形图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27694221/
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
Using Python libraries to plot two horizontal bar charts sharing same y axis
提问by Phuong Dao
I would like to plot two horizontal bar charts sharing same y axis. For example, the following question shows how to achieve this in R:
我想绘制两个共享相同 y 轴的水平条形图。例如,以下问题显示了如何在 R 中实现这一点:
Two horizontal bar charts with shared axis in ggplot2 (similar to population pyramid)
ggplot2 中带有共享轴的两个水平条形图(类似于人口金字塔)
How can I create a similar plot with Python?
如何使用 Python 创建类似的图?
The plot from the question above looks like this:
上述问题的情节如下所示:


Here is the list of states used in the graph above (the y axis):
以下是上图中使用的状态列表(y 轴):
["AK", "TX", "CA", "MT", "NM", "AZ", "NV", "CO", "OR", "WY",
"MI", "MN", "UT", "ID", "KS", "NE", "SD", "WA", "ND", "OK"]
Here is the list of the numbers of sales staff for each state:
以下是每个州的销售人员人数列表:
[20,30,40,10,15,35,18,25,22,7,12,22,3,4,5,8,14,28,24,32]
The sales figures can be random.
销售数字可以是随机的。
回答by Joe Kington
Generally speaking, if the two variables you're displaying are in different units or have different ranges, you'll want to use two subplots with shared y-axes for this. This is similar to what the answer by @regdoug does, but it's best to explicitly share the y-axis to ensure that your data stays aligned (e.g. try zooming/panning with this example).
一般来说,如果您显示的两个变量采用不同的单位或具有不同的范围,您将需要为此使用具有共享 y 轴的两个子图。这与@regdoug 的回答类似,但最好明确共享 y 轴以确保您的数据保持对齐(例如,尝试使用此示例进行缩放/平移)。
For example:
例如:
import matplotlib.pyplot as plt
y = range(20)
x1 = range(20)
x2 = range(0, 200, 10)
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].barh(y, x1, align='center', color='gray')
axes[1].barh(y, x2, align='center', color='gray')
axes[0].invert_xaxis()
plt.show()


If you want to more precisely reproduce the example shown in the question you linked to (I'm leaving off the gray background and white grids, but those are easy to add, if you prefer them):
如果您想更准确地重现您链接到的问题中显示的示例(我不使用灰色背景和白色网格,但如果您愿意,这些很容易添加):
import numpy as np
import matplotlib.pyplot as plt
# Data
states = ["AK", "TX", "CA", "MT", "NM", "AZ", "NV", "CO", "OR", "WY", "MI",
"MN", "UT", "ID", "KS", "NE", "SD", "WA", "ND", "OK"]
staff = np.array([20, 30, 40, 10, 15, 35, 18, 25, 22, 7, 12, 22, 3, 4, 5, 8,
14, 28, 24, 32])
sales = staff * (20 + 10 * np.random.random(staff.size))
# Sort by number of sales staff
idx = staff.argsort()
states, staff, sales = [np.take(x, idx) for x in [states, staff, sales]]
y = np.arange(sales.size)
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].barh(y, staff, align='center', color='gray', zorder=10)
axes[0].set(title='Number of sales staff')
axes[1].barh(y, sales, align='center', color='gray', zorder=10)
axes[1].set(title='Sales (x 00)')
axes[0].invert_xaxis()
axes[0].set(yticks=y, yticklabels=states)
axes[0].yaxis.tick_right()
for ax in axes.flat:
ax.margins(0.03)
ax.grid(True)
fig.tight_layout()
fig.subplots_adjust(wspace=0.09)
plt.show()


One caveat. I haven't actually aligned the y-tick-labels correctly. It is possible to do this, but it's more of a pain than you might expect. Therefore, if you really want y-tick-labels that are always perfectly centered in the middle of the figure, it's easiest to draw them a different way. Instead of axes[0].set(yticks=y, yticklabels=states), you'd do something like:
一个警告。我实际上没有正确对齐 y-tick-labels。这样做是可能的,但这比您想象的要痛苦。因此,如果您真的希望 y-tick-labels 始终完美地居中在图形中间,最容易以不同的方式绘制它们。而不是axes[0].set(yticks=y, yticklabels=states),你会做这样的事情:
axes[0].set(yticks=y, yticklabels=[])
for yloc, state in zip(y, states):
axes[0].annotate(state, (0.5, yloc), xycoords=('figure fraction', 'data'),
ha='center', va='center')
回答by regdoug
Using some information I found in the matplotlib mailing list, I adapted one of the matplotlib horizontal bar chart example to make a pyramid plot.
使用我在 matplotlib 邮件列表中找到的一些信息,我改编了 matplotlib 水平条形图示例之一来制作金字塔图。
The pyramid_plotfunction listed below will plot horizontal bars side-by-side.
下面pyramid_plot列出的函数将并排绘制水平条。
def pyramid_plot(ylabels, data_left, xlabel_left, data_right, xlabel_right, fig=None, **kwargs):
if(fig is None):
fig = plt.figure()
y_pos = np.arange(len(ylabels))
empty_ticks = tuple('' for n in people)
fig.add_subplot(121)
plt.barh(y_pos, data_left, **kwargs)
plt.yticks(y_pos, empty_ticks)
oldlims = plt.gca().get_xlim()
plt.axis(xmin=oldlims[1], xmax=oldlims[0])
plt.xlabel(xlabel_left)
fig.add_subplot(122)
plt.barh(y_pos, data_right, **kwargs)
plt.yticks(y_pos, ylabels)
plt.xlabel(xlabel_right)
return fig
The pyramid_plotfunction is used as follows
该pyramid_plot功能用于如下
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
# Example data
people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')
performance = 3 + 10 * np.random.rand(len(people))
salary = np.linspace(30,60,len(people))
# Plot the data
pyrfig = plt.figure(1)
pyrfig = pyramid_plot(people, salary, 'Salary (thousands)', performance, 'Performance', pyrfig, align='center', alpha=0.4)
pyrfig.suptitle('Pyramid Plot')
pyrfig.set_figwidth(1.5*pyrfig.get_figheight())
plt.show(pyrfig)
References:
参考:
http://matplotlib.org/examples/lines_bars_and_markers/barh_demo.html
http://matplotlib.org/examples/lines_bars_and_markers/barh_demo.html
https://www.mail-archive.com/[email protected]/msg11606.html
https://www.mail-archive.com/[email protected]/msg11606.html

