91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在Python中實現一個histogram直方圖功能

發布時間:2021-02-25 15:46:18 來源:億速云 閱讀:355 作者:戴恩恩 欄目:開發技術

本文章向大家介紹如何在Python中實現一個histogram直方圖功能的基本知識點總結和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下。

Python主要用來做什么

Python主要應用于:1、Web開發;2、數據科學研究;3、網絡爬蟲;4、嵌入式應用開發;5、游戲開發;6、桌面應用開發。

純Python實現histogram

當準備用純Python來繪制直方圖的時候,最簡單的想法就是將每個值出現的次數以報告形式展示。這種情況下,使用 字典 來完成這個任務是非常合適的,我們看看下面代碼是如何實現的。

>>> a = (0, 1, 1, 1, 2, 3, 7, 7, 23)

>>> def count_elements(seq) -> dict:
... """Tally elements from `seq`."""
... hist = {}
... for i in seq:
...  hist[i] = hist.get(i, 0) + 1
... return hist

>>> counted = count_elements(a)
>>> counted
{0: 1, 1: 3, 2: 1, 3: 1, 7: 2, 23: 1}

我們看到,count_elements() 返回了一個字典,字典里出現的鍵為目標列表里面的所有唯一數值,而值為所有數值出現的頻率次數。hist[i] = hist.get(i, 0) + 1 實現了每個數值次數的累積,每次加一。

實際上,這個功能可以用一個Python的標準庫 collection.Counter 類來完成,它兼容Pyhont 字典并覆蓋了字典的 .update() 方法。

>>> from collections import Counter

>>> recounted = Counter(a)
>>> recounted
Counter({0: 1, 1: 3, 3: 1, 2: 1, 7: 2, 23: 1})

可以看到這個方法和前面我們自己實現的方法結果是一樣的,我們也可以通過 collection.Counter 來檢驗兩種方法得到的結果是否相等。

>>> recounted.items() == counted.items()
True

我們利用上面的函數重新再造一個輪子 ASCII_histogram,并最終通過Python的輸出格式format來實現直方圖的展示,代碼如下:

def ascii_histogram(seq) -> None:
 """A horizontal frequency-table/histogram plot."""
 counted = count_elements(seq)
 for k in sorted(counted):
 print('{0:5d} {1}'.format(k, '+' * counted[k]))

這個函數按照數值大小順序進行繪圖,數值出現次數用 (+) 符號表示。在字典上調用 sorted() 將會返回一個按鍵順序排列的列表,然后就可以獲取相應的次數 counted[k] 

>>> import random
>>> random.seed(1)

>>> vals = [1, 3, 4, 6, 8, 9, 10]
>>> # `vals` 里面的數字將會出現5到15次
>>> freq = (random.randint(5, 15) for _ in vals)

>>> data = []
>>> for f, v in zip(freq, vals):
... data.extend([v] * f)

>>> ascii_histogram(data)
 1 +++++++
 3 ++++++++++++++
 4 ++++++
 6 +++++++++
 8 ++++++
 9 ++++++++++++
 10 ++++++++++++

這個代碼中,vals內的數值是不重復的,并且每個數值出現的頻數是由我們自己定義的,在5和15之間隨機選擇。然后運用我們上面封裝的函數,就得到了純Python版本的直方圖展示。

總結:純python實現頻數表(非標準直方圖),可直接使用collection.Counter方法實現。

使用Numpy實現histogram

以上是使用純Python來完成的簡單直方圖,但是從數學意義上來看,直方圖是分箱到頻數的一種映射,它可以用來估計變量的概率密度函數的。而上面純Python實現版本只是單純的頻數統計,不是真正意義上的直方圖。

因此,我們從上面實現的簡單直方圖繼續往下進行升級。一個真正的直方圖首先應該是將變量分區域(箱)的,也就是分成不同的區間范圍,然后對每個區間內的觀測值數量進行計數。恰巧,Numpy的直方圖方法就可以做到這點,不僅僅如此,它也是后面將要提到的matplotlib和pandas使用的基礎。

舉個例子,來看一組從拉普拉斯分布上提取出來的浮點型樣本數據。這個分布比標準正態分布擁有更寬的尾部,并有兩個描述參數(location和scale):

>>> import numpy as np

>>> np.random.seed(444)
>>> np.set_printoptions(precision=3)

>>> d = np.random.laplace(loc=15, scale=3, size=500)
>>> d[:5]
array([18.406, 18.087, 16.004, 16.221, 7.358])

由于這是一個連續型的分布,對于每個單獨的浮點值(即所有的無數個小數位置)并不能做很好的標簽(因為點實在太多了)。但是,你可以將數據做 分箱 處理,然后統計每個箱內觀察值的數量,這就是真正的直方圖所要做的工作。

下面我們看看是如何用Numpy來實現直方圖頻數統計的。

>>> hist, bin_edges = np.histogram(d)

>>> hist
array([ 1, 0, 3, 4, 4, 10, 13, 9, 2, 4])

>>> bin_edges
array([ 3.217, 5.199, 7.181, 9.163, 11.145, 13.127, 15.109, 17.091,
 19.073, 21.055, 23.037])

