導(dǎo)讀:相比于科學(xué),數(shù)據(jù)分析更像是一門藝術(shù)。創(chuàng)建樣式優(yōu)美的數(shù)據(jù)可視化是這個藝術(shù)中不可缺少的部分。然而,某些人認(rèn)為優(yōu)美的,也會有人覺得難以接受。和藝術(shù)類似,隨著數(shù)據(jù)分析的快速演變,人們的觀念和品味也一直在變化。但是總的來說沒有人是絕對正確和錯誤的。
作為一個數(shù)據(jù)藝術(shù)家以及有經(jīng)驗的Python程序員,我們可以從matplotlib、Seaborn、Bokeh和ggplot這些庫里面選擇一些來使用。
作者:伊凡·伊德里斯(Ivan Idris)
如需轉(zhuǎn)載請聯(lián)系大數(shù)據(jù)(ID:hzdashuju)
01 圖形化安斯庫姆四重奏
安斯庫姆四重奏(Anscombe's Quartet)是一個經(jīng)典案例,它可以說明為什么可視化是很重要的。四重奏包含了四組統(tǒng)計特性一致的數(shù)據(jù)。每個數(shù)據(jù)集有一些x值以及相對應(yīng)的y值,我們將在一個IPython Notebook中列出這些指標(biāo)。如果你繪制出這些數(shù)據(jù)集,你將發(fā)現(xiàn)這些圖表截然不同。
操作步驟
在本節(jié)你需要執(zhí)行如下操作:
(1)由如下導(dǎo)入開始:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl
from dautil import report
from dautil import plotting
import numpy as np
from tabulate import tabulate
(2)定義以下函數(shù)來計算某一數(shù)據(jù)集中x和y的均值和方差、相關(guān)系數(shù),以及斜率和每個數(shù)據(jù)集的線性擬合的截距:
def aggregate():
df = sns.load_dataset("anscombe")
agg = df.groupby('dataset')\
.agg([np.mean, np.var])\
.transpose()
groups = df.groupby('dataset')
corr = [g.corr()['x'][1] for _, g in groups]
builder = report.DFBuilder(agg.columns)
builder.row(corr)
fits = [np.polyfit(g['x'], g['y'], 1) for _, g in groups]
builder.row([f[0] for f in fits])
builder.row([f[1] for f in fits])
bottom = builder.build(['corr', 'slope', 'intercept'])
return df, pd.concat((agg, bottom))
(3)下面這個函數(shù)返回一個字符串,這個字符串有一部分是Markdown,有一部分是重組的文字,有一部分是HTML,這主要是因為原生的Markdown不支持圖表:
def generate(table):
writer = report.RSTWriter()
writer.h1('Anscombe Statistics')
writer.add(tabulate(table, tablefmt='html', floatfmt='.3f'))
return writer.rst
(4)繪制數(shù)據(jù)并相應(yīng)地與Seaborn的lmplot()函數(shù)線性擬合:
def plot(df):
sns.set(style="ticks")
g = sns.lmplot(x="x", y="y", col="dataset",
hue="dataset", data=df,
col_wrap=2, ci=None, palette="muted", size=4,
scatter_kws={"s": 50, "alpha": 1})
plotting.embellish(g.fig.axes)
(5)展示一個統(tǒng)計數(shù)據(jù)的表格如下:
df, table = aggregate()
from IPython.display import display_markdown
display_markdown(generate(table), raw=True)
下表中顯示每個數(shù)據(jù)集的幾乎相同的統(tǒng)計數(shù)據(jù)(我修改了IPython配置文件里的 custom.css,所以下表是有顏色的):
(6)以下幾行代碼繪制了數(shù)據(jù)集:
%matplotlib inline
plot(df)
請參見以下截圖了解最終結(jié)果:
02 選擇Seaborn的調(diào)色板
Seaborn的調(diào)色板和matplotlib的顏色表類似。色彩可以幫助你發(fā)現(xiàn)數(shù)據(jù)中的模式,也是重要的可視化組成部分。Seaborn有很豐富的調(diào)色板,在這個示例中會將其可視化。
操作步驟
(1)導(dǎo)入部分如下:
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from dautil import plotting
(2)使用以下函數(shù)幫助繪制調(diào)色板:
def plot_palette(ax, plotter, pal, i, label, ncol=1):
n = len(pal)
x = np.linspace(0.0, 1.0, n)
y = np.arange(n) + i*n
ax.scatter(x, y, c=x,
cmap=mpl.colors.ListedColormap(list(pal)),
s=200)
plotter.plot(x,y,label=label)
handles, labels = ax.get_legend_handles_labels()
ax.legend(loc='best', ncol=ncol, fontsize=18)
(3)分類調(diào)色板(categorical palette)對于分類數(shù)據(jù)很有用,例如性別、血型等。以下函數(shù)可以繪制一些Seaborn的分類調(diào)色板:
def plot_categorical_palettes(ax):
palettes = ['deep', 'muted', 'pastel', 'bright', 'dark','colorblind']
plotter = plotting.CyclePlotter(ax)
ax.set_title('Categorical Palettes')
for i, p in enumerate(palettes):
pal = sns.color_palette(p)
plot_palette(ax, plotter, pal, i, p, 4)
(4)圓形色彩系統(tǒng)(circular color system)通常用HLS(色度亮度飽和度,Hue Lightness Saturation)來取代RGB(紅綠藍(lán)Red Gree Blue)顏色空間。如果你有很多分類這將會很有用。以下函數(shù)可以使用HLS系統(tǒng)繪制調(diào)色板。
def plot_circular_palettes(ax):
ax.set_title('Circular Palettes')
plotter = plotting.CyclePlotter(ax)
pal = sns.color_palette("hls", 6)
plot_palette(ax, plotter, pal, 0, 'hls')
sns.hls_palette(6, l=.3, s=.8)
plot_palette(ax, plotter, pal, 1, 'hls l=.3 s=.8')
pal = sns.color_palette("husl", 6)
plot_palette(ax, plotter, pal, 2, 'husl')
sns.husl_palette(6, l=.3, s=.8)
plot_palette(ax, plotter, pal, 3, 'husl l=.3 s=.8')
(5)Seaborn也有基于在線的ColorBrewer工具的調(diào)色板(http://colorbrewer2.org/)。用以下函數(shù)繪制出來:
def plot_brewer_palettes(ax):
ax.set_title('Brewer Palettes')
plotter = plotting.CyclePlotter(ax)
pal = sns.color_palette("Paired")
plot_palette(ax, plotter, pal, 0, 'Paired')
pal = sns.color_palette("Set2", 6)
plot_palette(ax, plotter, pal, 1, 'Set2')
(6)連續(xù)調(diào)色板(sequential palettes)對于數(shù)據(jù)范圍很廣的數(shù)據(jù)來說很有用,比如說有數(shù)量級差異的數(shù)據(jù)。用以下函數(shù)繪制出來:
def plot_sequential_palettes(ax):
ax.set_title('Sequential Palettes')
plotter = plotting.CyclePlotter(ax)
pal = sns.color_palette("Blues")
plot_palette(ax, plotter, pal, 0, 'Blues')
pal = sns.color_palette("BuGn_r")
plot_palette(ax, plotter, pal, 1, 'BuGn_r')
pal = sns.color_palette("GnBu_d")
plot_palette(ax, plotter, pal, 2, 'GnBu_d')
pal = sns.color_palette("cubehelix", 6)
plot_palette(ax, plotter, pal, 3, 'cubehelix')
(7)以下幾行代碼調(diào)用了我們之前定義的函數(shù):
%matplotlib inline
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
plot_categorical_palettes(axes[0][0])
plot_circular_palettes(axes[0][1])
plot_brewer_palettes(axes[1][0])
plot_sequential_palettes(axes[1][1])
plotting.hide_axes(axes)
plt.tight_layout()
請參見以下截圖了解最終結(jié)果:
03 選擇matplotlib的顏色表
matplotlib的顏色表最近受到了很多批評,因為它們可能會誤導(dǎo)用戶,但是在我看來大多數(shù)的顏色表還是不錯的。默認(rèn)的顏色表在matplotlib 2.0中有一些改進(jìn),可以在這里查看:
http://matplotlib.org/style_changes.html
當(dāng)然,有些matplotlib的顏色表不支持一些不錯的參數(shù),比如說jet。在藝術(shù)中,就像數(shù)據(jù)分析中一樣,幾乎沒有什么東西是絕對正確的,所以這里就交給讀者去判斷。
實際上,我覺得考慮如何解決印刷出版物以及各種各樣的色盲問題是很重要的。在這個示例中我將用色條來可視化相對安全的顏色表。這里使用到的是matplotlib眾多顏色表中的很小一部分。
操作步驟
(1)導(dǎo)入部分如下:
import matplotlib.pyplot as plt
import matplotlib as mpl
from dautil import plotting
(2)通過以下代碼畫出數(shù)據(jù)集:
fig, axes = plt.subplots(4, 4)
cmaps = ['autumn', 'spring', 'summer', 'winter',
'Reds', 'Blues', 'Greens', 'Purples',
'Oranges', 'pink', 'Greys', 'gray',
'binary', 'bone', 'hot', 'cool']
for ax, cm in zip(axes.ravel(), cmaps):
cmap = plt.cm.get_cmap(cm)
cb = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
orientation='horizontal')
cb.set_label(cm)
ax.xaxis.set_ticklabels([])
plt.tight_layout()
plt.show()
請參見以下截圖了解最終結(jié)果:
04 與IPython Notebook部件交互
簡單來說,這些部件可以讓你像在HTML表單里一樣選擇一些值,這包括滑塊、下拉框、選擇框等。正如你會讀到的,這些部件非常方便將我們在第1章中提及的天氣數(shù)據(jù)可視化。
操作步驟
(1)導(dǎo)入部分如下:
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.html.widgets import interact
from dautil import data
from dautil import ts
(2)加載數(shù)據(jù)同時請求內(nèi)聯(lián)圖:
%matplotlib inline
df = data.Weather.load()
(3)定義以下函數(shù),這個函數(shù)會顯示氣泡圖:
def plot_data(x='TEMP', y='RAIN', z='WIND_SPEED', f='A', size=10,cmap='Blues'):
dfx = df[x].resample(f)
dfy = df[y].resample(f).mean()
dfz = df[z].resample(f).mean()
bubbles = (dfz - dfz.min())/(dfz.max() - dfz.min())
years = dfz.index.year
sc = plt.scatter(dfx, dfy, s= size * bubbles + 9, c = years,
cmap=cmap, label=data.Weather.get_header(z),
alpha=0.5)
plt.colorbar(sc, label='Year')
freqs = {'A': 'Annual', 'M': 'Monthly', 'D': 'Daily'}
plt.title(freqs[f] + ' Averages')
plt.xlabel(data.Weather.get_header(x))
plt.ylabel(data.Weather.get_header(y))
plt.legend(loc='best')
(4)通過以下代碼調(diào)用我們剛剛定義的函數(shù):
vars = df.columns.tolist()
freqs = ('A', 'M', 'D')
cmaps = [cmap for cmap in plt.cm.datad if not cmap.endswith("_r")]
cmaps.sort()
interact(plot_data, x=vars, y=vars, z=vars, f=freqs,size=(100,700), cmap=cmaps)
(5)本示例需要上手操作一下來理解它的工作原理,下面是一個樣例氣泡圖:
(6)定義另一個函數(shù)(和第(2)步中的程序同名,注釋掉前一個),這個函數(shù)里我們將數(shù)據(jù)按照日或月進(jìn)行分組:
def plot_data(x='TEMP', y='RAIN', z='WIND_SPEED',
groupby='ts.groupby_yday',
size=10, cmap='Blues'):
if groupby == 'ts.groupby_yday':
groupby = ts.groupby_yday
elif groupby == 'ts.groupby_month':
groupby = ts.groupby_month
else:
raise AssertionError('Unknown groupby ' + groupby)
dfx = groupby(df[x]).mean()
dfy = groupby(df[y]).mean()
dfz = groupby(df[z]).mean()
bubbles = (dfz - dfz.min())/(dfz.max() - dfz.min())
colors = dfx.index.values
sc = plt.scatter(dfx, dfy, s= size * bubbles + 9,
c = colors,cmap=cmap,
label=data.Weather.get_header(z), alpha=0.5)
plt.colorbar(sc, label='Day of Year')
by_dict = {ts.groupby_yday: 'Day of Year', ts.groupby_month: 'Month'}
plt.title('Grouped by ' + by_dict[groupby])
plt.xlabel(data.Weather.get_header(x))
plt.ylabel(data.Weather.get_header(y))
plt.legend(loc='best')
(7)用這段代碼調(diào)用上述函數(shù):
groupbys = ('ts.groupby_yday', 'ts.groupby_month')
interact(plot_data, x=vars, y=vars, z=vars, groupby=groupbys,
size=(100,700), cmap=cmaps)
請參見以下截圖了解最終結(jié)果:
我對這個圖的第一印象是溫度和風(fēng)速似乎是正相關(guān)的。
05 查看散點圖矩陣
如果你的數(shù)據(jù)集中變量不是很多,那么查看你數(shù)據(jù)所有的散點圖是個不錯的主意。通過調(diào)用Seaborn或者pandas的一個函數(shù)就可以做到。這些函數(shù)會展示一個矩陣的核密度估計圖或?qū)蔷€上的直方圖。
操作步驟
(1)導(dǎo)入部分如下:
import pandas as pd
from dautil import data
from dautil import ts
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib as mpl
(2)以下幾行代碼加載天氣數(shù)據(jù):
df = data.Weather.load()
df = ts.groupby_yday(df).mean()
df.columns = [data.Weather.get_header(c) for c in df.columns]
(3)用Seaborn的pairplot()函數(shù)繪制圖形,這個函數(shù)默認(rèn)繪制對角線上的直方圖:
%matplotlib inline
# Seaborn plotting, issues due to NaNs
sns.pairplot(df.fillna(0))
結(jié)果如下所示:
(4)通過pandas的scatter_matrix()函數(shù)生成一個類似的圖形,并請求對角線上的核密度估計圖:
sns.set({'figure.figsize': '16, 12'})
mpl.rcParams['axes.linewidth'] = 9
mpl.rcParams['lines.linewidth'] = 2
plots = pd.scatter_matrix(df, marker='o', diagonal='kde')
plt.show()
請參見以下截圖了解最終結(jié)果:
06 通過mpld3使用d3.js進(jìn)行可視化
d3.js是在2011年推出的一個JavaScript數(shù)據(jù)可視化庫,我們可以在IPython Notebook里面使用這個庫。我們將在一個普通matplotlib圖上添加一個懸浮工具提示。這里我們會使用mpld3包作為使用d3.js的橋梁。這個示例不需要任何JavaScript編程。
1. 準(zhǔn)備工作
通過以下命令安裝mpld3 0.2:
$ [sudo] pip install mpld3
2. 操作步驟
(1)由導(dǎo)入開始,并啟用mpld3:
%matplotlib inline
import matplotlib.pyplot as plt
import mpld3
mpld3.enable_notebook()
from mpld3 import plugins
import seaborn as sns
from dautil import data
from dautil import ts
(2)加載天氣數(shù)據(jù)并按照下面的方法將其繪制出來:
df = data.Weather.load()
df = df[['TEMP', 'WIND_SPEED']]
df = ts.groupby_yday(df).mean()
fig, ax = plt.subplots()
ax.set_title('Averages Grouped by Day of Year')
points = ax.scatter(df['TEMP'], df['WIND_SPEED'],
s=30, alpha=0.3)
ax.set_xlabel(data.Weather.get_header('TEMP'))
ax.set_ylabel(data.Weather.get_header('WIND_SPEED'))
labels = ["Day of year {0}".format(i) for i in range(366)]
tooltip = plugins.PointLabelTooltip(points, labels)
plugins.connect(fig, tooltip)
高亮顯示的那一行是工具欄。在下面的截圖中,我們可以看到“Day of year 31”文本來自這個工具欄:
如你所見,在這個圖形的底部,還有可以平移和縮放圖形的裝置。
07 創(chuàng)建熱圖
熱圖使用一組顏色在矩陣中可視化數(shù)據(jù)。最初,熱圖用于表示金融資產(chǎn)(如股票)的價格。Bokeh是一個Python包,可以在IPython Notebook中顯示熱圖,或者生成一個獨立的HTML文件。
1. 準(zhǔn)備工作
Anaconda自帶了Bokeh 0.9.1。Bokeh的安裝說明在:
http://bokeh.pydata.org/en/latest/docs/installation.html
2. 操作步驟
(1)導(dǎo)入部分如下:
from collections import OrderedDict
from dautil import data
from dautil import ts
from dautil import plotting
import numpy as np
import bokeh.plotting as bkh_plt
from bokeh.models import HoverTool
(2)下面的函數(shù)加載了溫度數(shù)據(jù)并按照年和月進(jìn)行分組:
def load():
df = data.Weather.load()['TEMP']
return ts.groupby_year_month(df)
(3)定義一個將數(shù)據(jù)重排成特殊的Bokeh結(jié)構(gòu)的函數(shù):
def create_source():
colors = plotting.sample_hex_cmap()
month = []
year = []
color = []
avg = []
for year_month, group in load():
month.append(ts.short_month(year_month[1]))
year.append(str(year_month[0]))
monthly_avg = np.nanmean(group.values)
avg.append(monthly_avg)
color.append(colors[min(int(abs(monthly_avg)) - 2, 8)])
source = bkh_plt.ColumnDataSource(data=dict(month=month, year=year, color=color, avg=avg))
return year, source
(4)定義一個返回橫軸標(biāo)簽的函數(shù):
def all_years():
years = set(year)
start_year = min(years)
end_year = max(years)
return [str(y) for y in range(int(start_year), int(end_year),5)]
(5)定義一個繪制包含了懸浮工具欄的熱圖的函數(shù):
def plot(year, source):
fig = bkh_plt.figure(title="De Bilt, NL Temperature (1901 -2014)",
x_range=all_years(),
y_range=list(reversed(ts.short_months())),
toolbar_location="left",
tools="resize,hover,save,
pan,box_zoom,wheel_zoom")
fig.rect("year", "month", 1, 1, source=source,
color="color", line_color=None)
fig.xaxis.major_label_orientation = np.pi/3
hover = fig.select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
('date', '@month @year'),
('avg', '@avg'),
])
bkh_plt.output_notebook()
bkh_plt.show(fig)
(6)調(diào)用上述定義的函數(shù):
year, source = create_source()
plot(year, source)
請參見以下截圖了解最終結(jié)果:
08 把箱線圖、核密度圖和小提琴圖組合
小提琴圖(Violin Plot)是一種組合盒圖和核密度圖或直方圖的圖形類型。Seaborn和matplotlib都能提供小提琴圖。在這個示例中我們將使用Seaborn來繪制天氣數(shù)據(jù)的Z分?jǐn)?shù)(標(biāo)準(zhǔn)分?jǐn)?shù)),分?jǐn)?shù)的標(biāo)準(zhǔn)化并不是必需的,但是如果沒有它的話小提琴圖會很發(fā)散。
操作步驟
(1)導(dǎo)入部分如下:
import seaborn as sns
from dautil import data
import matplotlib.pyplot as plt
(2)加載天氣數(shù)據(jù)并計算標(biāo)準(zhǔn)分?jǐn)?shù):
df = data.Weather.load()
zscores = (df - df.mean())/df.std()
(3)繪制標(biāo)準(zhǔn)分?jǐn)?shù)的小提琴圖:
%matplotlib inline
plt.figure()
plt.title('Weather Violin Plot')
sns.violinplot(zscores.resample('M').mean())
plt.ylabel('Z-scores')
第一個小提琴圖如下所示:
(4)繪制雨天和旱天相對風(fēng)速的小提琴圖:
plt.figure()
plt.title('Rainy Weather vs Wind Speed')
categorical = df
categorical['RAIN'] = categorical['RAIN'] > 0
ax = sns.violinplot(x="RAIN", y="WIND_SPEED",data=categorical)
第二個小提琴圖如下所示:
09 使用蜂巢圖可視化網(wǎng)絡(luò)圖
蜂巢圖(Hive Plot)是用于繪制網(wǎng)絡(luò)圖的可視化技術(shù)。在蜂巢圖中我們將邊緣繪制為曲線。我們根據(jù)屬性對節(jié)點進(jìn)行分組,并在徑向軸上顯示它們。
有些庫在蜂窩圖方面很專業(yè)。同時我們將使用API來劃分Facebook用戶的圖形。
https://snap.stanford.edu/data/egonets-Facebook.html
這個數(shù)據(jù)屬于斯坦福網(wǎng)絡(luò)分析項目(Stanford Network Analysis Project,SNAP),它也提供了Python API,但是目前SNAP API還不支持Python 3。
1. 準(zhǔn)備工作
Anaconda自帶了NetworkX 1.9.1,它安裝說明可見:
https://networkx.github.io/documentation/latest/install.html
同時我們還需要community包,安裝地址:
https://bitbucket.org/taynaud/python-louvain
在PyPi上有一個同名的包,但是它和我們需要安裝的沒有任何關(guān)系。安裝hiveplot包,這個包托管在:
https://github.com/ericmjl/hiveplot
$ [sudo] pip install hiveplot
本示例中使用的hiveplot版本是0.1.7.4。
2. 操作步驟
(1)導(dǎo)入部分如下所示:
import networkx as nx
import community
import matplotlib.pyplot as plt
from hiveplot import HivePlot
from collections import defaultdict
from dautil import plotting
from dautil import dataython
(2)載入數(shù)據(jù),創(chuàng)建一個NetworkX的Graph對象:
fb_file = data.SPANFB().load()
G = nx.read_edgelist(fb_file,create_using = nx.Graph(),nodetype = int)
print(nx.info(G))
(3)分割圖形對象并按照如下的方法創(chuàng)建一個nodes字典:
parts = community.best_partition(G)
nodes = defaultdict(list)
for n, d in parts.items():
nodes[d].append(n)
(4)這個圖形會非常大,所以我們將會創(chuàng)建三個邊緣分組:
edges = defaultdict(list)
for u, v in nx.edges(G, nodes[0]):
edges[0].append((u, v, 0))
for u, v in nx.edges(G, nodes[1]):
edges[1].append((u, v, 1))
for u, v in nx.edges(G, nodes[2]):
edges[2].append((u, v, 2))
(5)繪制這個圖形大約需要6分鐘:
%matplotlib inline
cmap = plotting.sample_hex_cmap(name='hot', ncolors=len(nodes.keys()))
h = HivePlot(nodes, edges, cmap, cmap)
h.draw()
plt.title('Facebook Network Hive Plot')
等待一段時間,我們可以看到如下的圖形:
10 顯示地圖
無論是處理全球數(shù)據(jù)還是本地數(shù)據(jù),使用地圖都是一個適合的可視化方式。我們需要用坐標(biāo)來將數(shù)據(jù)定位到地圖上,通常我們使用的就是這個點的經(jīng)度和緯度。有很多現(xiàn)有的文件格式可以存儲地理位置數(shù)據(jù)。
在這個示例中我們將會使用到特別的shapefile格式以及更常見的制表符分隔值(Tab Separated Values,TSV)格式。shapefile格式是由Esri公司創(chuàng)建的,并包含了三個必需的文件,它們的擴(kuò)展名分別是.shp、.shx、.dbf。
.dbf文件包含了shapefile中每一個地理位置的額外信息的數(shù)據(jù)庫。我們將使用的shapefile包含了國家邊界、人口以及國內(nèi)生產(chǎn)總值(Gross Domestic Product,GDP)的數(shù)據(jù)。我們可以使用cartopy庫下載shapefile。
TSV文件包含了超過4000個城市的按時間序列的人口數(shù)據(jù),可以在這里獲得:
https://nordpil.com/resources/world-database-of-large-cities/
1. 準(zhǔn)備工作
首先我們需要從源文件安裝Proj.4,或者你也可以使用二進(jìn)制版本安裝:
https://github.com/OSGeo/proj.4/wiki
Proj.4的安裝說明在:
https://github.com/OSGeo/proj.4
然后我們可以通過pip安裝cartopy,本示例中使用到的是cartopy-0.13.0?;蛘吣阋部梢酝ㄟ^下面的指令進(jìn)行安裝:
$ conda install -c scitools cartopy
2. 操作步驟
(1)導(dǎo)入部分如下所示:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import cartopy.io.shapereader as shpreader
import matplotlib as mpl
import pandas as pd
from dautil import options
from dautil import data
(2)我們會使用顏色來做國家人口以及人口眾多的城市的可視化。引入如下數(shù)據(jù):
countries = shpreader.natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')
cities = pd.read_csv(data.Nordpil().load_urban_tsv(),sep='\t', encoding='ISO-8859-1')
mill_cities = cities[cities['pop2005'] > 1000]
(3)使用以下代碼畫出地圖,以及相應(yīng)的顏色條,并將人口眾多的城市標(biāo)記在地圖上:
%matplotlib inline
plt.figure(figsize=(16, 12))
gs = mpl.gridspec.GridSpec(2, 1,
height_ratios=[20, 1])
ax = plt.subplot(gs[0], projection=ccrs.PlateCarree())
norm = mpl.colors.Normalize(vmin=0, vmax=2 * 10 ** 9)
cmap = plt.cm.Blues
ax.set_title('Population Estimates by Country')
for country in shpreader.Reader(countries).records():
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor=cmap(
norm(country.attributes['pop_est'])))
plt.plot(mill_cities['Longitude'],
mill_cities['Latitude'], 'r.',
label='Populous city',
transform=ccrs.PlateCarree())
options.set_mpl_options()
plt.legend(loc='lower left')
cax = plt.subplot(gs[1])
cb = mpl.colorbar.ColorbarBase(cax,
cmap=cmap,
norm=norm,
orientation='horizontal')
cb.set_label('Population Estimate')
plt.tight_layout()
11 使用類ggplot2圖
ggplot2是在R語言用戶群中很流行的數(shù)據(jù)可視化庫。ggplot2的主要思想是在數(shù)據(jù)可視化的產(chǎn)出中包含多個圖層。就像一個畫家,我們從一個空的畫布開始,緊接著一步步地添加圖層。
通常我們使用rpy2來讓Python接入R語言代碼。然而,如果我們只是想使用ggplot2的話,用pyggplot庫會顯得更加方便。在這個示例中將實現(xiàn)三個國家的人口增長的可視化,使用的數(shù)據(jù)來自pandas上檢索到的世界銀行的數(shù)據(jù)。這些數(shù)據(jù)中包含各種指標(biāo)和相關(guān)元數(shù)據(jù)。在這里可以下載到關(guān)于這些指標(biāo)的描述:
http://api.worldbank.org/v2/en/topic/19?downloadformat=excel
我們可以認(rèn)為世界銀行的數(shù)據(jù)集是靜態(tài)的。然而,類似的數(shù)據(jù)集經(jīng)常發(fā)生變化,足以占用分析師所有的時間。更換指標(biāo)的名字明顯會影響代碼,所以我決定通過joblib庫來緩存數(shù)據(jù)。但是這個方法美中不足的是不能pickle所有的Python對象。
1. 準(zhǔn)備工作
首先你需要有安裝了ggplot2的R語言環(huán)境。如果你不是特別想使用ggplot2,或許你可以跳過這個示例。
R語言的主頁是:
http://www.r-project.org/
ggplot2的文檔:
http://docs.ggplot2.org/current/index.html
你可以通過pip安裝pyggplot,我使用的是pyggplot-23。安裝joblib,請瀏覽:
https://pythonhosted.org/joblib/installing.html
我的Anaconda中有joblib 0.8.4。
2. 操作步驟
(1)導(dǎo)入部分如下:
import pyggplot
from dautil import data
(2)通過以下代碼加載數(shù)據(jù):
dawb = data.Worldbank()
pop_grow = dawb.get_name('pop_grow')
df = dawb.download(indicator=pop_grow, start=1984, end=2014)
df = dawb.rename_columns(df, use_longnames=True)
(3)下面用我們新建的pandas對象DataFrame初始化pyggplot:
p = pyggplot.Plot(df)
(4)添加條形圖:
p.add_bar('country', dawb.get_longname(pop_grow), color='year')
(5)翻轉(zhuǎn)圖表,使條形圖指向右邊并渲染
p.coord_flip()
p.render_notebook()
請參見以下截圖了解最終結(jié)果:
12 使用影響圖高亮數(shù)據(jù)
類似于氣泡圖,影響圖(influence plot)會考慮到單個數(shù)據(jù)點擬合、影響和杠桿之后的殘差。殘差的大小繪制在垂直軸上,并且可以標(biāo)識數(shù)據(jù)點是異常值。為了更好地理解影響圖,可以看下面的這些方程。
根據(jù)statsmodels文檔,殘差按標(biāo)準(zhǔn)偏差式(2.1)進(jìn)行縮放,在式(2.2)中,n是觀測點的數(shù)量,p是回歸量。式(2.3)我們習(xí)慣稱之為帽子矩陣(hat-matrix)。帽子矩陣的對角元素給出稱為杠桿(leverage)的特殊度量,杠桿作為水平軸的量,可以標(biāo)識出影響圖的潛在影響。
在影響圖中,影響會決定繪圖點的大小。影響大的點往往具有高殘差和杠桿。statsmodels可以使用Cook距離(Cook's distance)(見式(2.4))或者DFFITS(見式(2.5))來衡量影響值。
操作步驟
(1)導(dǎo)入部分如下:
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.formula.api import ols
from dautil import data
(2)獲取可用的國家的編碼:
dawb = data.Worldbank()
countries = dawb.get_countries()[['name', 'iso2c']]
(3)從世界銀行加載數(shù)據(jù):
population = dawb.download(indicator=[dawb.get_name('pop_grow'),
dawb.get_name('gdp_pcap'),
dawb.get_name('primary_education')],
country=countries['iso2c'],
start=2014,
end=2014)
population = dawb.rename_columns(population)
(4)定義一個普通最小二乘模型如下:
population_model = ols("pop_grow ~ gdp_pcap + primary_education",
data=population).fit()
(5)使用Cook距離描繪這個模型的影響圖:
%matplotlib inline
fig, ax = plt.subplots(figsize=(19.2, 14.4))
fig = sm.graphics.influence_plot(population_model, ax=ax, criterion="cooks")
plt.grid()
請參見以下截圖了解最終結(jié)果:
關(guān)于作者:Ivan Idris,曾是Java和數(shù)據(jù)庫應(yīng)用開發(fā)者,后專注于Python和數(shù)據(jù)分析領(lǐng)域,致力于編寫干凈、可測試的代碼。他還是《Python Machine Learning By Example》《NumPy Cookbook》等書的作者,在工程實踐和書籍撰寫方面都非常有經(jīng)驗。