更改熊猫箱线图子图中各个框的颜色
Posted
技术标签:
【中文标题】更改熊猫箱线图子图中各个框的颜色【英文标题】:Change color of individual boxes in pandas boxplot subplots 【发布时间】:2018-11-30 12:23:24 【问题描述】:这是参考以下问题,其中讨论了调整子图标题和布局的选项: modify pandas boxplot output
我的要求是更改每个子图中各个框的颜色(如下所示):
以下是共享链接中用于调整子图的标题和轴属性的代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])
df['models'] = pd.Series(np.repeat(['model1','model2', 'model3', 'model4', 'model5', 'model6', 'model7'], 20))
bp = df.boxplot(by="models",layout=(4,1),figsize=(6,8))
[ax_tmp.set_xlabel('') for ax_tmp in np.asarray(bp).reshape(-1)]
fig = np.asarray(bp).reshape(-1)[0].get_figure()
fig.suptitle('New title here')
plt.show()
我尝试使用: ax.set_facecolor('颜色') 属性,但没有成功获得想要的结果。
我也尝试访问 bp['boxes'] 但显然它不可用。我需要了解存储在 bp 中的数据结构,才能访问子图中的各个框。
期待
P.S:我知道 seaborn。但目前需要使用 df.boxplot 来理解和实现。谢谢
【问题讨论】:
我认为使用 pandas 很难做到这一点。由于 pandas 绘图在引擎盖下使用matplotlib
,我会考虑使用纯 matplotlib,这使得更改单个框的颜色变得非常容易
【参考方案1】:
要调整 pandas.boxplot
中框的颜色,您必须稍微调整代码。首先,您必须告诉boxplot
实际用颜色填充框。您可以通过指定patch_artist = True
来执行此操作,如文档中的here 所述。但是,您似乎无法指定颜色(默认为蓝色) - 如果我错了,请任何人纠正我。这意味着您必须在之后更改颜色。幸运的是,pandas.boxplot
提供了一个简单的选项,通过指定 return_type = 'both'
see here 来获取箱线图中的艺术家作为返回值进行解释。你得到的是一个pandas.Series
,其中的键根据你的DataFrame
列和值是包含绘制箱线图的Axes
实例的元组以及字典中箱线图的实际元素。我认为代码是不言自明的:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])
df['models'] = pd.Series(np.repeat(['model1','model2', 'model3', 'model4', 'model5', 'model6', 'model7'], 20))
bp_dict = df.boxplot(
by="models",layout=(4,1),figsize=(6,8),
return_type='both',
patch_artist = True,
)
colors = ['b', 'y', 'm', 'c', 'g', 'b', 'r', 'k', ]
for row_key, (ax,row) in bp_dict.iteritems():
ax.set_xlabel('')
for i,box in enumerate(row['boxes']):
box.set_facecolor(colors[i])
plt.show()
生成的图如下所示:
希望这会有所帮助。
【讨论】:
谢谢 Thomas :) 这很有帮助。只是提到我最终使用了 bp_dict.iteritems(): 因为我收到了属性错误 - “AttributeError: 'Series' object has no attribute 'items'” 嗨 Thomas。如何为每个子图保留独立轴(y 和 x)?我用 i,el in enumerate(list(df.columns.values)): df.boxplot(el, by=metacategory,ax=axes.flatten()[i]) 但无法将独立颜色应用于在那种情况下每个盒子...... ***.com/questions/50971091/… @JALO-JusAnotherLivngOrganism 感谢您的评论——我稍微编辑了答案。我也会看看你的其他问题......【参考方案2】:虽然你将返回命名为df.boxplot
bp
,但它实际上是一个(n)个(数组)轴。检查轴以获取箱线图的各个部分很麻烦(但可能)。
首先,为了能够为盒子的内部着色,您需要将盒子变成补丁,df.boxplot(..., patch_artist=True)
。
然后您需要在坐标轴中的所有艺术家中找到框。
# We want to make the 4th box in the second axes red
axes[1].findobj(matplotlib.patches.Patch)[3].set_facecolor("red")
完整代码:
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])
df['models'] = pd.Series(np.repeat(['model1', 'model2', 'model3', 'model4',
'model5', 'model6', 'model7'], 20))
axes = df.boxplot(by="models", layout=(len(df.columns)-1,1), figsize=(6,8), patch_artist=True)
for ax in axes:
ax.set_xlabel('')
# We want to make the 4th box in the second axes red
axes[1].findobj(matplotlib.patches.Patch)[3].set_facecolor("red")
fig = axes[0].get_figure()
fig.suptitle('New title here')
plt.show()
【讨论】:
非常感谢您的意见 :) 您的回答确实帮助我更好地理解了结构。你的两个答案都很有帮助和完美。我接受托马斯的回答只是为了尊重他首先回答的事实。我希望有接受这两个选项..再次非常感谢。顺便说一句,我仍在学习过程中,关于如何独立追求变量/赋值结构的任何建议?以便了解需要哪些索引?再次感谢。问候 JALO 哦,我没有看到其他答案。这可能是更好的一个,因为您不必在轴中找到对象(如果您在轴中还有其他绘图对象,这也是相关的)。不知道我理解你所说的“独立地追求变量/赋值的结构”是什么意思。 我的意思是如何在坐标区中查找对象。例如,作为一个新手,我试图打印轴。我试图为每个子图手动分配 y 轴的限制(一行中的子图共享公共 y 轴/x 轴)。我正在使用 ymx=max(df.loc[row_key]); ax.set_ylim(0, ymx),但我认为有一个命令可以保持轴分开? for i,el in enumerate(list(df.columns.values)[:-1]): tt.boxplot(el, by=metacategory,ax=axes.flatten()[i]) 有帮助,但我不能以这种方式为各个框着色...findobj 不存在用于子图.. 我认为您正在尝试将一个完整的问题压缩成 300 个字符的评论。我不认为我以这种压缩方式理解你的问题。 这里是问题:***.com/questions/50971091/…以上是关于更改熊猫箱线图子图中各个框的颜色的主要内容,如果未能解决你的问题,请参考以下文章