這個結果可能不是很直觀。來說一下,np.histogram() 默認地使用10個相同大小的區間(箱),然后返回一個元組(頻數,分箱的邊界),如上所示。要注意的是:這個邊界的數量是要比分箱數多一個的,可以簡單通過下面代碼證實。

>>> hist.size, bin_edges.size
(10, 11)

那問題來了,Numpy到底是如何進行分箱的呢?只是通過簡單的 np.histogram() 就可以完成了,但具體是如何實現的我們仍然全然不知。下面讓我們來將 np.histogram() 的內部進行解剖,看看到底是如何實現的(以最前面提到的a列表為例)。

>>> # 取a的最小值和最大值
>>> first_edge, last_edge = a.min(), a.max()

>>> n_equal_bins = 10 # NumPy得默認設置,10個分箱
>>> bin_edges = np.linspace(start=first_edge, stop=last_edge,
...    num=n_equal_bins + 1, endpoint=True)
...
>>> bin_edges
array([ 0. , 2.3, 4.6, 6.9, 9.2, 11.5, 13.8, 16.1, 18.4, 20.7, 23. ])

解釋一下:首先獲取a列表的最小值和最大值,然后設置默認的分箱數量,最后使用Numpy的 linspace 方法進行數據段分割。分箱區間的結果也正好與實際吻合,0到23均等分為10份,23/10,那么每份寬度為2.3。

除了np.histogram之外,還存在其它兩種可以達到同樣功能的方法:np.bincount() np.searchsorted() ,下面看看代碼以及比較結果。

>>> bcounts = np.bincount(a)
>>> hist, _ = np.histogram(a, range=(0, a.max()), bins=a.max() + 1)

>>> np.array_equal(hist, bcounts)
True

>>> # Reproducing `collections.Counter`
>>> dict(zip(np.unique(a), bcounts[bcounts.nonzero()]))
{0: 1, 1: 3, 2: 1, 3: 1, 7: 2, 23: 1}

總結:通過Numpy實現直方圖,可直接使用np.histogram()或者np.bincount()

使用Matplotlib和Pandas可視化Histogram

從上面的學習,我們看到了如何使用Python的基礎工具搭建一個直方圖,下面我們來看看如何使用更為強大的Python庫包來完成直方圖。Matplotlib基于Numpy的histogram進行了多樣化的封裝并提供了更加完善的可視化功能。

import matplotlib.pyplot as plt

# matplotlib.axes.Axes.hist() 方法的接口
n, bins, patches = plt.hist(x=d, bins='auto', color='#0504aa',
    alpha=0.7, rwidth=0.85)
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.title('My Very Own Histogram')
plt.text(23, 45, r'$\mu=15, b=3$')
maxfreq = n.max()
# 設置y軸的上限
plt.ylim(ymax=np.ceil(maxfreq / 10) * 10 if maxfreq % 10 else maxfreq + 10)

如何在Python中實現一個histogram直方圖功能

之前我們的做法是,在x軸上定義了分箱邊界,y軸是相對應的頻數,不難發現我們都是手動定義了分箱的數目。但是在以上的高級方法中,我們可以通過設置 bins='auto' 自動在寫好的兩個算法中擇優選擇并最終算出最適合的分箱數。這里,算法的目的就是選擇出一個合適的區間(箱)寬度,并生成一個最能代表數據的直方圖來。

如果使用Python的科學計算工具實現,那么可以使用Pandas的 Series.histogram() ,并通過 matplotlib.pyplot.hist() 來繪制輸入Series的直方圖,如下代碼所示。

import pandas as pd

size, scale = 1000, 10
commutes = pd.Series(np.random.gamma(scale, size=size) ** 1.5)

commutes.plot.hist(grid=True, bins=20, rwidth=0.9,
     color='#607c8e')
plt.title('Commute Times for 1,000 Commuters')
plt.xlabel('Counts')
plt.ylabel('Commute Time')
plt.grid(axis='y', alpha=0.75)

如何在Python中實現一個histogram直方圖功能

pandas.DataFrame.histogram() 的用法與Series是一樣的,但生成的是對DataFrame數據中的每一列的直方圖。

總結:通過pandas實現直方圖,可使用Seris.plot.hist() DataFrame.plot.hist() ,matplotlib實現直方圖可以用matplotlib.pyplot.hist()

繪制核密度估計(KDE)

KDE(Kernel density estimation)是核密度估計的意思,它用來估計隨機變量的概率密度函數,可以將數據變得更平緩。

使用Pandas庫的話,你可以使用 plot.kde() 創建一個核密度的繪圖,plot.kde() 對于 Series和DataFrame數據結構都適用。但是首先,我們先生成兩個不同的數據樣本作為比較(兩個正太分布的樣本):

>>> # 兩個正太分布的樣本
>>> means = 10, 20
>>> stdevs = 4, 2
>>> dist = pd.DataFrame(
...  np.random.normal(loc=means, scale=stdevs, size=(1000, 2)),
...  columns=['a', 'b'])
>>> dist.agg(['min', 'max', 'mean', 'std']).round(decimals=2)
   a  b
