Python 神兵谱之数据分析-下篇:数据可视化

前言

承接上一篇《Python 神兵谱之数据分析-中篇:数据处理》,今天我们来讲讲这下篇:数据可视化。

无论是数据采集还是数据处理,都是冰山在水面下的内容,水面下做的再好,也需要水面上的可视化来呈现。而水面上展示的内容多少,需要水面下成倍的积累。

那么,如何快速做好数据可视化呢?

下篇:数据可视化

数据可视化,顾名思义就是将繁多的数据转换成利于展示,便于人理解的图表。而这其中,最为常见的就是几种图:饼图、折线图、柱状图、雷达图、箱线图等等。下面我们来看看 Python 中众多的绘图库,如何来绘制这些图表吧。

Matplotlib

Matplotlib 是 Python 非常著名的绘图库,受到了 Matlab 的启发,使用方式和接口都非常像 Matlab。先来看看用 Matplotlib 绘制的图,

比较中规中矩,非常适合科学计算领域。

Matplotlib 一般以如下的方式引用。

python copyable">import matplotlib.pyplot as plt

Matplotlib 中有几个核心概念。

  • Figure:面板,所有图像都是位于 figure 对象中,一个图像只能有一个 figure 对象。
  • Subplot:子图,figure 对象下创建一个或多个 subplot 对象(即坐标系)用于绘制图像。
  • Axis:坐标轴,即每个子图或坐标系中的一条坐标轴。

绘制柱状图的例子。

import matplotlib.pyplot as plt

labels = ['G1', 'G2', 'G3', 'G4', 'G5']

men_means = [20, 35, 30, 35, 27]

women_means = [25, 32, 34, 20, 25]

men_std = [2, 3, 4, 1, 2]

women_std = [3, 5, 2, 3, 3]

width = 0.35

fig, ax = plt.subplots() # 即 Figure,subplot 对象

# 绘制柱状图

ax.bar(labels, men_means, width, yerr=men_std, label='Men')

ax.bar(labels, women_means, width, yerr=women_std, bottom=men_means, label='Women')

# 设置标签、标题、图例

ax.set_ylabel('Scores')

ax.set_title('Scores by group and gender')

ax.legend()

# 显示图表

plt.show()

会显示如下所示的图形。

Matplotlib 配置的方式比较直观,同时也支持 Numpy 数组作为输入。

fig = plt.figure(2)  # 新开一个窗口

ax1 = fig.add_subplot(1, 2, 1, polar=True) # 启动一个极坐标子图

theta = np.arange(0, 2 * np.pi, 0.02) # 角度数列值

ax1.plot(theta, 2 * np.ones_like(theta), lw=2) # 画图,参数:角度,半径,lw线宽

ax1.plot(theta, theta / 6, linestyle='--', lw=2) # 画图,参数:角度,半径,linestyle样式,lw线宽

# 启动一个极坐标子图

ax2 = fig.add_subplot(1, 2, 2, polar=True)

ax2.plot(theta, np.cos(5 * theta), linestyle='--', lw=2)

ax2.plot(theta, 2 * np.cos(4 * theta), lw=2)

# 设置网格轴的距离和角度

ax2.set_rgrids(np.arange(0.2, 2, 0.2), angle=45)

ax2.set_thetagrids([0, 45, 90])

plt.show()

Matplotlib 是 Python 绘图库中功能强大,但是偏底层的,对于绘图的控制能力比较强,但是配置项也比较多。

Seaborn

Seaborn 是基于 Matplotlib 开发的绘图库,提供了更高级和简洁的语法。通过 Seaborn 的高级 API,能够快速绘图图形,且无需配置就提供了一些好看的样式。

先上一个折线图。

import seaborn as sns

sns.set(style="ticks")

# 载入测试数据集

df = sns.load_dataset("anscombe")

# 为每个数据集绘制折线图并展示线性回归线

sns.lmplot(x="x", y="y", col="dataset", hue="dataset", data=df,

col_wrap=2, ci=None, palette="muted", height=4,

scatter_kws={"s": 50, "alpha": 1})

绘图只有一行代码,是不是非常的酷!

Seaborn 有一套统一的绘图 API,要求原始数据的输入类型为 Pandas 的 Dataframe 或 Numpy 数组,API 形式如下:

  • sns.图名(x='X轴列名', y='Y轴列名', data=原始数据df对象)
  • sns.图名(x='X轴列名', y='Y轴列名', hue='分组绘图参数', data=原始数据df对象)
  • sns.图名(x=np.array, y=np.array[, ...])

也来绘制一个柱状图。

import seaborn as sns

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

