Matplotlib绘制两种颜色的分布图

3
这里的目标是将高于某个阈值的颜色转换为一种颜色,低于该阈值的颜色转换为另一种颜色。下面的代码尝试将其分成两个直方图,但只有当阈值为50%时才看起来平衡。我认为我必须玩弄离散变量。 finalutilityrange 是一个包含许多值的向量(您需要生成它以测试代码),我正在尝试绘制它。 值 deter 是决定它们将是蓝色还是红色的值。 discreetlevel 就是我想要的分组数量。
import random
import numpy as np
import matplotlib.pyplot as plt

discreetlevel = 10
deter = 2

for x in range(0,len(finalutilityrange)):
    if finalutilityrange[x-1]>=deter:
        piraterange.append(finalutilityrange[x-1])
    else:
        nonpiraterange.append(finalutilityrange[x-1])

plt.hist(piraterange,bins=discreetlevel,normed=False,cumulative=False,color = 'b')
plt.hist(nonpiraterange,bins=discreetlevel),normed=False,cumulative=False,color = 'r')
plt.title("Histogram")
plt.xlabel("Utlity")
plt.ylabel("Probability")
plt.show()

不是你的问题,但你的for循环实现有误。幸运的是,Python解释器会解释finalutilityrange[-1]而不是引发错误。 - Mad Physicist
谢谢您的纠正! - Dio
3个回答

3

这个解决方案比@user2699的要复杂一些,我只是为了完整性而提出它。你可以完全控制hist返回的补丁对象,所以如果你能确保使用的阈值恰好处于一个bin边缘,就很容易改变所选补丁的颜色。你可以做到这一点,因为hist可以接受一个bin边缘的序列作为bins参数。

import numpy as np
from matplotlib import pyplot as plt 

# Make sample data
finalutilityrange = np.random.randn(100)
discreetlevel = 10
deter = 0.2

# Manually create `discreetlevel` bins anchored to  `deter`
binsAbove = round(discreetlevel * np.count_nonzero(finalutilityrange > deter) / finalutilityrange.size)
binsBelow = discreetlevel - binsAbove
binwidth = max((finalutilityrange.max() - deter) / binsAbove,
               (deter - finalutilityrange.min()) / binsBelow)
bins = np.concatenate([
           np.arange(deter - binsBelow * binwidth, deter, binwidth),
           np.arange(deter, deter + (binsAbove + 0.5) * binwidth, binwidth)
])

# Use the bins to make a single histogram
h, bins, patches = plt.hist(finalutilityrange, bins, color='b')

# Change the appropriate patches to red
plt.setp([p for p, b in zip(patches, bins) if b >= deter], color='r')

结果是一个由不同颜色的条形组成的均匀直方图: enter image description here 如果您将锚定到“deter”,则柱可能会比没有锚定时略宽。通常,第一个或最后一个柱将稍微超出数据边缘。

@Mad_Physicist 有点困惑,x是什么? - Dio
@Dio。感谢你的提醒。x是我在测试工作区中使用的变量,我忘记将其更改为finalutilityrange。现已修复。 - Mad Physicist
还更新了最后的列表推导式。请注意,setp 在处理任意可迭代对象时可能会出现问题,但已经修复,但可能尚未在官方的1.5版本中发布。 - Mad Physicist
那么如何将图例添加到具有不同颜色的这两种类型的数据中呢? - rosefun
@rosefun。如果您找不到答案,我建议您搜索并提出新问题。 - Mad Physicist

1
这个回答并没有涉及到你的代码,因为它不是自包含的。但是对于你想做的事情来说,默认的直方图应该可以工作(假设已经加载了numpy/pyplot)。
x = randn(100)
idx = x < 0.2 # Threshold to separate values
hist([x[idx], x[~idx]], color=['b', 'r'])

解释:

  1. 第一行只是生成一些随机数据进行测试,
  2. 创建一个索引,确定数据低于某个阈值的位置,可以用 ~ 取反来确定高于阈值的位置
  3. 最后一行绘制直方图。该命令接受要绘制的单独组的列表,这在这里没有太大区别,但如果 normed=True,它将会有所不同。

直方图绘图还有更多功能,请查阅文档,以免意外实现。


@user2699 谢谢,可以用了!问题: ~ 到底是做什么的?还有一个问题,为什么图表中颜色之间会出现分裂?红色和蓝色之间少了一根柱子... - Dio
这是因为您的分割阈值未对齐到一个或两个直方图的箱子。 - Mad Physicist
@Dio,“~”表示否定“idx”,因此它可以找到超过阈值的值所在的位置。条形图问题也可能是显示方式的问题,每个组都会为每个bin留出一个空间,即使该值为0。您可以使用选项“histype”更改该行为。 - user2699

0

就像上面一样做:

x = np.random.randn(100)
threshold_x = 0.2 # Threshold to separate values

x_lower, x_upper = (
    [_ for _ in x if _ < threshold_x], 
    [_ for _ in x if _ >= threshold_x]
)

hist([x_lower, x_upper], color=['b', 'r'])

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