我想绘制两个共享相同y轴的水平条形图。例如,以下问题显示了如何在R中实现此目的:
Two horizontal bar charts with shared axis in ggplot2 (similar to population pyramid)
如何使用Python创建类似的情节?
上述问题的情节如下:
以下是上图(y轴)中使用的状态列表:
["AK", "TX", "CA", "MT", "NM", "AZ", "NV", "CO", "OR", "WY",
"MI", "MN", "UT", "ID", "KS", "NE", "SD", "WA", "ND", "OK"]
以下是每个州的销售人员数量列表:
[20,30,40,10,15,35,18,25,22,7,12,22,3,4,5,8,14,28,24,32]
销售数字可以是随机的。
答案 0 :(得分:21)
一般来说,如果您显示的两个变量位于不同的单位或具有不同的范围,那么您将需要使用两个具有共享y轴的子图。这类似于@regdoug的答案,但最好明确地共享y轴以确保数据保持对齐(例如,尝试使用此示例进行缩放/平移)。
例如:
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()
如果您想更精确地重现您链接到的问题中显示的示例(我将不再使用灰色背景和白色网格,但如果您愿意,可以轻松添加这些示例):
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 $1000)')
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()
一个警告。我没有真正正确对齐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')
答案 1 :(得分:2)
使用我在matplotlib邮件列表中找到的一些信息,我调整了一个matplotlib水平条形图示例来制作金字塔图。
下面列出的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
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)
参考文献:
http://matplotlib.org/examples/lines_bars_and_markers/barh_demo.html
https://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg11606.html