min -1.57 12.46
max 25.32 26.44
mean 10.12 19.94
std 3.94 1.94

以上看到,我們生成了兩組正態分布樣本,并且通過一些描述性統計參數對兩組數據進行了簡單的對比。現在,我們可以在同一個Matplotlib軸上繪制每個直方圖以及對應的kde,使用pandas的plot.kde()的好處就是:它會自動的將所有列的直方圖和kde都顯示出來,用起來非常方便,具體代碼如下:

fig, ax = plt.subplots()
dist.plot.kde(ax=ax, legend=False, title='Histogram: A vs. B')
dist.plot.hist(density=True, ax=ax)
ax.set_ylabel('Probability')
ax.grid(axis='y')
ax.set_facecolor('#d8dcd6')

如何在Python中實現一個histogram直方圖功能

總結:通過pandas實現kde圖,可使用Seris.plot.kde() DataFrame.plot.kde()

使用Seaborn的完美替代

一個更高級可視化工具就是Seaborn,它是在matplotlib的基礎上進一步封裝的強大工具。對于直方圖而言,Seaborn有 distplot() 方法,可以將單變量分布的直方圖和kde同時繪制出來,而且使用及其方便,下面是實現代碼(以上面生成的d為例):

import seaborn as sns

sns.set_style('darkgrid')
sns.distplot(d)

如何在Python中實現一個histogram直方圖功能

distplot方法默認的會繪制kde,并且該方法提供了 fit 參數,可以根據數據的實際情況自行選擇一個特殊的分布來對應。

sns.distplot(d, fit=stats.laplace, kde=False)

如何在Python中實現一個histogram直方圖功能

注意這兩個圖微小的區別。第一種情況你是在估計一個未知的概率密度函數(PDF),而第二種情況是你是知道分布的,并想知道哪些參數可以更好的描述數據。

總結:通過seaborn實現直方圖,可使用seaborn.distplot() ,seaborn也有單獨的kde繪圖seaborn.kde()

在Pandas中的其它工具

除了繪圖工具外,pandas也提供了一個方便的.value_counts() 方法,用來計算一個非空值的直方圖,并將之轉變成一個pandas的series結構,示例如下:

>>> import pandas as pd

>>> data = np.random.choice(np.arange(10), size=10000,
...       p=np.linspace(1, 11, 10) / 60)
>>> s = pd.Series(data)

>>> s.value_counts()
9 1831
8 1624
7 1423
6 1323
5 1089
4  888
3  770
2  535
1  347
0  170
dtype: int64

>>> s.value_counts(normalize=True).head()
9 0.1831
8 0.1624
7 0.1423
6 0.1323
5 0.1089
dtype: float64

此外,pandas.cut() 也同樣是一個方便的方法,用來將數據進行強制的分箱。比如說,我們有一些人的年齡數據,并想把這些數據按年齡段進行分類,示例如下:

>>> ages = pd.Series(
...  [1, 1, 3, 5, 8, 10, 12, 15, 18, 18, 19, 20, 25, 30, 40, 51, 52])
>>> bins = (0, 10, 13, 18, 21, np.inf) # 邊界
>>> labels = ('child', 'preteen', 'teen', 'military_age', 'adult')
>>> groups = pd.cut(ages, bins=bins, labels=labels)

>>> groups.value_counts()
child   6
adult   5
teen   3
military_age 2
preteen   1
dtype: int64

>>> pd.concat((ages, groups), axis=1).rename(columns={0: 'age', 1: 'group'})
 age   group
0  1   child
1  1   child
2  3   child
3  5   child
4  8   child
5 10   child
6 12  preteen
7 15   teen
8 18   teen
9 18   teen
10 19 military_age
11 20 military_age
12 25   adult
13 30   adult
14 40   adult
15 51   adult
16 52   adult

除了使用方便外,更加好的是這些操作最后都會使用 Cython 代碼來完成,在運行速度的效果上也是非常快的。

總結:其它實現直方圖的方法,可使用.value_counts()pandas.cut()

該使用哪個方法?

至此,我們了解了很多種方法來實現一個直方圖。但是它們各自有什么有缺點呢?該如何對它們進行選擇呢?當然,一個方法解決所有問題是不存在的,我們也需要根據實際情況而考慮如何選擇,下面是對一些情況下使用方法的一個推薦,僅供參考。

如何在Python中實現一個histogram直方圖功能

以上就是小編為大家帶來的如何在Python中實現一個histogram直方圖功能的全部內容了,希望大家多多支持億速云!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

天台县| 昌黎县| 滦南县| 葫芦岛市| 南京市| 通榆县| 湘乡市| 朝阳市| 三河市| 宁远县| 托克托县| 镶黄旗| 福建省| 卢龙县| 安远县| 修文县| 新郑市| 揭阳市| 琼海市| 呈贡县| 循化| 光山县| 仲巴县| 新余市| 上蔡县| 福州市| 阿克陶县| 兴隆县| 秀山| 彩票| 海原县| 吉木乃县| 墨脱县| 福鼎市| 远安县| 平顺县| 邓州市| 襄汾县| 澄城县| 霍林郭勒市| 瑞丽市|