围绕x轴标签的Pyplot箱线图

3

我有一系列箱线图,希望它们围绕着x轴刻度居中(每个刻度有2个具体)。请考虑以下内容:

# fake up some more data
spread= rand(50) * 100
center = ones(25) * 40
flier_high = rand(10) * 100 + 100
flier_low = rand(10) * -100
d2 = concatenate( (spread, center, flier_high, flier_low), 0 )
data.shape = (-1, 1)
d2.shape = (-1, 1)
#data = concatenate( (data, d2), 1 )
# Making a 2-D array only works if all the columns are the
# same length.  If they are not, then use a list instead.
# This is actually more efficient because boxplot converts
# a 2-D array into a list of vectors internally anyway.
data = [data, d2, d2[::2,0]]
# multiple box plots on one figure
figure()
boxplot(data)

这将产生以下箱线图:

Boxplot output

但是我想要6个箱线图,其中2个围绕着1,2个围绕着2,以此类推...如果我再添加三个,则只会将它们添加到4、5、6...任何帮助都将不胜感激。

编辑 为了清楚我所说的“居中”,我想要一个箱线图位于标有“1”的xtick左侧,另一个箱线图位于其右侧。它们可能在y范围内重叠,因此我不希望它们重叠绘制。

1个回答

9

要控制箱线图的x轴位置,请使用positions参数。

例如:

import numpy as np
import matplotlib.pyplot as plt

dists = [np.random.normal(i, 1, 100) for i in range(0, 10, 2)]

fig, ax = plt.subplots()
ax.boxplot(dists, positions=[0, 1, 2, 0, 1])
plt.show()

enter image description here

如果你想让这些组并排显示,你需要自己计算它们的位置。其中一种方法是:

def grouped_boxplots(data_groups, ax=None, max_width=0.8, pad=0.05, **kwargs):
    if ax is None:
        ax = plt.gca()

    max_group_size = max(len(item) for item in data_groups)
    total_padding = pad * (max_group_size - 1)
    width = (max_width - total_padding) / max_group_size
    kwargs['widths'] = width

    def positions(group, i):
        span = width * len(group) + pad * (len(group) - 1)
        ends = (span - width) / 2
        x = np.linspace(-ends, ends, len(group))
        return x + i

    artists = []
    for i, group in enumerate(data_groups, start=1):
        artist = ax.boxplot(group, positions=positions(group, i), **kwargs)
        artists.append(artist)

    ax.margins(0.05)
    ax.set(xticks=np.arange(len(data_groups)) + 1)
    ax.autoscale()
    return artists

以下是使用它的一个快速示例:

data = [[np.random.normal(i, 1, 30) for i in range(2)],
        [np.random.normal(i, 1.5, 30) for i in range(3)],
        [np.random.normal(i, 2, 30) for i in range(4)]]

grouped_boxplots(data)
plt.show()

输入图像描述

...为了展示一个过于花哨的例子:


(注:此处无需翻译html标签)
import numpy as np
import matplotlib.pyplot as plt

def main():
    data = [[np.random.normal(i, 1, 30) for i in range(2)],
            [np.random.normal(i, 1.5, 30) for i in range(3)],
            [np.random.normal(i, 2, 30) for i in range(4)]]

    fig, ax = plt.subplots()
    groups = grouped_boxplots(data, ax, max_width=0.9,
                              patch_artist=True, notch=True)

    colors = ['lavender', 'lightblue', 'bisque', 'lightgreen']
    for item in groups:
        for color, patch in zip(colors, item['boxes']):
            patch.set(facecolor=color)

    proxy_artists = groups[-1]['boxes']
    ax.legend(proxy_artists, ['Group A', 'Group B', 'Group C', 'Group D'],
              loc='best')
    ax.set(xlabel='Year', ylabel='Performance', axisbelow=True,
           xticklabels=['2012', '2013', '2014'])

    ax.grid(axis='y', ls='-', color='white', lw=2)
    ax.patch.set(facecolor='0.95')
    plt.show()

def grouped_boxplots(data_groups, ax=None, max_width=0.8, pad=0.05, **kwargs):
    if ax is None:
        ax = plt.gca()

    max_group_size = max(len(item) for item in data_groups)
    total_padding = pad * (max_group_size - 1)
    width = (max_width - total_padding) / max_group_size
    kwargs['widths'] = width

    def positions(group, i):
        span = width * len(group) + pad * (len(group) - 1)
        ends = (span - width) / 2
        x = np.linspace(-ends, ends, len(group))
        return x + i

    artists = []
    for i, group in enumerate(data_groups, start=1):
        artist = ax.boxplot(group, positions=positions(group, i), **kwargs)
        artists.append(artist)

    ax.margins(0.05)
    ax.set(xticks=np.arange(len(data_groups)) + 1)
    ax.autoscale()
    return artists

main()

enter image description here


如果我的箱线图占据相同的y轴范围会发生什么?它们会互相覆盖吗?这就是为什么我希望它们围绕索引居中(即一个在0的左侧,一个在右侧)。这样我就可以将它们并排放置。 - sedavidw
@sedavidw - 是的,它们会重叠。我误解了你所说的“居中”。我马上会添加一个你所想要的例子... - Joe Kington
@sedavidw - 我已经添加了一个示例,展示了一种你所想的分组方式。希望这能让你更接近目标。 - Joe Kington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接