# 生成数据

x = np.arange(8)

y = np.array([1,5,3,6,2,4,5,6])

df = pd.DataFrame({"x-axis": x, "y-axis": y})

# 绘制柱状图

sns.barplot("x-axis", "y-axis", palette="RdBu_r", data=df)

# 调用 Matplotlib 的底层 API

plt.xticks(rotation=90)

plt.show()

Seaborn 提供了一个高层的简便的 API,可以和 Matplotlib 结合使用,大大简化了 Matplotlib 的配置操作。

plotnine/ggplot

plotnine 和 ggplot 的灵感都来源于 R 语言的 ggplot2,和 Matplotlib 的设计思路完全不同,是图层叠加的思想,即一层层叠加绘制。不过它们仍旧是基于 Matplotlib 开发的。输入数据需要是 Pandas 的 DataFrame 类型。两个库的语法类似,ggplot 最近已经不更新,而 plotnine 是最近比较活跃的。

下面的代码来自 plotnine,绘制柱状图。

import pandas as pd

import numpy as np

from plotnine import *

from plotnine.data import *

ggplot(mpg) + geom_bar(aes(x='class'))

通过 + 把一个个图层叠加起来,一般会有数据层、几何图形层和美化层组成。

然后加一些色彩。

ggplot(mpg) + geom_bar(aes(x='class', fill='drv'))

再进行一些变换。

(

ggplot(mpg)

+ geom_bar(aes(x='class', fill='drv'))

+ coord_flip()

+ theme_classic()

)

plotnine / ggplot 的语法非常简洁,非常适合于喜欢或习惯 R 语言绘图的人。

Bokeh

Bokeh 是 Python 中一个非常强大的交互式图表库,即通过 JS 代码生成可以交互的网页端图表,非常适合嵌入到前端应用中。Bokeh 绘制的图表非常好看,并且有不错的交互体验。

左侧的选择框可实时影响中间的数据渲染,图表右侧还有交互式的控制栏。同时数据点也能响应鼠标事件,例如鼠标移动上去后显示具体数值。

上述图表的代码如下:

import pandas as pd

from bokeh.layouts import column, row

from bokeh.models import Select

from bokeh.palettes import Spectral5

from bokeh.plotting import curdoc, figure

from bokeh.sampledata.autompg import autompg_clean as df

df = df.copy()

SIZES = list(range(6, 22, 3))

COLORS = Spectral5

N_SIZES = len(SIZES)

N_COLORS = len(COLORS)

# 数据清理

df.cyl = df.cyl.astype(str)

df.yr = df.yr.astype(str)

del df['name']

columns = sorted(df.columns)

discrete = [x for x in columns if df[x].dtype == object]

continuous = [x for x in columns if x notin discrete]

defcreate_figure():

xs = df[x.value].values

ys = df[y.value].values

x_title = x.value.title()

y_title = y.value.title()

kw = dict()

if x.value in discrete:

kw['x_range'] = sorted(set(xs))

if y.value in discrete:

kw['y_range'] = sorted(set(ys))

kw['title'] = "%s vs %s" % (x_title, y_title)

p = figure(plot_height=600, plot_width=800, tools='pan,box_zoom,hover,reset', **kw)

p.xaxis.axis_label = x_title

p.yaxis.axis_label = y_title

if x.value in discrete:

p.xaxis.major_label_orientation = pd.np.pi / 4

sz = 9

if size.value != 'None':

if len(set(df[size.value])) > N_SIZES:

groups = pd.qcut(df[size.value].values, N_SIZES, duplicates='drop')

else:

groups = pd.Categorical(df[size.value])

sz = [SIZES[xx] for xx in groups.codes]

c = "#31AADE"

if color.value != 'None':

if len(set(df[color.value])) > N_COLORS:

groups = pd.qcut(df[color.value].values, N_COLORS, duplicates='drop')

else:

groups = pd.Categorical(df[color.value])

c = [COLORS[xx] for xx in groups.codes]

p.circle(x=xs, y=ys, color=c, size=sz, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)

return p

defupdate(attr, old, new):

layout.children[1] = create_figure()

x = Select(title='X-Axis', value='mpg', options=columns)

x.on_change('value', update)

y = Select(title='Y-Axis', value='hp', options=columns)

y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + continuous)

size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + continuous)

color.on_change('value', update)

controls = column(x, y, color, size, width=200)

layout = row(controls, create_figure())

curdoc().add_root(layout)

curdoc().title = "Crossfilter"

由于 Bokeh 生成的是 Html 网页,无法直接看到图片,可以使用 Bokeh 服务器运行查看,当然也可以整合到自己的前端服务中。

