目前,我试图用python中的fill_between函数填充直方图,直到原始数字中的10和90百分位数。 然而,问题是直方图曲线不是一个“函数”,而是一系列离散数与bin大小的间隔。我无法填充到10或90百分位。我尝试了几次尝试,但我失败了。 下面的代码是我试过的:
S1 = [0.34804491 0.18036933 0.41111951 0.31947523 .........
0.46212255 0.39229157 0.28937502 0.22095423 0.52415083]
N, bins = np.histogram(S1, bins=np.linspace(0.1,0.7,20), normed=False)
bincenters = 0.5*(bins[1:]+bins[:-1])
ax.fill_between(bincenters,N,0,where=bincenters<=np.percentile(S1,10),interpolate=True,facecolor='r', alpha=0.5)
ax.fill_between(bincenters,N,0,where=bincenters>=np.percentile(S1,90),interpolate=True, facecolor='r', alpha=0.5,label = "Summer 10 P")
它似乎只在给定百分位数之前或之后填充直到bincenter,直到达到那些。
任何想法或帮助都会非常感激。 艾萨克
答案 0 :(得分:2)
尝试将最后两行更改为:
ax.fill_between(bincenters, 0, N, interpolate=True,
where=((bincenters>=np.percentile(bincenters, 10)) &
(bincenters<=np.percentile(bincenters, 90))))
我相信你想在np.percentile
上致电bincenters
,因为这是你有效的x轴。
另一个区别是,您希望填充10<x<90
区域之间的填充,这需要在&
参数中使用where
。
根据OP的评论进行编辑:
我认为要实现你想要的,你必须做一些你自己的最小插值。请使用随机正态分布查看下面的示例,其中我使用interp1d
scipy.interpolate
来bincenters
进行插值。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# create normally distributed random data
n = 10000
data = np.random.normal(0, 1, n)
bins = np.linspace(-data.max(), data.max(), 20)
hist = np.histogram(data, bins=bins)[0]
bincenters = 0.5 * (bins[1:] + bins[:-1])
# create interpolation function and dense x-axis to interpolate over
f = interp1d(bincenters, hist, kind='cubic')
x = np.linspace(bincenters.min(), bincenters.max(), n)
plt.plot(bincenters, hist, '-o')
# calculate greatest bincenter < 10th percentile
bincenter_under10thPerc = bincenters[bincenters < np.percentile(bincenters, 10)].max()
bincenter_10thPerc = np.percentile(bincenters, 10)
bincenter_90thPerc = np.percentile(bincenters, 90)
# calculate smallest bincenter > 90th percentile
bincenter_above90thPerc = bincenters[bincenters > np.percentile(bincenters, 90)].min()
# fill between 10th percentile region using dense x-axis array, x
plt.fill_between(x, 0, f(x), interpolate=True,
where=((x>=bincenter_under10thPerc) &
(x<=bincenter_10thPerc)))
# fill between 90th percentile region using dense x-axis array, x
plt.fill_between(x, 0, f(x), interpolate=True,
where=((x>=bincenter_90thPerc) &
(x<=bincenter_above90thPerc)))
我得出的数字如下。请注意,我将百分位数从10/90%更改为30/70%,以便它们在情节中显示得更好。再次,我希望这就是你要做的事情
答案 1 :(得分:0)
我有一个版本,使用axvspan
制作一个Rectangle,然后将hist用作clip_path:
def hist(sample, low=None, high=None):
# draw the histogram
options = dict(alpha=0.5, color='C0')
xs, ys, patches = plt.hist(sample,
density=True,
histtype='step',
linewidth=3,
**options)
# fill in the histogram, if desired
if low is not None:
x1 = low
if high is not None:
x2 = high
else:
x2 = np.max(sample)
fill = plt.axvspan(x1, x2,
clip_path=patches[0],
**options)
这样的事情对你有用吗?