Matplotlib:绘制具有非透明边缘的透明直方图

Posted

技术标签:

【中文标题】Matplotlib:绘制具有非透明边缘的透明直方图【英文标题】:Matplotlib: plotting transparent histogram with non transparent edge 【发布时间】:2015-04-08 12:13:48 【问题描述】:

我正在绘制一个直方图,我有三个要一起绘制的数据集,每个数据集都有不同的颜色和线型(虚线、点线等)。 我还提供了一些透明度,以便看到重叠的条形。

关键是我希望每个条的边缘不要像内部那样变得透明。 这是一个例子:

import matplotlib.pyplot as plt
import numpy as np

x = np.random.random(20)
y =np.random.random(20)
z= np.random.random(20)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', alpha = 0.5, lw=3, color= 'b')
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', alpha = 0.5, lw=3, color= 'r')
ax.hist(z, bins=np.arange(0, 1, 0.1), alpha = 0.5, lw=3, color= 'k')
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(0, 7)
plt.show()

【问题讨论】:

【参考方案1】:

plt.hist 接受传递给matplotlib.patches.Patch 的构造函数的附加关键字参数。特别是,您可以传递一个fc= 参数,该参数允许您在创建直方图时使用(R, G, B, A) 元组设置补丁面颜色。改变 facecolor 的 alpha 值不会影响边缘的透明度:

ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', lw=3, fc=(0, 0, 1, 0.5))
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', lw=3, fc=(1, 0, 0, 0.5))
ax.hist(z, bins=np.arange(0, 1, 0.1), lw=3, fc=(0, 0, 0, 0.5))

【讨论】:

有没有办法仍然使用自动颜色循环? 这有点小技巧,但可以从轴上获取道具循环器(请参阅this answer 和下面的 cmets)。您可能想要ax._get_patches_for_fill.prop_cycler 而不是ax._get_lines.prop_cycler)。 prop 循环器返回的颜色将是字符串(例如 'b')而不是 RGB 元组,因此您需要使用 matplotlib.colors.to_rgb(color_string) 将字符串转换为 RGB 元组,然后附加您自己的 alpha 值。 谢谢你工作正常!我发布了一个小答案来展示一个完整的解决方案。【参考方案2】:

我认为也许最愚蠢的解决方案是最简单和最好的?只需重新绘制直方图,没有内部颜色和 alpha。那应该只重新绘制直方图线。

此外,您可能希望通过从第一个直方图中完全删除它们来消除线条/破折号/点不重叠的可能性

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

x = np.random.random(20)
y = np.random.random(20)
z = np.random.random(20)

fig = plt.figure()
ax = fig.add_subplot(111)

ax.hist(x, bins=np.arange(0, 1, 0.1), edgecolor='None', alpha = 0.5, color= 'b')
ax.hist(y, bins=np.arange(0, 1, 0.1), edgecolor='None', alpha = 0.5, color= 'r')
ax.hist(z, bins=np.arange(0, 1, 0.1), edgecolor="None", alpha = 0.5, color= 'k')


ax.hist(x, bins=np.arange(0, 1, 0.1), ls='dashed', lw=3, facecolor="None")
ax.hist(y, bins=np.arange(0, 1, 0.1), ls='dotted', lw=3, facecolor="None")
ax.hist(z, bins=np.arange(0, 1, 0.1), lw=3, facecolor="None")

plt.show()

没有二阶图形应该看起来像你的图形没有任何边界。底部的 3 个直方图命令添加了边框以生成下面的图像。适用于 Python3.4 Win7

[删掉,因为显然我没有足够的代表来发布图片]

【讨论】:

【参考方案3】:

我需要一个不需要我明确设置颜色的解决方案,即,我仍想使用默认颜色循环。以下解决方案基于@ljetibo 的想法,使用@ali_m 的想法绘制两次直方图以提取颜色循环的状态:

# increment and get the "props" cycle (and extract the color)
color = next(ax._get_lines.prop_cycler)["color"]
# 1. draw: inner area with alpha
ax.hist(data, color=color, alpha=0.3)
# 2. draw: only edges with full color
ax.hist(data, color=color, edgecolor=color, fc="None", lw=1)

请注意,除了edgecolor 之外,还要指定color=color 似乎是必要的。否则,hist 调用本身将再次增加颜色循环。

【讨论】:

以上是关于Matplotlib:绘制具有非透明边缘的透明直方图的主要内容,如果未能解决你的问题,请参考以下文章

matplotlib可视化篇barh()--直方图(2)

Matplotlib 绘制直方图、散点图

matplotlib 中 Poly3DCollection 图的透明度

Python使用matplotlib绘制透明背景的可视化图像并保存透明背景的可视化结果(transparent background)

如何绘制直方图的密度而非计数? (Matplotlib)

如何从具有透明背景的 matplotlib 导出绘图?