bokeh serve --show crossfilter

Pygal

Pygal 是一个 SVG 绘图库,SVG 是一种矢量图,也可嵌入前端网页中做交互式展示。不过和 Bokeh 不同的是,SVG 只是图表交互,并不包含 JS 代码来动态修改数据和样式。

Pygal 绘制的图表也是可以通过鼠标交互的,也可是隐藏或显示某个系列数据。

绘制柱状图。

bar_chart = pygal.Bar()

# 添加数据

bar_chart.add('Fibonacci', [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])

# 生成 SVG

bar_chart.render_to_file('bar_chart.svg')

只能展示静态的截图。

多个系列的数据。

import pygal

# 配置图表

line_chart = pygal.Bar()

line_chart.title = 'Browser usage evolution (in %)'

line_chart.x_labels = map(str, range(2002, 2013))

# 添加数据

line_chart.add('Firefox', [None, None, 0, 16.6, 25, 31, 36.4, 45.5, 46.3, 42.8, 37.1])

line_chart.add('Chrome', [None, None, None, None, None, None, 0, 3.9, 10.8, 23.8, 35.3])

line_chart.add('IE', [85.8, 84.6, 84.7, 74.5, 66, 58.6, 54.7, 44.8, 36.2, 26.6, 20.1])

line_chart.add('Others', [14.2, 15.4, 15.3, 8.9, 9, 10.4, 8.9, 5.8, 6.7, 6.8, 7.5])

line_chart.render()

Pygal 语法简单,且能生成交互式 SVG 图表,适合有前端简单交互需求的场景使用。

Plotly

Plotly 是针对科学计算和机器学习可视化开发的图表库,同时它们还有 Dash 框架,用于快速开发机器学习或数据科学的应用。Plotly 绘制的图表非常美观,而且也是前端交互式的图表。Plotly 是 Plotly 公司的产品,不过它仍旧是开源且免费使用的,无需联网或注册账户,不过它们也提供企业版本。

还是绘制柱状图。

import plotly.express as px

data_canada = px.data.gapminder().query("country == 'Canada'")

fig = px.bar(data_canada, x='year', y='pop')

fig.show()

图表也是可以交互的,且右上角有菜单栏。

简单的代码美化效果。

import plotly.express as px

data = px.data.gapminder()

data_canada = data[data.country == 'Canada']

fig = px.bar(data_canada, x='year', y='pop',

hover_data=['lifeExp', 'gdpPercap'], color='lifeExp',

labels={'pop':'population of Canada'}, height=400)

fig.show()

Plotly 非常适合构建前端交互式图表,同时可以使用 Dash 框架快速构建数据分析应用,使用上也非常简单明了。

Altair

Altair 是基于 Vega 和 Vega-Lite 语法的声明式绘图语言,可以使用简单的语法绘制交互式的图表,效果还是比较好的。

照例来绘制柱状图。

import altair as alt

import pandas as pd

source = pd.DataFrame({

'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],

'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]

})

alt.Chart(source).mark_bar().encode(

x='a',

y='b'

)

图表也是交互式的。

import altair as alt

from vega_datasets import data

source = data.wheat()

bar = alt.Chart(source).mark_bar().encode(

x='year:O',

y='wheat:Q'

)

# 添加均值线

rule = alt.Chart(source).mark_rule(color='red').encode(

y='mean(wheat):Q'

)

(bar + rule).properties(width=600)

Altair 的使用也非常简单,且可以绘制强大的交互式图表,不过需要学习 Vega 或 Vega-lite 绘图语法。

后记

Python 的绘图库非常之多,还有许多库这里还没有罗列,并不代表它们不好用。对于库的选择和使用,需要我们基于不同的使用场景。例如,生成纯图片文件的 Matlibplot,Seaborn,plotline,ggplot,生成交互式图表的 Bokeh、Plotly、Altair,生成 SVG 的 Pygal。

一些库的 API 偏底层,编写代码量较大,但是灵活性高,例如 Matplotlib。一些库的 API 偏高层,封装更多,代码量少,但是有不少局限性,例如 Seaborn。

Python 神兵谱到此就完结了,以后我还是会继续分享有用的 Python 库或工具,甚至做一些深入实践,欢迎点赞关注评论。

参考

  • Matplotlib
  • Seaborn
  • ggplot
  • plotnine
  • Bokeh
  • Pygal
  • Plotly
  • Altair

以上是 Python 神兵谱之数据分析-下篇:数据可视化 的全部内容, 来源链接: utcz.com/a/33917.html

回到顶部