如果您想要一个直方图,您不需要给x值附加任何“名称”,因为:
x
轴上您将拥有数据的区间y
轴上是计数(默认)或频率(density=True
)import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30) # density=False would make counts
plt.ylabel('Probability')
plt.xlabel('Data');
请注意,选择bins=30
的数量是任意的,而选择“正确”的箱宽度有Freedman-Diaconis规则以更科学的方式进行:
,其中
IQR
是四分位距,n
是要绘制的数据点的总数
因此,根据这个规则,可以计算出bins
的数量:
q25, q75 = np.percentile(x, [25, 75])
bin_width = 2 * (q75 - q25) * len(x) ** (-1/3)
bins = round((x.max() - x.min()) / bin_width)
print("Freedman–Diaconis number of bins:", bins)
plt.hist(x, bins=bins);
Freedman–Diaconis number of bins: 82
最后,您可以使用PDF
线、标题和图例使您的直方图变得更加漂亮:
import scipy.stats as st
plt.hist(x, density=True, bins=82, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 300)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel("Probability")
plt.xlabel("Data")
plt.title("Histogram");
如果你愿意尝试其他机会,使用seaborn
可以更快捷:
# !pip install seaborn
import seaborn as sns
sns.displot(x, bins=82, kde=True);
现在回到原帖。
如果您的数据点数量有限,使用条形图更有意义来表示您的数据。然后,您可以将标签附加到x轴:
x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c']);
plt.hist(probability)
,也许还有分组选项,并且已经可用的x标签的使用是可疑的。import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375,
0.373117033603708, 0.36813186813186816, 0.32517482517482516,
0.4175257731958763, 0.41025641025641024, 0.39408866995073893,
0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327,
0.35398230088495575]
plt.hist(probability)
plt.show()
带着结果
在这种情况下,matplotlib默认提供以下直方图值。(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
0.42028986]),
<a list of 10 Patch objects>)
x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
print(left, right, right-left)
例如,对于3个箱子(我在13个观测值的情况下做出的判断),将得到以下直方图
plt.hist(probability, bins=3)
使用“behind the bars”绘制的图表数据
问题的作者需要澄清"probability"值列表的含义 - "probability"是否只是响应变量的名称(那么为什么准备了直方图的x标签,这毫无意义),还是列表值是从数据计算出来的概率(那么它们不加起来就没有意义)。matplotlib.hist()
函数绘制直方图,但可以说在同样的要求下使用该函数是行不通的,因为问题的后半部分要求将给定的概率用作条形的 y 值,将给定的名称(字符串)用作 x 值。import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375,
0.373117033603708, 0.36813186813186816, 0.32517482517482516,
0.4175257731958763, 0.41025641025641024, 0.39408866995073893,
0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327,
0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')
这是一种非常迂回的方法,但如果您想制作直方图,已知bin值但没有源数据,则可以使用np.random.randint
函数生成每个bin范围内正确数量的值以进行图形绘制,例如:
import numpy as np
import matplotlib.pyplot as plt
data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])
关于标签,您可以将x轴刻度与条形图对齐,得到如下结果:
#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])