翻译:张媛
校对:卢苗苗
本文共8269字,建议阅读10分钟。
用代码将你的数据集进行多维可视化!
介绍
描述性分析是与数据科学或特定研究相关的任何分析生命周期中的核心组成部分之一。数据聚合,汇总与可视化是支撑数据分析这一领域的主要支柱。从传统商业智能时代开始,即使在如今的人工智能时代,数据可视化一直是一种强大的工具,由于其能够有效地抽象出正确的信息,清晰直观地理解和解释数据结果而被很多组织广泛地采用。然而处理通常具有两个以上属性的数据集时开始出现问题,因为数据分析和通信的媒介一般局限于两个维度。在本文中,我们将探讨多维数据可视化过程中的一些有效策略。
动机
“一图胜千言。”
这是我们很熟悉的非常流行的一句话,也是我们将理解和利用数据可视化作为数据分析的有效工具的巨大灵感和动力。永远记住“有效的数据可视化是一门艺术,也是一门科学”。在开始之前,我还想引用一句话,这句话不仅与本文相关,还强调了数据化的必要性。
“一张图最大的价值在于它使我们注意到我们没有预料到的东西。”
— John Tukey
数据可视化快速回顾
本文假设一般读者都知道用于绘图和数据可视化的基本图表知识,因此这里不会对此进行详细解释,但是我们将在接下来的操作实验中覆盖其大部分内容。就像著名的可视化先驱和统计学家Edward Tufte提到的那样,数据可视化应该以数据为基础进行“清晰,精确,高效”的模式和见解交流。
结构化数据通常包括由行表示的数据观察值和由列表示的数据属性或特征。每一列也可以称为数据集的特定维度。最常见的数据类型包括连续的数值数据和离散的分类数据,因此任何数据可视化基本上以直方图,散点图,箱型图等简单易懂的方式来描述一个或多个数据属性。接下来的介绍将涵盖单变量(一维)和多变量(多维)的数据可视化策略,我们将在这里使用Python机器学习生态系统,并建议您检查进行数据分析和可视化的应用框架,包括pandas, matplotlib, seaborn, plotly 和 bokeh等工具。另外,如果您对使用数据制作出精美而有意义的可视化结果感兴趣,那么了解D3.js也是必须的。有兴趣的读者建议您可以阅读EdwardTufte的‘ The Visual Display ofQuantitative Information’一书。
空谈无益,请看可视化的代码实现!
让我们开始吧,停止喋喋不休地谈论理论和概念。我们将使用UCI机器学习库提供的葡萄酒质量数据集。这些数据实际上包含两个数据集,分别描述了葡萄牙“Vinho Verde”葡萄酒中红色和白色变种的多种属性。本文中的所有分析都可以在我的GitHub库Jupyter Notebook文档中找到,您可以尽情尝试!
首先我们将加载以下依赖项,以便进行后续的数据分析。
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
import numpy as np
import seaborn as sns
%matplotlib inline
我们将主要使用matplotlib和 seaborn作为可视化框架,您也可以自由选择任何其他的框架进行同样的尝试。经过一些基本的数据预处理步骤后,我们来看看数据。
white_wine = pd.read_csv('winequality-white.csv', sep=';')
red_wine = pd.read_csv('winequality-red.csv', sep=';')
# store wine type as an attribute
red_wine['wine_type'] = 'red'
white_wine['wine_type'] = 'white'
# bucket wine quality scores into qualitative quality labels
red_wine['quality_label'] = red_wine['quality'].apply(lambda value: 'low'
if value
if value
red_wine['quality_label'] = pd.Categorical(red_wine['quality_label'],
categories=['low', 'medium', 'high'])
white_wine['quality_label'] = white_wine['quality'].apply(lambda value: 'low'
if value
if value
white_wine['quality_label'] = pd.Categorical(white_wine['quality_label'],
categories=['low', 'medium', 'high'])
# merge red and white wine datasets
wines = pd.concat([red_wine, white_wine])
# re-shuffle records just to randomize data points
wines = wines.sample(frac=1, random_state=42).reset_index(drop=True)
我们通过合并与红白葡萄酒相关的数据集来创建一个单一的葡萄酒数据框架。我们还根据葡萄酒的样品质量属性创建了一个类别变量quality_label,接下来我们看一下数据。
wines.head()
The wine quality dataset
很显然,我们有几个葡萄酒样本的数字和分类属性,每个观察值都属于一个红白葡萄酒样本,其属性是从物理和化学试验中测量和获得的特定数值。如果您想了解每个属性的详细解释,可以查看我的Jupyter笔记,但这些名称的意思是不言而喻的。接下来让我们对这些感兴趣的属性做一个快速的基本描述性统计。
subset_attributes = ['residual sugar', 'total sulfur dioxide', 'sulphates',
'alcohol', 'volatile acidity', 'quality']
rs = round(red_wine[subset_attributes].describe(),2)
ws = round(white_wine[subset_attributes].describe(),2)
pd.concat([rs, ws], axis=1, keys=['Red Wine Statistics', 'White Wine Statistics'])
葡萄酒类型的基本描述性统计
比较这些不同类型的葡萄酒样本的统计方法是非常容易的,要注意一些属性的明显差异,稍后我们将在具体的可视化过程中体现这些内容。
单变量分析
单变量分析基本上是数据分析或可视化的最简单的形式,我们只需要关心和分析一个数据属性或者变量,对一维数据进行可视化。
一维数据可视化
对所有数字数据及其分布进行可视化的最快速最有效的方法之一是利用工具pandas中的直方图。
wines.hist(bins=15,color='steelblue', edgecolor='black', linewidth=1.0,
xlabelsize=8, ylabelsize=8,grid=False)
plt.tight_layout(rect=(0,0, 1.2, 1.2))
将属性值作为一维数据进行可视化处理
上面的图给出了一个将任何属性的基本数据分布进行可视化的好想法。
接下来让我们深入了解一个连续型数值属性。本质上来讲,直方图或者密度图就可以很好地理解该属性的数据分布。
# Histogram
fig = plt.figure(figsize = (6,4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax = fig.add_subplot(1,1, 1)
ax.set_xlabel("Sulphates")
ax.set_ylabel("Frequency")
ax.text(1.2, 800, r'$\mu$='+str(round(wines['sulphates'].mean(),2)),
fontsize=12)
freq, bins, patches = ax.hist(wines['sulphates'], color='steelblue', bins=15,
edgecolor='black', linewidth=1)
# Density Plot
fig = plt.figure(figsize = (6, 4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax1 = fig.add_subplot(1,1, 1)
ax1.set_xlabel("Sulphates")
ax1.set_ylabel("Frequency")
sns.kdeplot(wines['sulphates'], ax=ax1, shade=True, color='steelblue')
对一维连续数字类型的数据进行可视化
从上面的图表可以很明显地看出,葡萄酒硫酸盐的分布存在明确的右偏。
可视化一个离散分类型数据属性稍有不同,条形图是最有效的方法之一。你也可以使用饼图,但通常尽量避免使用这种形式,尤其是不同类别的数量超过3个时。
# Histogram
fig = plt.figure(figsize = (6,4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax = fig.add_subplot(1,1, 1)
ax.set_xlabel("Sulphates")
ax.set_ylabel("Frequency")
ax.text(1.2, 800, r'$\mu$='+str(round(wines['sulphates'].mean(),2)),
fontsize=12)
freq, bins, patches = ax.hist(wines['sulphates'], color='steelblue', bins=15,
edgecolor='black', linewidth=1)
# Density Plot
fig = plt.figure(figsize = (6, 4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax1 = fig.add_subplot(1,1, 1)
ax1.set_xlabel("Sulphates")
ax1.set_ylabel("Frequency")
sns.kdeplot(wines['sulphates'], ax=ax1, shade=True, color='steelblue')
对一维离散分类的数据进行可视化
接下来我们来看高维数据的可视化。
多变量分析
多变量分析是一种趣味和复杂性并存的分析方法,接下来我们将分析多个数据维度或者属性(2个或以上),不仅包括检查数据分布,还包括这些属性之间的潜在关系、模式和相关性。如果有必要的话,您也可以根据需要解决的问题,利用推理统计和假设检验,检查不同属性、群体等的统计意义。
二维数据可视化
研究不同数据属性之间的潜在关系或相关性的最佳方法之一是利用成对相关矩阵并将其描述为一个热图。
# Correlation Matrix Heatmap
f, ax = plt.subplots(figsize=(10, 6))
corr = wines.corr()
hm = sns.heatmap(round(corr,2), annot=True, ax=ax, cmap="coolwarm",fmt='.2f',
linewidths=.05)
f.subplots_adjust(top=0.93)
t= f.suptitle('Wine Attributes Correlation Heatmap', fontsize=14)
用相关热图对二维数据可视化
您可以清楚地看到,热图中的梯度根据相关性的强弱而变化,很容易发现那些彼此之间具有强相关性的潜在属性。另一种可视化的方法是对您感兴趣的属性使用成对散点图。
# Correlation Matrix Heatmap
f, ax = plt.subplots(figsize=(10, 6))
corr = wines.corr()
hm = sns.heatmap(round(corr,2), annot=True, ax=ax, cmap="coolwarm",fmt='.2f',
linewidths=.05)
f.subplots_adjust(top=0.93)
t= f.suptitle('Wine Attributes Correlation Heatmap', fontsize=14)
用成对散点图对二维数据进行可视化
根据上图,您可以看到散点图也是一种观察二维数据属性之间潜在关系的好方法。另一种将多个属性的多变量数据可视化的方法是使用平行坐标。
# Correlation Matrix Heatmap
f, ax = plt.subplots(figsize=(10, 6))
corr = wines.corr()
hm = sns.heatmap(round(corr,2), annot=True, ax=ax, cmap="coolwarm",fmt='.2f',
linewidths=.05)
f.subplots_adjust(top=0.93)
t= f.suptitle('Wine Attributes Correlation Heatmap', fontsize=14)
使用平行坐标对多维数据进行可视化
基本上来讲,在上图所示的可视化中,点被表示为连接的线段,每条垂直线代表一个数据属性,所有属性中的一组完整连接的线段表示一个数据点。因此趋于同一类的点将会更加接近。仅仅通过观察就可以很清楚地看到,与白葡萄酒相比,红葡萄酒的密度稍微高一点。此外,与红葡萄酒相比,白葡萄酒的残余糖分和二氧化硫总量较高,但同时红葡萄酒的固定酸度高于白葡萄酒。您也可以从之前的统计表中查看数据来验证这个结论。
让我们来看看一些可以对两个连续的数字属性进行可视化的方法。特别是散点图和联合图,他们不仅是检查数据模式和相关性的好方法,而且还可以查看各个属性的分布。
# Scatter Plot
plt.scatter(wines['sulphates'], wines['alcohol'],
alpha=0.4, edgecolors='w')
plt.xlabel('Sulphates')
plt.ylabel('Alcohol')
plt.title('Wine Sulphates - Alcohol Content',y=1.05)
# Joint Plot
jp = sns.jointplot(x='sulphates', y='alcohol', data=wines,
kind='reg', space=0, size=5, ratio=4)
使用散点图和联合图可视化二维连续数字数据
如上图所示,左边是散点图,右边是联合图,就像我们提到的那样,你可以在联合图中查看数据的相关性,关系以及个体分布。
那么如何对两个离散的分类属性进行可视化呢?一种方法是利用单独的块(子图)或切面作为分类维度之一。
# Using subplots or facets along with Bar Plots
fig = plt.figure(figsize = (10, 4))
title = fig.suptitle("Wine Type - Quality", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
# red wine - wine quality
ax1 = fig.add_subplot(1,2, 1)
ax1.set_title("Red Wine")
ax1.set_xlabel("Quality")
ax1.set_ylabel("Frequency")
rw_q = red_wine['quality'].value_counts()
rw_q = (list(rw_q.index), list(rw_q.values))
ax1.set_ylim([0, 2500])
ax1.tick_params(axis='both', which='major', labelsize=8.5)
bar1 = ax1.bar(rw_q[0], rw_q[1], color='red',
edgecolor='black', linewidth=1)
# white wine - wine quality
ax2 = fig.add_subplot(1,2, 2)
ax2.set_title("White Wine")
ax2.set_xlabel("Quality")
ax2.set_ylabel("Frequency")
ww_q = white_wine['quality'].value_counts()
ww_q = (list(ww_q.index), list(ww_q.values))
ax2.set_ylim([0, 2500])
ax2.tick_params(axis='both', which='major', labelsize=8.5)
bar2 = ax2.bar(ww_q[0], ww_q[1], color='white',
edgecolor='black', linewidth=1)
使用条形图和子图(切面)可视化二维离散分类数据,
虽然这是一种很好的对分类数据进行可视化的方法,但正如您所看到的,使用matplotlib编程导致代码量很大。 另一个好方法是在单个图中使用堆叠条或多个条来表示不同的属性,通过seaborn我们可以很容易地实现这个目标。
# Multi-bar Plot
cp = sns.countplot(x="quality", hue="wine_type", data=wines,
palette={"red": "#FF9999", "white": "#FFE888"})
在一个条形图中可视化二维离散的分类数据
这个方法看起来更简洁一些,你也可以很容易地从单一的图中比较不同的类别。
让我们看看在二维(基本上是数字和分类在一起)混合属性的可视化。 一种方法是将子图或切面与一般的直方图或密度图一起使用。
# facets with histograms
fig = plt.figure(figsize = (10,4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax1 = fig.add_subplot(1,2, 1)
ax1.set_title("Red Wine")
ax1.set_xlabel("Sulphates")
ax1.set_ylabel("Frequency")
ax1.set_ylim([0, 1200])
ax1.text(1.2, 800, r'$\mu$='+str(round(red_wine['sulphates'].mean(),2)),
fontsize=12)
r_freq, r_bins, r_patches = ax1.hist(red_wine['sulphates'], color='red', bins=15,
edgecolor='black', linewidth=1)
ax2 = fig.add_subplot(1,2, 2)
ax2.set_title("White Wine")
ax2.set_xlabel("Sulphates")
ax2.set_ylabel("Frequency")
ax2.set_ylim([0, 1200])
ax2.text(0.8, 800, r'$\mu$='+str(round(white_wine['sulphates'].mean(),2)),
fontsize=12)
w_freq, w_bins, w_patches = ax2.hist(white_wine['sulphates'], color='white', bins=15,
edgecolor='black', linewidth=1)
# facets with density plots
fig = plt.figure(figsize = (10, 4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax1 = fig.add_subplot(1,2, 1)
ax1.set_title("Red Wine")
ax1.set_xlabel("Sulphates")
ax1.set_ylabel("Density")
sns.kdeplot(red_wine['sulphates'], ax=ax1, shade=True, color='r')
ax2 = fig.add_subplot(1,2, 2)
ax2.set_title("White Wine")
ax2.set_xlabel("Sulphates")
ax2.set_ylabel("Density")
sns.kdeplot(white_wine['sulphates'], ax=ax2, shade=True, color='y')
在二维切面和直方图或密度图中对混合属性进行可视化
虽然这很好,但是再一次产生了大量的样板代码,而这原本可以通过使用seaborn来避免,甚至可以通过一张图表描述所有的图。
# Using multiple Histograms
fig = plt.figure(figsize = (6, 4))
title = fig.suptitle("Sulphates Content in Wine", fontsize=14)
fig.subplots_adjust(top=0.85, wspace=0.3)
ax = fig.add_subplot(1,1, 1)
ax.set_xlabel("Sulphates")
ax.set_ylabel("Frequency")
g = sns.FacetGrid(wines, hue='wine_type', palette={"red": "r", "white": "y"})
g.map(sns.distplot, 'sulphates', kde=False, bins=15, ax=ax)
ax.legend(title='Wine Type')
plt.close(2)
在二维混合属性中使用多维直方图
您可以看到上面生成的图表清晰简洁,我们可以轻松地在各种分布之间进行比较。除此之外,箱型图是另一种根据分类属性中的不同值对数据组进行描绘的有效方式。 方块图是了解数据中四分位数值以及潜在异常值的好方法。
# Box Plots
f, (ax) = plt.subplots(1, 1, figsize=(12, 4))
f.suptitle('Wine Quality - Alcohol Content', fontsize=14)
sns.boxplot(x="quality", y="alcohol", data=wines, ax=ax)
ax.set_xlabel("Wine Quality",size = 12,alpha=0.8)
ax.set_ylabel("Wine Alcohol %",size = 12,alpha=0.8)
二维混合属性的有效可视化方法——箱型图
另一个类似的可视化方法是小提琴图,这是使用核密度图对分组数值数据可视化的另一种有效方法(描绘了不同值的数据的概率密度)。
# Violin Plots
f, (ax) = plt.subplots(1, 1, figsize=(12, 4))
f.suptitle('Wine Quality - Sulphates Content', fontsize=14)
sns.violinplot(x="quality", y="sulphates", data=wines, ax=ax)
ax.set_xlabel("Wine Quality",size = 12,alpha=0.8)
ax.set_ylabel("Wine Sulphates",size = 12,alpha=0.8)
小提琴图是二维混合属性的有效表示方法
您可以清楚地观察到不同的葡萄酒硫酸盐对应的葡萄酒质量类别的密度图。
对二维数据可视化非常简单,但随着维度(属性)增加,复杂度也在上升,原因是我们被现有显示媒介所在的二维空间所束缚。
对于三维数据,我们可以通过在图表中采用z轴或利用子图和切面来引入一个深度的概念。
然而,对于三维以上的数据,对其进行类似的可视化就变得更加困难,最好的方法是使用图形的切面,颜色,形状,大小,深度等特性,您还可以将时间作为一个维度,为其他属性绘制一个动图(考虑时间是数据中的维度)。看看Hans Roslin 的优秀演讲,就可以得到同样的想法!
三维数据可视化
考虑到数据中有三个属性或维度,我们可以考虑成对散点图并引入颜色或色调的概念来对它们进行可视化,以便在分类维度中分离出数值。
# Scatter Plot with Hue for visualizing data in 3-D
cols = ['density', 'residual sugar', 'total sulfur dioxide', 'fixed acidity', 'wine_type']
pp = sns.pairplot(wines[cols], hue='wine_type', size=1.8, aspect=1.8,
palette={"red": "#FF9999", "white": "#FFE888"},
plot_kws=dict(edgecolor="black", linewidth=0.5))
fig = pp.fig
fig.subplots_adjust(top=0.93, wspace=0.3)
t = fig.suptitle('Wine Attributes Pairwise Plots', fontsize=14)
用散点图和色调(颜色)对三维数据可视化
根据上图,您可以对各个参数的相关性和模式进行分析,并在不同的葡萄酒中进行比较,例如,我们可以清楚地看到,与红葡萄酒相比,白葡萄酒的总二氧化硫和残留糖含量更高。
让我们来看看对三个连续的数字属性进行可视化的策略。 一种方法是用常规的长度(x轴)和宽度(y轴)表示其中的二维,将第三维表示为深度(z轴)。
# Visualizing 3-D numeric data with Scatter Plots
# length, breadth and depth
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
xs = wines['residual sugar']
ys = wines['fixed acidity']
zs = wines['alcohol']
ax.scatter(xs, ys, zs, s=50, alpha=0.6, edgecolors='w')
ax.set_xlabel('Residual Sugar')
ax.set_ylabel('Fixed Acidity')
ax.set_zlabel('Alcohol')
通过引入深度的概念对三维数字类型的数据进行可视化
我们还可以利用常规的二维坐标轴,并将尺寸的概念作为第三维(本质上是气泡图),其中点的大小表示第三维数据的数量。
# Visualizing 3-D numeric data with a bubble chart
# length, breadth and size
plt.scatter(wines['fixed acidity'], wines['alcohol'], s=wines['residual sugar']*25,
alpha=0.4, edgecolors='w')
plt.xlabel('Fixed Acidity')
plt.ylabel('Alcohol')
plt.title('Wine Alcohol Content - Fixed Acidity - Residual Sugar',y=1.05)
通过引入尺寸的概念对三维数字类型的数据进行可视化
因此,您可以看到上图不是一个传统的散点图,而更接近于一个用不同气泡的大小表示残糖量的气泡图。 当然,我们所看到的这些数据呈现出来的模式并不是绝对的,通过其他两个维度上看到的是不同的样子。
为了对三个离散的分类属性进行可视化,我们可以使用传统的柱状图,利用色调的概念以及切面或子图来表示第三维。Seaborn框架帮助我们在最少代码量的情况下进行有效地绘图。
# Visualizing 3-D categorical data using bar plots
# leveraging the concepts of hue and facets
fc = sns.factorplot(x="quality", hue="wine_type", col="quality_label",
data=wines, kind="count",
palette={"red": "#FF9999", "white": "#FFE888"}
通过引入色调和切面的概念对三维数字类型的数据进行可视化
上图清楚地显示了与每个维度相关的频率,可以看到在理解相关洞察力方面是多么容易和有效。
考虑到三个混合属性的可视化,我们可以利用色调的概念将分组数据中的某个分类属性分开,同时使用传统的方式比如散点图来对数字属性的两个维度进行可视化。
# Visualizing 3-D mix data using scatter plots
# leveraging the concepts of hue for categorical dimension
jp = sns.pairplot(wines, x_vars=["sulphates"], y_vars=["alcohol"], size=4.5,
hue="wine_type", palette={"red": "#FF9999", "white": "#FFE888"},
plot_kws=dict(edgecolor="k", linewidth=0.5))
# we can also view relationships\correlations as needed
lp = sns.lmplot(x='sulphates', y='alcohol', hue='wine_type',
palette={"red": "#FF9999", "white": "#FFE888"},
data=wines, fit_reg=True, legend=True,
scatter_kws=dict(edgecolor="k", linewidth=0.5))
利用散点图和色调概念在三维空间中对混合属性进行可视化
因此,色调作为类别或组的一个很好的分隔符,尽管上面所观察到的相关性不强或非常弱,但我们仍然可以从这些图中了解到,与白葡萄酒相比,红葡萄酒中所含的硫酸盐略高一些。您还可以使用核密度图而不是散点图来理解三维数据。
# Visualizing 3-D mix data using kernel density plots
# leveraging the concepts of hue for categorical dimension
ax = sns.kdeplot(white_wine['sulphates'], white_wine['alcohol'],
cmap="YlOrBr", shade=True, shade_lowest=False)
ax = sns.kdeplot(red_wine['sulphates'], red_wine['alcohol'],
cmap="Reds", shade=True, shade_lowest=False)
利用核密度图和色调概念,在三维空间中对混合属性进行可视化。
很明显,与白葡萄酒相比,红葡萄酒样品的硫酸盐含量更高。你也可以根据色调的强度查看密度的大小。
如果我们要分析三个维度中的多个分类属性,可以利用色调和一个常规坐标轴来处理数据,并使用如箱形图或小提琴图来对不同的数据组进行可视化。
# Visualizing 3-D mix data using violin plots
# leveraging the concepts of hue and axes for > 1 categorical dimensions
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))
f.suptitle('Wine Type - Quality - Acidity', fontsize=14)
sns.violinplot(x="quality", y="volatile acidity",
data=wines, inner="quart", linewidth=1.3,ax=ax1)
ax1.set_xlabel("Wine Quality",size = 12,alpha=0.8)
ax1.set_ylabel("Wine Volatile Acidity",size = 12,alpha=0.8)
sns.violinplot(x="quality", y="volatile acidity", hue="wine_type",
data=wines, split=True, inner="quart", linewidth=1.3,
palette={"red": "#FF9999", "white": "white"}, ax=ax2)
ax2.set_xlabel("Wine Quality",size = 12,alpha=0.8)
ax2.set_ylabel("Wine Volatile Acidity",size = 12,alpha=0.8)
l = plt.legend(loc='upper right', title='Wine Type')
利用拆分的小提琴图和色调的概念,在三维空间中对混合属性进行可视化。
根据上图,在右边的三维可视化图中,x轴表示葡萄酒质量,wine_type表示色调, 我们可以清楚地得到一些有趣的发现,如红葡萄酒与白葡萄酒相比,挥发性酸度更高。
您也可以考虑使用箱形图通过类似的方式表示具有多个分类变量的混合属性。
# Visualizing 3-D mix data using box plots
# leveraging the concepts of hue and axes for > 1 categorical dimensions
f, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 4))
f.suptitle('Wine Type - Quality - Alcohol Content', fontsize=14)
sns.boxplot(x="quality", y="alcohol", hue="wine_type",
data=wines, palette={"red": "#FF9999", "white": "white"}, ax=ax1)
ax1.set_xlabel("Wine Quality",size = 12,alpha=0.8)
ax1.set_ylabel("Wine Alcohol %",size = 12,alpha=0.8)
sns.boxplot(x="quality_label", y="alcohol", hue="wine_type",
data=wines, palette={"red": "#FF9999", "white": "white"}, ax=ax2)
ax2.set_xlabel("Wine Quality Class",size = 12,alpha=0.8)
ax2.set_ylabel("Wine Alcohol %",size = 12,alpha=0.8)
l = plt.legend(loc='best', title='Wine Type')
利用箱形图和色调的概念,在三维空间中对混合属性进行可视化。
我们可以看到,对于quality和quality_label属性,葡萄酒酒精含量会随着质量的提高而增加;按照质量等级来分析,与白葡萄酒相比,红葡萄酒的中值酒精含量稍微高一点。 然而,如果看具体的葡萄酒级别,在较低级别的葡萄酒(3&4)中,白葡萄酒的中值酒精含量大于红葡萄酒;与白葡萄酒相比,红葡萄酒的平均酒精含量通常略高一些。
四维数据可视化
基于之前的讨论,我们可以利用图表的各种组件进行多维可视化。 对四维数据可视化的一种方法是将深度和色调用作散点图等常规图形的特定数据维度。
# Visualizing 4-D mix data using scatter plots
# leveraging the concepts of hue and depth
fig = plt.figure(figsize=(8, 6))
t = fig.suptitle('Wine Residual Sugar - Alcohol Content - Acidity - Type', fontsize=14)
ax = fig.add_subplot(111, projection='3d')
xs = list(wines['residual sugar'])
ys = list(wines['alcohol'])
zs = list(wines['fixed acidity'])
data_points = [(x, y, z) for x, y, z in zip(xs, ys, zs)]
colors = ['red' if wt == 'red' else 'yellow' for wt in list(wines['wine_type'])]
for data, color in zip(data_points, colors):
x, y, z = data
ax.scatter(x, y, z, alpha=0.4, c=color, edgecolors='none', s=30)
ax.set_xlabel('Residual Sugar')
ax.set_ylabel('Alcohol')
ax.set_zlabel('Fixed Acidity')
利用散点图和色调和深度的概念对四维数据进行可视化
从上图可以明显看出色调是表示wine_type属性的,此外,由于图表的天然复杂性,解读这些可视化数据开始变得困难,但仍然可以得到一些信息,例如红葡萄酒的固定酸度更高,白葡萄酒的残糖量更高。当然,如果酒精和固定酸度之间有某种联系,我们可能会看到一个数据点逐渐增加或减少的趋势。
另一种策略是保留二维图,但使用色调和数据点大小作为数据维度。 通常情况下,这将是一个类似于我们之前进行可视化的气泡图。
# Visualizing 4-D mix data using bubble plots
# leveraging the concepts of hue and size
size = wines['residual sugar']*25
fill_colors = ['#FF9999' if wt=='red' else '#FFE888' for wt in list(wines['wine_type'])]
edge_colors = ['red' if wt=='red' else 'orange' for wt in list(wines['wine_type'])]
plt.scatter(wines['fixed acidity'], wines['alcohol'], s=size,
alpha=0.4, color=fill_colors, edgecolors=edge_colors)
plt.xlabel('Fixed Acidity')
plt.ylabel('Alcohol')
plt.title('Wine Alcohol Content - Fixed Acidity - Residual Sugar - Type',
利用气泡图与色调和尺寸的概念,对四维数据进行可视化
我们使用色调来表示wine_type,用数据点大小来表示残糖量。我们确实看到了与前面的图表相似的模式,而白葡萄酒的气泡尺寸通常较大,表明白葡萄酒的残糖比较高。
如果我们需要用两个分类属性表示更多的东西,可以重复利用色调和切面的概念来描述这些属性,以及像散点图这样的常规图来表示数字属性。让我们看几个例子。
# Visualizing 4-D mix data using scatter plots
# leveraging the concepts of hue and facets for > 1 categorical attributes
g = sns.FacetGrid(wines, col="wine_type", hue='quality_label',
col_order=['red', 'white'], hue_order=['low', 'medium', 'high'],
aspect=1.2, size=3.5, palette=sns.light_palette('navy', 4)[1:])
g.map(plt.scatter, "volatile acidity", "alcohol", alpha=0.9,
edgecolor='white', linewidth=0.5, s=100)
fig = g.fig
fig.subplots_adjust(top=0.8, wspace=0.3)
fig.suptitle('Wine Type - Alcohol - Quality - Acidity', fontsize=14)
l = g.add_legend(title='Wine Quality Class')
利用散点图以及色调和切面的概念对四维数据进行可视化
这种可视化的有效性可以通过我们能够很容易地发现多个模式的事实来验证。白葡萄酒的挥发性酸度较低,高品质葡萄酒的酸度也较低。同样基于白葡萄酒样品,高品质的葡萄酒具有较高的酒精含量,而低品质的葡萄酒的酒精含量最低!
让我们用其他一些属性来创建一个类似的例子,并进行四维可视化。
# Visualizing 4-D mix data using scatter plots
# leveraging the concepts of hue and facets for > 1 categorical attributes
g = sns.FacetGrid(wines, col="wine_type", hue='quality_label',
col_order=['red', 'white'], hue_order=['low', 'medium', 'high'],
aspect=1.2, size=3.5, palette=sns.light_palette('navy', 4)[1:])
g.map(plt.scatter, "volatile acidity", "alcohol", alpha=0.9,
edgecolor='white', linewidth=0.5, s=100)
fig = g.fig
fig.subplots_adjust(top=0.8, wspace=0.3)
fig.suptitle('Wine Type - Alcohol - Quality - Acidity', fontsize=14)
l = g.add_legend(title='Wine Quality Class')
利用散点图以及色调和切面的概念对四维数据进行可视化
我们清楚地看到,高品质葡萄酒的总二氧化硫含量较低,如果您对葡萄酒的成分有必要的了解,就会知道这个结论非常重要。我们还发现,红葡萄酒的总二氧化硫含量低于白葡萄酒,但是在其他几个数据点上,红葡萄酒的酸度却更高。
五维数据可视化
让我们再次遵循上一节所述的类似策略,利用各种绘图组件,在五个维度中可视化数据。除了用常规轴代表其他两个维度,我们使用深度,色调和尺寸来表示三个数据维度。 由于我们使用尺寸的概念,我们将会画出一个三维气泡图。
# Visualizing 5-D mix data using bubble charts
# leveraging the concepts of hue, size and depth
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
t = fig.suptitle('Wine Residual Sugar - Alcohol Content - Acidity - Total Sulfur Dioxide - Type', fontsize=14)
xs = list(wines['residual sugar'])
ys = list(wines['alcohol'])
zs = list(wines['fixed acidity'])
data_points = [(x, y, z) for x, y, z in zip(xs, ys, zs)]
ss = list(wines['total sulfur dioxide'])
colors = ['red' if wt == 'red' else 'yellow' for wt in list(wines['wine_type'])]
for data, color, size in zip(data_points, colors, ss):
x, y, z = data
ax.scatter(x, y, z, alpha=0.4, c=color, edgecolors='none', s=size)
ax.set_xlabel('Residual Sugar')
ax.set_ylabel('Alcohol')
ax.set_zlabel('Fixed Acidity')
利用气泡图和色调,深度和尺寸的概念,对五维数据进行可视化
这个图表描述了我们在前一节中讨论的相同模式和见解,同时也可以看到,根据表示二氧化硫总量的点的大小,与红葡萄酒相比,白葡萄酒的二氧化硫总量更高。
# Visualizing 5-D mix data using bubble charts
# leveraging the concepts of hue, size and depth
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
t = fig.suptitle('Wine Residual Sugar - Alcohol Content - Acidity - Total Sulfur Dioxide - Type', fontsize=14)
xs = list(wines['residual sugar'])
ys = list(wines['alcohol'])
zs = list(wines['fixed acidity'])
data_points = [(x, y, z) for x, y, z in zip(xs, ys, zs)]
ss = list(wines['total sulfur dioxide'])
colors = ['red' if wt == 'red' else 'yellow' for wt in list(wines['wine_type'])]
for data, color, size in zip(data_points, colors, ss):
x, y, z = data
ax.scatter(x, y, z, alpha=0.4, c=color, edgecolors='none', s=size)
ax.set_xlabel('Residual Sugar')
ax.set_ylabel('Alcohol')
ax.set_zlabel('Fixed Acidity')
利用气泡图和色调,切面和大小的概念,对五维数据进行可视化。
除了深度之外,我们还可以使用切面和色调来表示这五个数据维度中的多个分类属性。表示大小的属性之一可以是数字的(连续)或者甚至是分类的(但是我们可能需要用代表数据点大小的数字来表示它)。 虽然因为缺乏分类属性,我们在这里并没有对此进行描述,但是您可以在自己的数据集上进行尝试。
这基本上是另一种替代方法来对我们以前绘制的图进行五维可视化。 虽然在观察之前绘制的图表时,表示深度的附加维度可能会让很多人感到困惑,但由于切面的优势,这个图依然在二维平面上保持有效,因此通常更有效且易于解释。
我们已经看到,处理如此多的数据维度变得越来越复杂! 会不会有人在想,为什么不增加更多的维度呢?让我们来试试看吧!
六维数据可视化
希望接下来的尝试更加有趣。让我们在可视化中添加另一个数据维度,除了常规的两个轴,我们将利用深度,色调,大小和形状,来描述所有六个数据维度。
# Visualizing 6-D mix data using scatter charts
# leveraging the concepts of hue, size, depth and shape
fig = plt.figure(figsize=(8, 6))
t = fig.suptitle('Wine Residual Sugar - Alcohol Content - Acidity - Total Sulfur Dioxide - Type - Quality', fontsize=14)
ax = fig.add_subplot(111, projection='3d')
xs = list(wines['residual sugar'])
ys = list(wines['alcohol'])
zs = list(wines['fixed acidity'])
data_points = [(x, y, z) for x, y, z in zip(xs, ys, zs)]
ss = list(wines['total sulfur dioxide'])
colors = ['red' if wt == 'red' else 'yellow' for wt in list(wines['wine_type'])]
markers = [',' if q == 'high' else 'x' if q == 'medium' else 'o' for q in list(wines['quality_label'])]
for data, color, size, mark in zip(data_points, colors, ss, markers):
x, y, z = data
ax.scatter(x, y, z, alpha=0.4, c=color, edgecolors='none', s=size, marker=mark)
ax.set_xlabel('Residual Sugar')
ax.set_ylabel('Alcohol')
ax.set_zlabel('Fixed Acidity')
利用散点图和色调,深度,形状和大小的概念,对六维数据进行可视化
这是六个维度在一个图中。我们用形状表示葡萄酒的属性quality_label ,用高(平方像素),中(X标记)和低(圆)表示葡萄酒的品质,葡萄酒类型以色调表示,深度表示固定酸度,数据点大小表示总二氧化硫含量。
解释这些似乎有点费力,但当您尝试理解正在发生什么的时候,请考虑以下几部分。
1.考虑形状和Y轴,与低品质的葡萄酒相比,中高品质的葡萄酒酒精含量更高;
2.考虑色调和大小,白葡萄酒的总二氧化硫含量比红葡萄酒要高。
3.考虑深度和色调,与红葡萄酒相比,白葡萄酒具有较低的固定酸度。
4.考虑色调和x轴,红葡萄酒与白葡萄酒相比残糖量较低。
5.考虑色调和形状,白葡萄酒与红葡萄酒相比似乎具有更高的品质(可能是由于白葡萄酒的样本量较大)。
我们还可以去掉深度的概念并将切面用于分类属性,来创建6维可视化,
# Visualizing 6-D mix data using scatter charts
# leveraging the concepts of hue, facets and size
g = sns.FacetGrid(wines, row='wine_type', col="quality", hue='quality_label', size=4)
g.map(plt.scatter, "residual sugar", "alcohol", alpha=0.5,
edgecolor='k', linewidth=0.5, s=wines['total sulfur dioxide']*2)
fig = g.fig
fig.set_size_inches(18, 8)
fig.subplots_adjust(top=0.85, wspace=0.3)
fig.suptitle('Wine Type - Sulfur Dioxide - Residual Sugar - Alcohol - Quality Class - Quality Rating', fontsize=14)
l = g.add_legend(title='Wine Quality Class')
利用散点图和色调,切面和大小的概念,以六维可视化数据
因此,在这种情况下,我们利用色调和切面来表示三个分类属性,并使用两个常规坐标轴和大小来表示六维数据可视化的三个数字属性。
结论
数据可视化既是一门艺术,也是一门科学。 如果您正在阅读本文,我真的很赞赏您在阅读这篇文章时的做出的努力。本文的目的不是为了记忆任何事情,也不是要给出一套固定的数据可视化规则。 这里的主要目标是了解和学习一些有效的数据可视化策略,特别是当维数开始增加时,希望您将这些代码用于将来可视化自己的数据集。欢迎在评论中留下您的反馈意见,并分享您自己的数据可视化的有效策略,尤其是如果您可以做得更好。
本文中使用的所有代码和数据集都可以从我的GitHub访问得到。
您也可以通过Jupyter笔记访问代码。
译者简介
张媛,某云计算公司不务正业服务工程师一枚。喜欢下雨天,读闲书,缺乏技术细胞,欣赏并喜欢有态度有立场的人,爱浪漫,注重仪式感,喜欢记录。最近的愿望是拥有自己的小窝,给想念的人写一封信。
转载须知
如需转载,请在开篇显著位置注明作者和出处(转自:数据派ID:datapi),并在文章结尾放置数据派醒目二维码。有原创标识文章,请发送【文章名称-待授权公众号名称及ID】至联系邮箱,申请白名单授权并按要求编辑。
发布后请将链接反馈至联系邮箱(见下方)。未经许可的转载以及改编者,我们将依法追究其法律责任。
领取专属 10元无门槛券
私享最新 技术干货