如何在Python中使用Matplotlib绘制带有数据列表的直方图?


98

我正在尝试使用该matplotlib.hist()函数绘制直方图,但是我不确定该怎么做。

我有一个清单

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]

和名称(字符串)列表。

如何使概率作为每个小节的y值,并命名为x值?

Answers:


167

如果您想要直方图,则无需在x值上附加任何“名称”,因为在x轴上您将具有数据仓:

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');

在此处输入图片说明

您可以通过PDF线条,标题和图例使直方图更奇特:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
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");

在此处输入图片说明

但是,如果您的数据点数量有限(例如在OP中),则条形图可以更好地表示您的数据(然后您可以在x轴上附加标签):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

在此处输入图片说明


4
记住,在python行的末尾没有分号!
Toad22222

10
@ Toad22222这是Ipython笔记本单元的摘录。尝试在不使用分号的情况下执行它,并观察其中的区别。我在SO上发布的所有代码段都可以在我的计算机上完美运行。
谢尔盖·布什曼诺夫

2
如果您想知道Sergey使用的分号,请参阅此处此处的#16,以了解在绘制以抑制有关plot对象的文本时Jupyter笔记本(以前为IPython笔记本)单元格中如何使用分号。
韦恩

19

如果尚未安装matplotlib,请尝试使用该命令。

> pip install matplotlib

图书馆进口

import matplotlib.pyplot as plot

直方图数据:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

显示直方图

plot.show()

和输出是这样的:

在此处输入图片说明


2
对于示例,plot.axis([50,110,0,0.06])'行是无用的。此外,由于很难对要显示的区域进行硬编码,因此如果您的数据不能完全容纳在其中,您可能会感到困惑,为什么它无法正确显示。
typhon04

8

尽管问题似乎要求使用以下方法绘制直方图 matplotlib.hist()函数,但可以使用问题的后半部分,即使用给定的概率作为直方图的y值并使用给定的名称(字符串)作为直方图的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')

4

这是一种非常绕行的方法,但是如果要创建直方图,在该直方图中您已经知道bin值但没有源数据,则可以使用该np.random.randint函数在每个范围内生成正确数量的值bin用于绘制的hist函数,例如:

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.. ])

2

这是一个老问题,但是先前的答案都没有解决真正的问题,即问题出在问题本身这一事实。

首先,如果已经计算出概率,即直方图聚合数据可以通过归一化的方式获得,则概率应加起来为1。它们显然没有,这意味着术语或数据有问题。或以询问方式。

其次,提供标签(而不是间隔)的事实通常意味着概率是分类响应变量的-最好使用条形图来绘制直方图(或者对pyplot的hist方法进行一些修改), Shayan Shafiq的答案提供了代码。

但是,请参阅问题1,这些概率是不正确的,在这种情况下使用条形图作为“直方图”将是错误的,因为由于某些原因,它不能告诉单变量分布的故事(也许类别是重叠的,并且观察被计数为多个)时间?),这种情况下不应称为直方图。

根据定义,直方图是单变量分布的图形表示(请参见 https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htmhttps://en.wikipedia.org/wiki /直方图),并通过绘制各种尺寸的条来创建,这些条表示关注变量的选定类别中的观察次数或观察频率。如果变量以连续刻度进行测量,则这些类别为箱(间隔)。直方图创建过程的重要部分是选择如何对分类变量的响应类别进行分组(或不分组分组),或者如何将可能值的域划分为连续的区间(在其中放置bin边界)类型变量。所有观察结果都应表示出来,并且每个图中只能观察一次。这意味着条形尺寸的总和应等于观察的总数(或宽度可变的情况下其面积,这是一种较不常用的方法)。或者,如果直方图已归一化,则所有概率必须加起来为1。

如果数据本身是作为响应的“概率”列表,即观察值是每个研究对象的(某物)概率值,则最佳答案就是 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>)

结果是一个数组元组,第一个数组包含观察计数,即将相对于图的y轴显示的值(它们总计为13,观察总数),第二个数组是x的区间边界-轴。

可以检查它们是否等距分布,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

在此处输入图片说明

或者,例如,对于3个bin(我的判断是需要13个观察值),一个将获得此直方图

plt.hist(probability, bins=3)

在此处输入图片说明

情节数据“在酒吧后面”是

在此处输入图片说明

问题的作者需要弄清楚“概率”值列表的含义是什么-“概率”只是响应变量的名称(然后为什么为直方图准备了x标签,这没有任何意义),还是列表值是根据数据计算出的概率(然后它们之和不等于1的事实就没有意义了)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.