12个案例教你用Python玩转数据可视化
「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑
作者 | 伊凡·伊德里斯(Ivan Idris),曾是Java和数据库应用开发者,后专注于Python和数据分析领域,致力于编写干净、可测试的代码。他还是《Python Machine Learning By Example》《NumPy Cookbook》等书的作者,在工程实践和书籍撰写方面都非常有经验。(本文摘编自《Python数据分析实战》,经出版方授权发布。)
来源 | 大数据(ID:hzdashuju)
编辑 | Jane
【导读】相比于科学,数据分析更像是一门艺术。创建样式优美的数据可视化是这个艺术中不可缺少的部分。然而,某些人认为优美的,也会有人觉得难以接受。和艺术类似,随着数据分析的快速演变,人们的观念和品味也一直在变化。但是总的来说没有人是绝对正确和错误的。
作为一个数据艺术家以及有经验的Python程序员,我们可以从 matplotlib、Seaborn、Bokeh 和 ggplot 这些库里面选择一些来使用。
一、图形化安斯库姆四重奏
安斯库姆四重奏(Anscombe's Quartet)是一个经典案例,它可以说明为什么可视化是很重要的。四重奏包含了四组统计特性一致的数据。每个数据集有一些x值以及相对应的y值,我们将在一个IPython Notebook中列出这些指标。如果你绘制出这些数据集,你将发现这些图表截然不同。
操作步骤
在本节你需要执行如下操作:
(1)由如下导入开始:
1import pandas as pd
2import seaborn as sns
3import matplotlib.pyplot as plt
4import matplotlib as mpl
5from dautil import report
6from dautil import plotting
7import numpy as np
8from tabulate import tabulate
(2)定义以下函数来计算某一数据集中 x 和 y 的均值和方差、相关系数,以及斜率和每个数据集的线性拟合的截距:
1def aggregate():
2 df = sns.load_dataset("anscombe")
3
4 agg = df.groupby('dataset')\
5 .agg([np.mean, np.var])\
6 .transpose()
7 groups = df.groupby('dataset')
8
9 corr = [g.corr()['x'][1] for _, g in groups]
10 builder = report.DFBuilder(agg.columns)
11 builder.row(corr)
12
13 fits = [np.polyfit(g['x'], g['y'], 1) for _, g in groups]
14 builder.row([f[0] for f in fits])
15 builder.row([f[1] for f in fits])
16 bottom = builder.build(['corr', 'slope', 'intercept'])
17
18 return df, pd.concat((agg, bottom))
(3)下面这个函数返回一个字符串,这个字符串有一部分是Markdown,有一部分是重组的文字,有一部分是HTML,这主要是因为原生的Markdown不支持图表:
1def generate(table):
2 writer = report.RSTWriter()
3 writer.h1('Anscombe Statistics')
4 writer.add(tabulate(table, tablefmt='html', floatfmt='.3f'))
5 return writer.rst
(4)绘制数据并相应地与Seaborn的lmplot()函数线性拟合:
1def plot(df):
2 sns.set(style="ticks")
3 g = sns.lmplot(x="x", y="y", col="dataset",
4 hue="dataset", data=df,
5 col_wrap=2, ci=None, palette="muted", size=4,
6 scatter_kws={"s": 50, "alpha": 1})
7
8 plotting.embellish(g.fig.axes)
(5)展示一个统计数据的表格如下:
1df, table = aggregate()
2from IPython.display import display_markdown
3display_markdown(generate(table), raw=True)
下表中显示每个数据集的几乎相同的统计数据(我修改了IPython配置文件里的 custom.css,所以下表是有颜色的):
(6)以下几行代码绘制了数据集:
1%matplotlib inline
2plot(df)
请参见以下截图了解最终结果:
二、选择 Seaborn 的调色板
Seaborn 的调色板和 matplotlib 的颜色表类似。色彩可以帮助你发现数据中的模式,也是重要的可视化组成部分。Seaborn有很丰富的调色板,在这个示例中会将其可视化。
操作步骤
(1)导入部分如下:
1import seaborn as sns
2import matplotlib.pyplot as plt
3import matplotlib as mpl
4import numpy as np
5from dautil import plotting
(2)使用以下函数帮助绘制调色板:
1def plot_palette(ax, plotter, pal, i, label, ncol=1):
2 n = len(pal)
3 x = np.linspace(0.0, 1.0, n)
4 y = np.arange(n) + i*n
5 ax.scatter(x, y, c=x,
6 cmap=mpl.colors.ListedColormap(list(pal)),
7 s=200)
8 plotter.plot(x,y,label=label)
9 handles, labels = ax.get_legend_handles_labels()
10 ax.legend(loc='best', ncol=ncol, fontsize=18)
(3)分类调色板(categorical palette)对于分类数据很有用,例如性别、血型等。以下函数可以绘制一些Seaborn的分类调色板:
1def plot_categorical_palettes(ax):
2 palettes = ['deep', 'muted', 'pastel', 'bright', 'dark','colorblind']
3 plotter = plotting.CyclePlotter(ax)
4 ax.set_title('Categorical Palettes')
5
6 for i, p in enumerate(palettes):
7 pal = sns.color_palette(p)
8 plot_palette(ax, plotter, pal, i, p, 4)
(4)圆形色彩系统(circular color system)通常用HLS(色度亮度饱和度,Hue Lightness Saturation)来取代RGB(红绿蓝Red Gree Blue)颜色空间。如果你有很多分类这将会很有用。以下函数可以使用HLS系统绘制调色板。
1def plot_circular_palettes(ax):
2 ax.set_title('Circular Palettes')
3 plotter = plotting.CyclePlotter(ax)
4
5 pal = sns.color_palette("hls", 6)
6 plot_palette(ax, plotter, pal, 0, 'hls')
7
8 sns.hls_palette(6, l=.3, s=.8)
9 plot_palette(ax, plotter, pal, 1, 'hls l=.3 s=.8')
10
11 pal = sns.color_palette("husl", 6)
12 plot_palette(ax, plotter, pal, 2, 'husl')
13
14 sns.husl_palette(6, l=.3, s=.8)
15 plot_palette(ax, plotter, pal, 3, 'husl l=.3 s=.8')
(5)Seaborn也有基于在线的ColorBrewer工具的调色板。用以下函数绘制出来:
http://colorbrewer2.org/
1def plot_brewer_palettes(ax):
2 ax.set_title('Brewer Palettes')
3 plotter = plotting.CyclePlotter(ax)
4
5 pal = sns.color_palette("Paired")
6 plot_palette(ax, plotter, pal, 0, 'Paired')
7
8 pal = sns.color_palette("Set2", 6)
9 plot_palette(ax, plotter, pal, 1, 'Set2')
(6)连续调色板(sequential palettes)对于数据范围很广的数据来说很有用,比如说有数量级差异的数据。用以下函数绘制出来:
1def plot_sequential_palettes(ax):
2 ax.set_title('Sequential Palettes')
3 plotter = plotting.CyclePlotter(ax)
4
5 pal = sns.color_palette("Blues")
6 plot_palette(ax, plotter, pal, 0, 'Blues')
7
8 pal = sns.color_palette("BuGn_r")
9 plot_palette(ax, plotter, pal, 1, 'BuGn_r')
10
11 pal = sns.color_palette("GnBu_d")
12 plot_palette(ax, plotter, pal, 2, 'GnBu_d')
13
14 pal = sns.color_palette("cubehelix", 6)
15 plot_palette(ax, plotter, pal, 3, 'cubehelix')
(7)以下几行代码调用了我们之前定义的函数:
1%matplotlib inline
2
3fig, axes = plt.subplots(2, 2, figsize=(16, 12))
4plot_categorical_palettes(axes[0][0])
5plot_circular_palettes(axes[0][1])
6plot_brewer_palettes(axes[1][0])
7plot_sequential_palettes(axes[1][1])
8plotting.hide_axes(axes)
9plt.tight_layout()
请参见以下截图了解最终结果:
三、选择matplotlib的颜色表
matplotlib的颜色表最近受到了很多批评,因为它们可能会误导用户,但是在我看来大多数的颜色表还是不错的。默认的颜色表在matplotlib 2.0中有一些改进,可以在这里查看:
http://matplotlib.org/style_changes.html
当然,有些matplotlib的颜色表不支持一些不错的参数,比如说jet。在艺术中,就像数据分析中一样,几乎没有什么东西是绝对正确的,所以这里就交给读者去判断。
实际上,我觉得考虑如何解决印刷出版物以及各种各样的色盲问题是很重要的。在这个示例中我将用色条来可视化相对安全的颜色表。这里使用到的是matplotlib众多颜色表中的很小一部分。
操作步骤
(1)导入部分如下:
1import matplotlib.pyplot as plt
2import matplotlib as mpl
3from dautil import plotting
(2)通过以下代码画出数据集:
1fig, axes = plt.subplots(4, 4)
2cmaps = ['autumn', 'spring', 'summer', 'winter',
3 'Reds', 'Blues', 'Greens', 'Purples',
4 'Oranges', 'pink', 'Greys', 'gray',
5 'binary', 'bone', 'hot', 'cool']
6
7for ax, cm in zip(axes.ravel(), cmaps):
8 cmap = plt.cm.get_cmap(cm)
9 cb = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
10 orientation='horizontal')
11 cb.set_label(cm)
12 ax.xaxis.set_ticklabels([])
13
14plt.tight_layout()
15plt.show()
请参见以下截图了解最终结果:
四、与 IPython Notebook 部件交互
简单来说,这些部件可以让你像在HTML表单里一样选择一些值,这包括滑块、下拉框、选择框等。正如你会读到的,这些部件非常方便将我们在第1章中提及的天气数据可视化。
操作步骤
(1)导入部分如下:
1import seaborn as sns
2import numpy as np
3import pandas as pd
4import matplotlib.pyplot as plt
5from IPython.html.widgets import interact
6from dautil import data
7from dautil import ts
(2)加载数据同时请求内联图:
1%matplotlib inline
2df = data.Weather.load()
(3)定义以下函数,这个函数会显示气泡图:
1def plot_data(x='TEMP', y='RAIN', z='WIND_SPEED', f='A', size=10,cmap='Blues'):
2 dfx = df[x].resample(f)
3 dfy = df[y].resample(f).mean()
4 dfz = df[z].resample(f).mean()
5
6 bubbles = (dfz - dfz.min())/(dfz.max() - dfz.min())
7 years = dfz.index.year
8 sc = plt.scatter(dfx, dfy, s= size * bubbles + 9, c = years,
9 cmap=cmap, label=data.Weather.get_header(z),
10 alpha=0.5)
11 plt.colorbar(sc, label='Year')
12
13 freqs = {'A': 'Annual', 'M': 'Monthly', 'D': 'Daily'}
14 plt.title(freqs[f] + ' Averages')
15 plt.xlabel(data.Weather.get_header(x))
16 plt.ylabel(data.Weather.get_header(y))
17 plt.legend(loc='best')
(4)通过以下代码调用我们刚刚定义的函数:
1vars = df.columns.tolist()
2freqs = ('A', 'M', 'D')
3cmaps = [cmap for cmap in plt.cm.datad if not cmap.endswith("_r")]
4cmaps.sort()
5interact(plot_data, x=vars, y=vars, z=vars, f=freqs,size=(100,700), cmap=cmaps)
(5)本示例需要上手操作一下来理解它的工作原理,下面是一个样例气泡图:
(6)定义另一个函数(和第(2)步中的程序同名,注释掉前一个),这个函数里我们将数据按照日或月进行分组:
1def plot_data(x='TEMP', y='RAIN', z='WIND_SPEED',
2 groupby='ts.groupby_yday',
3 size=10, cmap='Blues'):
4 if groupby == 'ts.groupby_yday':
5 groupby = ts.groupby_yday
6 elif groupby == 'ts.groupby_month':
7 groupby = ts.groupby_month
8 else:
9 raise AssertionError('Unknown groupby ' + groupby)
10 dfx = groupby(df[x]).mean()
11 dfy = groupby(df[y]).mean()
12 dfz = groupby(df[z]).mean()
13 bubbles = (dfz - dfz.min())/(dfz.max() - dfz.min())
14 colors = dfx.index.values
15 sc = plt.scatter(dfx, dfy, s= size * bubbles + 9,
16 c = colors,cmap=cmap,
17 label=data.Weather.get_header(z), alpha=0.5)
18 plt.colorbar(sc, label='Day of Year')
19 by_dict = {ts.groupby_yday: 'Day of Year', ts.groupby_month: 'Month'}
20 plt.title('Grouped by ' + by_dict[groupby])
21 plt.xlabel(data.Weather.get_header(x))
22 plt.ylabel(data.Weather.get_header(y))
23 plt.legend(loc='best')
(7)用这段代码调用上述函数:
1groupbys = ('ts.groupby_yday', 'ts.groupby_month')
2interact(plot_data, x=vars, y=vars, z=vars, groupby=groupbys,
3size=(100,700), cmap=cmaps)
请参见以下截图了解最终结果:
我对这个图的第一印象是温度和风速似乎是正相关的。
五、查看散点图矩阵
如果你的数据集中变量不是很多,那么查看你数据所有的散点图是个不错的主意。通过调用Seaborn或者pandas的一个函数就可以做到。这些函数会展示一个矩阵的核密度估计图或对角线上的直方图。
操作步骤
(1)导入部分如下:
1import pandas as pd
2from dautil import data
3from dautil import ts
4import matplotlib.pyplot as plt
5import seaborn as sns
6import matplotlib as mpl
(2)以下几行代码加载天气数据:
1df = data.Weather.load()
2df = ts.groupby_yday(df).mean()
3df.columns = [data.Weather.get_header(c) for c in df.columns]
(3)用Seaborn的pairplot()函数绘制图形,这个函数默认绘制对角线上的直方图:
1%matplotlib inline
2
3# Seaborn plotting, issues due to NaNs
4sns.pairplot(df.fillna(0))
结果如下所示:
(4)通过pandas的scatter_matrix()函数生成一个类似的图形,并请求对角线上的核密度估计图:
1sns.set({'figure.figsize': '16, 12'})
2mpl.rcParams['axes.linewidth'] = 9
3mpl.rcParams['lines.linewidth'] = 2
4plots = pd.scatter_matrix(df, marker='o', diagonal='kde')
5plt.show()
请参见以下截图了解最终结果:
六、通过 mpld3 使用 d3.js进行可视化
d3.js是在2011年推出的一个JavaScript 数据可视化库,我们可以在IPython Notebook里面使用这个库。我们将在一个普通matplotlib图上添加一个悬浮工具提示。这里我们会使用mpld3包作为使用d3.js的桥梁。这个示例不需要任何JavaScript编程。
1. 准备工作
通过以下命令安装mpld3 0.2:
1[sudo] pip install mpld3
2. 操作步骤
(1)由导入开始,并启用mpld3:
1%matplotlib inline
2import matplotlib.pyplot as plt
3import mpld3
4mpld3.enable_notebook()
5from mpld3 import plugins
6import seaborn as sns
7from dautil import data
8from dautil import ts
(2)加载天气数据并按照下面的方法将其绘制出来:
1df = data.Weather.load()
2df = df[['TEMP', 'WIND_SPEED']]
3df = ts.groupby_yday(df).mean()
4
5fig, ax = plt.subplots()
6ax.set_title('Averages Grouped by Day of Year')
7points = ax.scatter(df['TEMP'], df['WIND_SPEED'],
8 s=30, alpha=0.3)
9ax.set_xlabel(data.Weather.get_header('TEMP'))
10ax.set_ylabel(data.Weather.get_header('WIND_SPEED'))
11labels = ["Day of year {0}".format(i) for i in range(366)]
12tooltip = plugins.PointLabelTooltip(points, labels)
13
14plugins.connect(fig, tooltip)
高亮显示的那一行是工具栏。在下面的截图中,我们可以看到“Day of year 31”文本来自这个工具栏:
如你所见,在这个图形的底部,还有可以平移和缩放图形的装置。
七、创建热图
热图使用一组颜色在矩阵中可视化数据。最初,热图用于表示金融资产(如股票)的价格。Bokeh是一个Python包,可以在IPython Notebook中显示热图,或者生成一个独立的HTML文件。
1. 准备工作
Anaconda自带了 Bokeh 0.9.1。Bokeh的安装说明在:
http://bokeh.pydata.org/en/latest/docs/installation.html
2. 操作步骤
(1)导入部分如下:
1from collections import OrderedDict
2from dautil import data
3from dautil import ts
4from dautil import plotting
5import numpy as np
6import bokeh.plotting as bkh_plt
7from bokeh.models import HoverTool
(2)下面的函数加载了温度数据并按照年和月进行分组:
1def load():
2 df = data.Weather.load()['TEMP']
3 return ts.groupby_year_month(df)
(3)定义一个将数据重排成特殊的Bokeh结构的函数:
1def create_source():
2 colors = plotting.sample_hex_cmap()
3 month = []
4 year = []
5 color = []
6 avg = []
7 for year_month, group in load():
8 month.append(ts.short_month(year_month[1]))
9 year.append(str(year_month[0]))
10 monthly_avg = np.nanmean(group.values)
11 avg.append(monthly_avg)
12 color.append(colors[min(int(abs(monthly_avg)) - 2, 8)])
13 source = bkh_plt.ColumnDataSource(data=dict(month=month, year=year, color=color, avg=avg))
14 return year, source
(4)定义一个返回横轴标签的函数:
1def all_years():
2 years = set(year)
3 start_year = min(years)
4 end_year = max(years)
5 return [str(y) for y in range(int(start_year), int(end_year),5)]
(5)定义一个绘制包含了悬浮工具栏的热图的函数:
1def plot(year, source):
2 fig = bkh_plt.figure(title="De Bilt, NL Temperature (1901 -2014)",
3 x_range=all_years(),
4 y_range=list(reversed(ts.short_months())),
5 toolbar_location="left",
6 tools="resize,hover,save,
7 pan,box_zoom,wheel_zoom")
8 fig.rect("year", "month", 1, 1, source=source,
9 color="color", line_color=None)
10
11 fig.xaxis.major_label_orientation = np.pi/3
12
13 hover = fig.select(dict(type=HoverTool))
14 hover.tooltips = OrderedDict([
15 ('date', '@month @year'),
16 ('avg', '@avg'),
17 ])
18
19 bkh_plt.output_notebook()
20 bkh_plt.show(fig)
21
22
23
24(6)调用上述定义的函数:
25
26
27
28year, source = create_source()
29plot(year, source)
请参见以下截图了解最终结果:
八、把箱线图、核密度图和小提琴图组合
小提琴图(Violin Plot)是一种组合盒图和核密度图或直方图的图形类型。Seaborn和matplotlib都能提供小提琴图。在这个示例中我们将使用Seaborn来绘制天气数据的Z分数(标准分数),分数的标准化并不是必需的,但是如果没有它的话小提琴图会很发散。
操作步骤
(1)导入部分如下:
1import seaborn as sns
2from dautil import data
3import matplotlib.pyplot as plt
(2)加载天气数据并计算标准分数:
1df = data.Weather.load()
2zscores = (df - df.mean())/df.std()
(3)绘制标准分数的小提琴图:
1%matplotlib inline
2plt.figure()
3plt.title('Weather Violin Plot')
4sns.violinplot(zscores.resample('M').mean())
5plt.ylabel('Z-scores')
第一个小提琴图如下所示:
(4)绘制雨天和旱天相对风速的小提琴图:
1plt.figure()
2plt.title('Rainy Weather vs Wind Speed')
3categorical = df
4categorical['RAIN'] = categorical['RAIN'] > 0
5ax = sns.violinplot(x="RAIN", y="WIND_SPEED",data=categorical)
第二个小提琴图如下所示:
九、使用蜂巢图可视化网络图
蜂巢图(Hive Plot)是用于绘制网络图的可视化技术。在蜂巢图中我们将边缘绘制为曲线。我们根据属性对节点进行分组,并在径向轴上显示它们。
有些库在蜂窝图方面很专业。同时我们将使用API来划分Facebook用户的图形。
https://snap.stanford.edu/data/egonets-Facebook.html
这个数据属于斯坦福网络分析项目(Stanford Network Analysis Project,SNAP),它也提供了Python API,但是目前SNAP API还不支持Python 3。
1. 准备工作
Anaconda自带了NetworkX 1.9.1,它安装说明可见:
https://networkx.github.io/documentation/latest/install.html
同时我们还需要community包,安装地址:
https://bitbucket.org/taynaud/python-louvain
在PyPi上有一个同名的包,但是它和我们需要安装的没有任何关系。安装hiveplot包,这个包托管在:
https://github.com/ericmjl/hiveplot
1$ [sudo] pip install hiveplot
本示例中使用的hiveplot版本是0.1.7.4。
2. 操作步骤
(1)导入部分如下所示:
1import networkx as nx
2import community
3import matplotlib.pyplot as plt
4from hiveplot import HivePlot
5from collections import defaultdict
6from dautil import plotting
7from dautil import dataython
(2)载入数据,创建一个NetworkX的Graph对象:
1fb_file = data.SPANFB().load()
2G = nx.read_edgelist(fb_file,create_using = nx.Graph(),nodetype = int)
3print(nx.info(G))
(3)分割图形对象并按照如下的方法创建一个nodes字典:
1parts = community.best_partition(G)
2nodes = defaultdict(list)
3
4for n, d in parts.items():
5 nodes[d].append(n)
(4)这个图形会非常大,所以我们将会创建三个边缘分组:
1edges = defaultdict(list)
2
3for u, v in nx.edges(G, nodes[0]):
4 edges[0].append((u, v, 0))
5
6for u, v in nx.edges(G, nodes[1]):
7 edges[1].append((u, v, 1))
8
9for u, v in nx.edges(G, nodes[2]):
10 edges[2].append((u, v, 2))
(5)绘制这个图形大约需要6分钟:
1%matplotlib inline
2cmap = plotting.sample_hex_cmap(name='hot', ncolors=len(nodes.keys()))
3h = HivePlot(nodes, edges, cmap, cmap)
4h.draw()
5plt.title('Facebook Network Hive Plot')
等待一段时间,我们可以看到如下的图形:
十、显示地图
无论是处理全球数据还是本地数据,使用地图都是一个适合的可视化方式。我们需要用坐标来将数据定位到地图上,通常我们使用的就是这个点的经度和纬度。有很多现有的文件格式可以存储地理位置数据。
在这个示例中我们将会使用到特别的shapefile格式以及更常见的制表符分隔值(Tab Separated Values,TSV)格式。shapefile格式是由Esri公司创建的,并包含了三个必需的文件,它们的扩展名分别是.shp、.shx、.dbf。
.dbf文件包含了shapefile中每一个地理位置的额外信息的数据库。我们将使用的shapefile包含了国家边界、人口以及国内生产总值(Gross Domestic Product,GDP)的数据。我们可以使用cartopy库下载shapefile。
TSV文件包含了超过4000个城市的按时间序列的人口数据,可以在这里获得:
https://nordpil.com/resources/world-database-of-large-cities/
1. 准备工作
首先我们需要从源文件安装Proj.4,或者你也可以使用二进制版本安装:
https://github.com/OSGeo/proj.4/wiki
Proj.4的安装说明在:
https://github.com/OSGeo/proj.4
然后我们可以通过pip安装cartopy,本示例中使用到的是cartopy-0.13.0。或者你也可以通过下面的指令进行安装:
1$ conda install -c scitools cartopy
2. 操作步骤
(1)导入部分如下所示:
1import cartopy.crs as ccrs
2import matplotlib.pyplot as plt
3import cartopy.io.shapereader as shpreader
4import matplotlib as mpl
5import pandas as pd
6from dautil import options
7from dautil import data
(2)我们会使用颜色来做国家人口以及人口众多的城市的可视化。引入如下数据:
1countries = shpreader.natural_earth(resolution='110m',
2 category='cultural',
3 name='admin_0_countries')
4cities = pd.read_csv(data.Nordpil().load_urban_tsv(),sep='\t', encoding='ISO-8859-1')
5mill_cities = cities[cities['pop2005'] > 1000]
(3)使用以下代码画出地图,以及相应的颜色条,并将人口众多的城市标记在地图上:
1%matplotlib inline
2plt.figure(figsize=(16, 12))
3gs = mpl.gridspec.GridSpec(2, 1,
4 height_ratios=[20, 1])
5ax = plt.subplot(gs[0], projection=ccrs.PlateCarree())
6
7norm = mpl.colors.Normalize(vmin=0, vmax=2 * 10 ** 9)
8cmap = plt.cm.Blues
9ax.set_title('Population Estimates by Country')
10
11for country in shpreader.Reader(countries).records():
12 ax.add_geometries(country.geometry, ccrs.PlateCarree(),
13 facecolor=cmap(
14 norm(country.attributes['pop_est'])))
15
16plt.plot(mill_cities['Longitude'],
17 mill_cities['Latitude'], 'r.',
18 label='Populous city',
19 transform=ccrs.PlateCarree())
20
21options.set_mpl_options()
22plt.legend(loc='lower left')
23
24cax = plt.subplot(gs[1])
25cb = mpl.colorbar.ColorbarBase(cax,
26 cmap=cmap,
27 norm=norm,
28 orientation='horizontal')
29
30cb.set_label('Population Estimate')
31plt.tight_layout()
十一、使用类ggplot2图
ggplot2 是在 R 语言用户群中很流行的数据可视化库。ggplot2的主要思想是在数据可视化的产出中包含多个图层。就像一个画家,我们从一个空的画布开始,紧接着一步步地添加图层。
通常我们使用rpy2来让Python接入R语言代码。然而,如果我们只是想使用ggplot2的话,用pyggplot库会显得更加方便。在这个示例中将实现三个国家的人口增长的可视化,使用的数据来自pandas上检索到的世界银行的数据。这些数据中包含各种指标和相关元数据。在这里可以下载到关于这些指标的描述:
http://api.worldbank.org/v2/en/topic/19?downloadformat=excel
我们可以认为世界银行的数据集是静态的。然而,类似的数据集经常发生变化,足以占用分析师所有的时间。更换指标的名字明显会影响代码,所以我决定通过joblib库来缓存数据。但是这个方法美中不足的是不能pickle所有的Python对象。
1. 准备工作
首先你需要有安装了ggplot2的R语言环境。如果你不是特别想使用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)导入部分如下:
1import pyggplot
2from dautil import data
(2)通过以下代码加载数据:
1dawb = data.Worldbank()
2pop_grow = dawb.get_name('pop_grow')
3df = dawb.download(indicator=pop_grow, start=1984, end=2014)
4df = dawb.rename_columns(df, use_longnames=True)
(3)下面用我们新建的pandas对象DataFrame初始化pyggplot:
1p = pyggplot.Plot(df)
(4)添加条形图:
1p.add_bar('country', dawb.get_longname(pop_grow), color='year')
(5)翻转图表,使条形图指向右边并渲染
1p.coord_flip()
2p.render_notebook()
请参见以下截图了解最终结果:
十二、使用影响图高亮数据
类似于气泡图,影响图(influence plot)会考虑到单个数据点拟合、影响和杠杆之后的残差。残差的大小绘制在垂直轴上,并且可以标识数据点是异常值。为了更好地理解影响图,可以看下面的这些方程。
根据statsmodels文档,残差按标准偏差式(2.1)进行缩放,在式(2.2)中,n是观测点的数量,p是回归量。式(2.3)我们习惯称之为帽子矩阵(hat-matrix)。帽子矩阵的对角元素给出称为杠杆(leverage)的特殊度量,杠杆作为水平轴的量,可以标识出影响图的潜在影响。
在影响图中,影响会决定绘图点的大小。影响大的点往往具有高残差和杠杆。statsmodels可以使用Cook距离(Cook's distance)(见式(2.4))或者DFFITS(见式(2.5))来衡量影响值。
操作步骤
(1)导入部分如下:
1import matplotlib.pyplot as plt
2import statsmodels.api as sm
3from statsmodels.formula.api import ols
4from dautil import data
(2)获取可用的国家的编码:
1dawb = data.Worldbank()
2countries = dawb.get_countries()[['name', 'iso2c']]
(3)从世界银行加载数据:
1population = dawb.download(indicator=[dawb.get_name('pop_grow'),
2 dawb.get_name('gdp_pcap'),
3 dawb.get_name('primary_education')],
4 country=countries['iso2c'],
5 start=2014,
6 end=2014)
7population = dawb.rename_columns(population)
(4)定义一个普通最小二乘模型如下:
1population_model = ols("pop_grow ~ gdp_pcap + primary_education",
2 data=population).fit()
(5)使用Cook距离描绘这个模型的影响图:
1%matplotlib inline
2fig, ax = plt.subplots(figsize=(19.2, 14.4))
3fig = sm.graphics.influence_plot(population_model, ax=ax, criterion="cooks")
4plt.grid()
请参见以下截图了解最终结果:
(*本文仅代表作者观点,转载请联系原作者)
◆
精彩推荐
◆
「2019 Python开发者日」10余位一线Python技术专家共同打造一场硬核技术大会,更有深度培训实操环节,为开发者们带来更多深度实战机会。大会倒计时 2 天,少量余票即将售罄,欢迎点击阅读原文购票参会!更多详细信息请咨询 13581782348(微信同号)。
你也可以点击阅读原文查看大会详情。