Python: 出现频率

25 投票
3 回答
122946 浏览
提问于 2025-04-17 20:30

我有一串整数,想要知道每个整数出现的频率。这个问题在这里讨论过。

我遇到的问题是,我用的方法给出的频率是浮点数,而我的数据集只包含整数。这是为什么呢?我该如何从我的数据中获取整数的频率呢?

我正在使用pyplot.histogram来绘制一个显示出现频率的直方图。

import numpy as np
import matplotlib.pyplot as plt
from numpy import *
data = loadtxt('data.txt',dtype=int,usecols=(4,)) #loading 5th column of csv file into array named data. 
plt.hist(data) #plotting the column as histogram 

我得到了直方图,但我注意到如果我用“print”来输出hist(data),

hist=np.histogram(data)
print hist(data)

我得到的是:

(array([ 2323, 16338,  1587,   212,    26,    14,     3,     2,     2,     2]), 
array([  1. ,   2.8,   4.6,   6.4,   8.2,  10. ,  11.8,  13.6,  15.4,
    17.2,  19. ]))

这里第二个数组代表值,第一个数组代表出现的次数。

在我的数据集中,所有的值都是整数,为什么第二个数组会有浮点数呢?我该如何获取整数的频率呢?

更新:

这个解决了我的问题,谢谢Lev的回复。

plt.hist(data, bins=np.arange(data.min(), data.max()+1))

为了避免创建一个新问题,我该如何让每个整数的柱子“居中”呢?比如,我想让整数3的柱子占据2.5到3.5之间的空间,而不是在3和4之间。

histogram

3 个回答

3

(虽然来得有点晚,但我想补充一个关于 seaborn 的实现)

上面问题的 Seaborn 实现:

在写这段内容时,seaborn.__version__ = 0.9.0

加载所需的库,并设置一些模拟数据。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

data = np.array([3]*10 + [5]*20 + [7]*5 + [9]*27 + [11]*2)

使用 seaborn.distplot 绘制数据:

使用指定的区间,这些区间是根据上面的问题计算出来的。

sns.distplot(data,bins=np.arange(data.min(), data.max()+1),kde=False,hist_kws={"align" : "left"})
plt.show()

尝试 numpy 内置的分箱方法

我使用了下面的 doane 分箱方法,它生成了整数区间,可能值得尝试一下 来自 numpy.histogram_bin_edges 的标准分箱方法,因为这就是 matplotlib.hist() 如何对数据进行分箱的方式。

sns.distplot(data,bins="doane",kde=False,hist_kws={"align" : "left"})
plt.show()

生成了下面的直方图:

在这里输入图片描述

4

你可以使用 itertools 里的 groupby,就像在如何计算列表中元素的频率?中所示的那样。

import numpy as np
from itertools import groupby
freq = {key:len(list(group)) for key, group in groupby(np.sort(data))}
23

如果你不指定要用什么样的区间,np.histogrampyplot.hist 会默认使用10个相等的区间。第一个区间的左边界是最小值,而最后一个区间的右边界是最大值。

这就是为什么区间的边界是浮点数的原因。你可以使用 bins 这个参数来选择其他的区间,比如:

plt.hist(data, bins=np.arange(data.min(), data.max()+1))

补充:将所有区间向左移动最简单的方法可能就是从所有区间的边界减去0.5:

plt.hist(data, bins=np.arange(data.min(), data.max()+1)-0.5)

还有一种方法可以达到相同的效果(如果有非整数的话,这种方法就不一样了):

plt.hist(data, bins=np.arange(data.min(), data.max()+1), align='left')

撰写回答