文章選自towardsdatascience,做者:George Seif,機器之心編譯。數據可視化是數據科學家工做的重要部分。在項目的早期階段,咱們一般須要進行探索性數據分析來得到對數據的洞察。經過數據可視化可讓該過程變得更加清晰易懂,尤爲是在處理大規模、高維度數據集時。在本文中,咱們介紹了最基本的 5 種數據可視化圖表,在展現了它們的優劣點後,咱們還提供了繪製對應圖表的 Matplotlib 代碼。
Matplotlib 是一個很流行的 Python 庫,能夠幫助你快速方便地構建數據可視化圖表。然而,每次啓動一個新項目時都須要從新設置數據、參數、圖形和繪圖方式是很是枯燥無聊的。本文將介紹 5 種數據可視化方法,並用 Python 和 Matplotlib 寫一些快速易用的可視化函數。下圖展現了選擇正確可視化方法的導向圖。
python
因爲能夠直接看到原始數據的分佈,散點圖對於展現兩個變量之間的關係很是有用。你還能夠經過用顏色將數據分組來觀察不一樣組數據之間的關係,以下圖所示。你還能夠添加另外一個參數,如數據點的半徑來編碼第三個變量,從而可視化三個變量之間的關係,以下方第二個圖所示。bash
接下來是代碼部分。咱們首先將 Matplotlib 的 pyplot 導入爲 plt,並調用函數 plt.subplots() 來建立新的圖。咱們將 x 軸和 y 軸的數據傳遞給該函數,而後將其傳遞給 ax.scatter() 來畫出散點圖。咱們還能夠設置點半徑、點顏色和 alpha 透明度,甚至將 y 軸設置爲對數尺寸,最後爲圖指定標題和座標軸標籤。服務器
import matplotlib.pyplot as plt
import numpy as np
def scatterplot(x_data, y_data, x_label="", y_label="", title="", color = "r", yscale_log=False):
# Create the plot object
_, ax = plt.subplots()
# Plot the data, set the size (s), color and transparency (alpha)
# of the points
ax.scatter(x_data, y_data, s = 10, color = color, alpha = 0.75)
if yscale_log == True:
ax.set_yscale('log')
# Label the axes and provide a title
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
複製代碼
當一個變量隨另外一個變量的變化而變化的幅度很大時,即它們有很高的協方差時,線圖很是好用。以下圖所示,咱們能夠看到,全部專業課程的相對百分數隨年代的變化的幅度都很大。用散點圖來畫這些數據將變得很是雜亂無章,而難以看清其本質。線圖很是適合這種狀況,由於它能夠快速地總結出兩個變量的協方差。在這裏,咱們也能夠用顏色將數據分組。app
如下是線圖的實現代碼,和散點圖的代碼結構很類似,只在變量設置上有少量變化。ide
def lineplot(x_data, y_data, x_label="", y_label="", title=""):
# Create the plot object
_, ax = plt.subplots()
# Plot the best fit line, set the linewidth (lw), color and
# transparency (alpha) of the line
ax.plot(x_data, y_data, lw = 2, color = '#539caf', alpha = 1)
# Label the axes and provide a title
ax.set_title(title)
ax.set_xlabel(x_label)
ax.set_ylabel(y_label)
複製代碼
直方圖對於觀察或真正瞭解數據點的分佈十分有用。如下爲咱們繪製的頻率與 IQ 的直方圖,咱們能夠直觀地瞭解分佈的集中度(方差)與中位數,也能夠了解到該分佈的形狀近似服從於高斯分佈。使用這種柱形(而不是散點圖等)能夠清楚地可視化每個箱體(X 軸的一個等距區間)間頻率的變化。使用箱體(離散化)確實能幫助咱們觀察到「更完整的圖像」,由於使用全部數據點而不採用離散化會觀察不到近似的數據分佈,可能在可視化中存在許多噪聲,使其只能近似地而不能描述真正的數據分佈。函數
下面展現了 Matplotlib 中繪製直方圖的代碼。這裏有兩個步驟須要注意,首先,n_bins 參數控制直方圖的箱體數量或離散化程度。更多的箱體或柱體能給咱們提供更多的信息,但一樣也會引入噪聲並使咱們觀察到的全局分佈圖像變得不太規則。而更少的箱體將給咱們更多的全局信息,咱們能夠在缺乏細節信息的狀況下觀察到總體分佈的形狀。其次,cumulative 參數是一個布爾值,它容許咱們選擇直方圖是否是累積的,即選擇機率密度函數(PDF)或累積密度函數(CDF)。ui
def histogram(data, n_bins, cumulative=False, x_label = "", y_label = "", title = ""):
_, ax = plt.subplots()
ax.hist(data, n_bins = n_bins, cumulative = cumulative, color = '#539caf')
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
複製代碼
若是咱們但願比較數據中兩個變量的分佈,有人可能會認爲咱們須要製做兩個獨立的直方圖,並將它們拼接在一塊兒而進行比較。但實際上 Matplotlib 有更好的方法,咱們能夠用不一樣的透明度疊加多個直方圖。以下圖所示,均勻分佈設置透明度爲 0.5,所以咱們就能將其疊加在高斯分佈上,這容許用戶在同一圖表上繪製並比較兩個分佈。
編碼
在疊加直方圖的代碼中,咱們須要注意幾個問題。首先,咱們設定的水平區間要同時知足兩個變量的分佈。根據水平區間的範圍和箱體數,咱們能夠計算每一個箱體的寬度。其次,咱們在一個圖表上繪製兩個直方圖,須要保證一個直方圖存在更大的透明度。spa
# Overlay 2 histograms to compare them
def overlaid_histogram(data1, data2, n_bins = 0, data1_name="", data1_color="#539caf", data2_name="", data2_color="#7663b0", x_label="", y_label="", title=""):
# Set the bounds for the bins so that the two distributions are fairly compared
max_nbins = 10
data_range = [min(min(data1), min(data2)), max(max(data1), max(data2))]
binwidth = (data_range[1] - data_range[0]) / max_nbins
if n_bins == 0
bins = np.arange(data_range[0], data_range[1] + binwidth, binwidth)
else:
bins = n_bins
# Create the plot
_, ax = plt.subplots()
ax.hist(data1, bins = bins, color = data1_color, alpha = 1, label = data1_name)
ax.hist(data2, bins = bins, color = data2_color, alpha = 0.75, label = data2_name)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'best')
複製代碼
當對類別數不多(<10)的分類數據進行可視化時,條形圖是最有效的。當類別數太多時,條形圖將變得很雜亂,難以理解。你能夠基於條形的數量觀察不一樣類別之間的區別,不一樣的類別能夠輕易地分離以及用顏色分組。咱們將介紹三種類型的條形圖:常規、分組和堆疊條形圖。3d
常規條形圖如圖 1 所示。在 barplot() 函數中,x_data 表示 x 軸上的不一樣類別,y_data 表示 y 軸上的條形高度。偏差條形是額外添加在每一個條形中心上的線,可用於表示標準差。
分組條形圖容許咱們比較多個類別變量。以下圖所示,咱們第一個變量會隨不一樣的分組(G一、G2 等)而變化,咱們在每一組上比較不一樣的性別。正如代碼所示,y_data_list 變量如今其實是一組列表,其中每一個子列表表明了一個不一樣的組。而後咱們循環地遍歷每個組,並在 X 軸上繪製柱體和對應的值,每個分組的不一樣類別將使用不一樣的顏色表示。
堆疊條形圖很是適合於可視化不一樣變量的分類構成。在下面的堆疊條形圖中,咱們比較了工做日的服務器負載。經過使用不一樣顏色的方塊堆疊在同一條形圖上,咱們能夠輕鬆查看並瞭解哪臺服務器天天的工做效率最高,和同一服務器在不一樣天數的負載大小。繪製該圖的代碼與分組條形圖有相同的風格,咱們循環地遍歷每一組,但咱們此次在舊的柱體之上而不是旁邊繪製新的柱體。
def barplot(x_data, y_data, error_data, x_label="", y_label="", title=""):
_, ax = plt.subplots()
# Draw bars, position them in the center of the tick mark on the x-axis
ax.bar(x_data, y_data, color = '#539caf', align = 'center')
# Draw error bars to show standard deviation, set ls to 'none'
# to remove line between points
ax.errorbar(x_data, y_data, yerr = error_data, color = '#297083', ls = 'none', lw = 2, capthick = 2)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
def stackedbarplot(x_data, y_data_list, colors, y_data_names="", x_label="", y_label="", title=""):
_, ax = plt.subplots()
# Draw bars, one category at a time
for i in range(0, len(y_data_list)):
if i == 0:
ax.bar(x_data, y_data_list[i], color = colors[i], align = 'center', label = y_data_names[i])
else:
# For each category after the first, the bottom of the
# bar will be the top of the last category
ax.bar(x_data, y_data_list[i], color = colors[i], bottom = y_data_list[i - 1], align = 'center', label = y_data_names[i])
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right')
def groupedbarplot(x_data, y_data_list, colors, y_data_names="", x_label="", y_label="", title=""):
_, ax = plt.subplots()
# Total width for all bars at one x location
total_width = 0.8
# Width of each individual bar
ind_width = total_width / len(y_data_list)
# This centers each cluster of bars about the x tick mark
alteration = np.arange(-(total_width/2), total_width/2, ind_width)
# Draw bars, one category at a time
for i in range(0, len(y_data_list)):
# Move the bar to the right on the x-axis so it doesn't
# overlap with previously drawn ones
ax.bar(x_data + alteration[i], y_data_list[i], color = colors[i], label = y_data_names[i], width = ind_width)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
ax.legend(loc = 'upper right')
複製代碼
上述的直方圖對於可視化變量分佈很是有用,但當咱們須要更多信息時,怎麼辦?咱們可能須要清晰地可視化標準差,也可能出現中位數和平均值差值很大的狀況(有不少異常值),所以須要更細緻的信息。還可能出現數據分佈很是不均勻的狀況等等。
箱線圖能夠給咱們以上須要的全部信息。實線箱的底部表示第一個四分位數,頂部表示第三個四分位數,箱內的線表示第二個四分位數(中位數)。虛線表示數據的分佈範圍。
因爲箱線圖是對單個變量的可視化,其設置很簡單。x_data 是變量的列表。Matplotlib 函數 boxplot() 爲 y_data 的每一列或 y_data 序列中的每一個向量繪製一個箱線圖,所以 x_data 中的每一個值對應 y_data 中的一列/一個向量。
def boxplot(x_data, y_data, base_color="#539caf", median_color="#297083", x_label="", y_label="", title=""):
_, ax = plt.subplots()
# Draw boxplots, specifying desired style
ax.boxplot(y_data
# patch_artist must be True to control box fill
, patch_artist = True
# Properties of median line
, medianprops = {'color': median_color}
# Properties of box
, boxprops = {'color': base_color, 'facecolor': base_color}
# Properties of whiskers
, whiskerprops = {'color': base_color}
# Properties of whisker caps
, capprops = {'color': base_color})
# By default, the tick label starts at 1 and increments by 1 for
# each box drawn. This sets the labels to the ones we want
ax.set_xticklabels(x_data)
ax.set_ylabel(y_label)
ax.set_xlabel(x_label)
ax.set_title(title)
複製代碼
本文介紹了 5 種方便易用的 Matplotlib 數據可視化方法。將可視化過程抽象爲函數能夠令代碼變得易讀和易用。Hope you enjoyed!
原文地址: