Pandas 按类别分组箱线图以比较 3 个数据集 Matplotlib

Posted

技术标签:

【中文标题】Pandas 按类别分组箱线图以比较 3 个数据集 Matplotlib【英文标题】:Pandas Grouped Boxplot by Category to Compare 3 Datasets Matplotlib 【发布时间】:2022-01-12 19:33:40 【问题描述】:

我正在尝试通过“site_name”为 3 个数据集 - 'obs'、'raw' 和 'adj' 生成一个单独的分组箱线图。因此,在本例中,最终图应该有 3 个按“site_name”或 SITE A、SITE B 分组的“obs”、“raw”和“adj”时间序列的并排箱线图。我的数据如下所示:

    site_name   obs         raw         adj
0   SITE A  6.418529189 11.23949224 6.985811001
1   SITE A  8.788185389 14.97198142 9.321099071
2   SITE A  9.150093299 15.03959828 9.974189383
3   SITE A  8.960796086 14.53909986 10.08513361
4   SITE A  7.04010526  11.32339089 7.496043956
5   SITE A  7.750408473 12.23209169 7.893739255
6   SITE A  5.396922286 9.262985075 5.584104478
7   SITE A  4.842398234 8.77877907  5.436729651
8   SITE A  2.46593252  4.809821429 2.779181548
9   SITE A  5.650324669 9.868885673 6.720622287
10  SITE B  12.98071991 14.58748261 13.09878999
11  SITE B  8.768521796 9.628748068 8.751576507
12  SITE B  7.163978706 8.305841446 7.146397775
13  SITE B  7.765772425 8.367532468 7.540894661
14  SITE B  6.370840508 5.733239437 5.893661972
15  SITE B  4.46220486  5.286569343 4.356613139
16  SITE B  8.766229103 9.188587732 8.637717546
17  SITE B  7.648023594 7.622237762 7.481734266
18  SITE B  6.26515501  6.109928058 6.035798561
19  SITE B  6.962116967 8.466759388 7.241140473

而且,我已经尝试过了,但它什么也没画,而且给我一个错误 -

df.boxplot(column=['site_name'],by=['obs','raw','adj'])

这个错误:

TypeError: ufunc 'true_divide' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

而且,我在下面尝试了这段代码,但它按 site_name 将“obs”、“raw”和“adj”列绘制在单独的组中,这不是我需要的。这是没有达到所需结果的代码:

df.boxplot(column=['obs','raw','adj'],by=['site_name'])

感谢您的帮助,

【问题讨论】:

你的意思是df.groupby('site_name').boxplot(column=['obs','raw','adj']) 就是这样!!非常感谢!! 通过使用您的解决方案,我可以以某种方式缩放每个图的 y 轴吗?? 【参考方案1】:

你可以先做groupby,然后在obs、raw、adj列上做boxplot。

要自定义绘图属性,可以添加return_type='axes'获取matplotlib坐标轴,然后可以调用坐标轴上的自定义函数。

此熊猫箱线图制作共享 y 轴图,这意味着您不能在每个图中有不同的 y 限制。

我不知道如何在此解决方案中禁用共享 y 轴,但是,我知道如何在替代解决方案中实现动态 y 轴限制。 (请参阅下面的更新)

axes = df.groupby('site_name').boxplot(column=['obs','raw','adj'], return_type='axes')

for ax in axes:
    ax.set_ylim(0, 20)  # Change y-axis limit to 0 - 20

================================================ =

更新:

如果您想对每个图应用不同的 y 限制,请尝试使用 matplotlib 中的子图。

import matplotlib.pyplot as plt

# Create 2 subplots for SITE A, SITE B in 1 row. By default, this will create 2 subplots that does not share the y-axis.
# To make shared y-axis, use plt.subplots(1, 2, sharey=True)
fig, axs = plt.subplots(1, 2)

# Create a boxplot per site_name and render in the subplots by passing ax=axs
df.groupby('site_name').boxplot(column=['obs', 'raw', 'adj'], ax=axs)

# Apply different y limits
axs[0].set_ylim(0, 50)  # For SITE A
axs[1].set_ylim(0, 20)  # For SITE B

# display my plots
fig

【讨论】:

嗨 - 再次感谢。抱歉,“调用轴上的自定义函数”是什么意思? 啊抱歉,我的意思是调用axes 函数返回的axes 变量上的任何可用函数。在上面的例子中,我调用了set_ylim 函数。有关轴的更多可用功能,请参见此处:matplotlib.org/stable/api/axes_api.html 你能分步总结你的想法,让我清楚吗? y 轴对于每个图都是动态的,并且需要为每个图进行一些更改,因此看起来循环解决方案可能比您的 set_ylim 建议的原始解决方案更好......? 我更新了我的答案,你能检查一下这是你想要实现的还是我遗漏了什么。 谢谢你,艾玛 - 这会奏效!

以上是关于Pandas 按类别分组箱线图以比较 3 个数据集 Matplotlib的主要内容,如果未能解决你的问题,请参考以下文章

为熊猫箱线图(groupby)设置无标题

向分组箱线图添加线条

将分割图(点图)添加到分组箱线图 - Pandas 和 Seaborn

按两个条件分组的多个箱线图

箱线图按python pandas中的列分层

使用 seaborn 或 matplotlib 分组箱线图的数据格式