【问题标题】:Using Python libraries to plot two horizontal bar charts sharing same y axis [closed]使用 Python 库绘制共享相同 y 轴的两个水平条形图 [关闭]
【发布时间】:2015-02-25 22:55:35
【问题描述】:

我想绘制两个共享相同 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]

销售数字可以是随机的。

【问题讨论】:

    标签: python matplotlib pandas


    【解决方案1】:

    一般来说,如果您显示的两个变量的单位不同或范围不同,您需要为此使用两个共享 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')
    

    【讨论】:

    • 像上面那样在 barh 图上更改 x 轴范围/限制的最佳方法是什么?
    • @Chuck axes[0].axis(xmin=0, xmax=1) axes[1].axis(xmin=0, xmax=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

    【讨论】:

      猜你喜欢
      • 2021-11-22
      • 1970-01-01
      • 2017-09-19
      • 1970-01-01
      • 2017-10-07
      • 2019-03-27
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      相关资源
      最近更新 更多