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的主要内容,如果未能解决你的问题,请参考以下文章