箱线图:在seaborn中自定义宽度

8
我正试图使用seaborn绘制箱线图,其宽度取决于x轴值的对数。我正在创建宽度列表,并将其传递给seaborn.boxplot方法的widths参数。
但是,我得到的结果是:
raise ValueError(datashape_message.format("widths"))
ValueError: List of boxplot statistics and `widths` values must have same the length

当我进行调试并检查时,发现箱线图统计信息只有一个字典,而我有8个箱线图。无法确定问题出在哪里。

这是箱线图的图片

我正在使用pandas数据帧和seaborn进行绘图。

1个回答

4

Seaborn的箱线图似乎无法理解widths=参数。

这里有一种使用matplotlib的boxplot每个x值创建一个箱线图的方法,该方法接受width=参数。下面的代码假设数据已经组织在panda的数据框中。

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

df = pd.DataFrame({'x': np.random.choice([1, 3, 5, 8, 10, 30, 50, 100], 500),
                   'y': np.random.normal(750, 20, 500)})
xvals = np.unique(df.x)
positions = range(len(xvals))
plt.boxplot([df[df.x == xi].y for xi in xvals],
            positions=positions, showfliers=False,
            boxprops={'facecolor': 'none'}, medianprops={'color': 'black'}, patch_artist=True,
            widths=[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
means = [np.mean(df[df.x == xi].y) for xi in xvals]
plt.plot(positions, means, '--k*', lw=2)
# plt.xticks(positions, xvals) # not needed anymore, as the xticks are set by the swarmplot
sns.swarmplot('x', 'y', data=df)
plt.show()

范例图

有一篇相关问题问如何根据群组大小设置框的宽度。可以将宽度计算为某个最大宽度乘以每个群组的大小与最大群组大小的比值。

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

y_true = np.random.normal(size=100)
y_pred = y_true + np.random.normal(size=100)
df = pd.DataFrame({'y_true': y_true, 'y_pred': y_pred})
df['y_true_bin'] = pd.cut(df['y_true'], range(-3, 4))

sns.set()
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 5))
sns.boxplot(x='y_true_bin', y='y_pred', data=df, color='lightblue', ax=ax1)

bins, groups = zip(*df.groupby('y_true_bin')['y_pred'])
lengths = np.array([len(group) for group in groups])
max_width = 0.8
ax2.boxplot(groups, widths=max_width * lengths / lengths.max(),
            patch_artist=True, boxprops={'facecolor': 'lightblue'})
ax2.set_xticklabels(bins)
ax2.set_xlabel('y_true_bin')
ax2.set_ylabel('y_pred')
plt.tight_layout()
plt.show()

boxplot with widths depending on subset size


1
这在某种程度上解决了我的问题,但同时却又带来了新的问题。现在当我绘制 seaborn.swarmplot 或者 strip plot 时,它会以某种方式将整个图形向右移动一个箱线图的位置。链接 - FARAZ SHAIKH
1
如果通过swarmplot设置了刻度线,您可以删除plt.xticks(positions, xvals)。也许您没有更改旧的plt.xticks(range(1, len(xvals)+1), xvals),因为那会使值发生偏移。均值需要使用与箱线图相同的positions进行绘制。 - JohanC
1
盒形图已经处于其位置,但均线和x轴刻度仍然偏移。新的图表 - FARAZ SHAIKH
1
是的,现在它正如预期地绘制出来了。 :) - FARAZ SHAIKH
1
这个回答不是关于Seaborn的问题的确切答案,但是你通过pyplot绘制了盒形图,这有点像一个hack。你没有在这里使用Seaborn的特性。当我想要使用Seaborn的x、y、hue参数时,widths就不起作用了。 - buhtz
2
@buhtz 实际上,更“准确”的答案是:在seaborn中不支持widths参数。如果您还想包括hue,那么如何支持色调躲避并仍然获得漂亮的图形,同时避免重叠的框和框之间太远的距离,这将变得更加不明显。 - JohanC

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