数据分析 BY 伦大锤 阅读量 1,627
在“基本图形”中所接触的图形,主要用于展示单类别型或连续型变量的分布情况,此处将介绍更多用于展示双变量间关系(二元关系)和多变量间关系(多元关系)的绘图方法。
散点图可用来描述两个连续型变量间的关系,让我们从最简单的plot()函数出发。
1
2
3
4
|
attach
(
mtcars
)
plot
(
wt
,
mpg
,
main
=
"Basic Scatter Plot of MPG vs. Weight"
,
xlab
=
"Car Weight(lbs/1000)"
,
ylab
=
"Miles Per Gallon"
,
pch
=
19
)
abline
(
lm
(
mpg
~
wt
)
,
col
=
"red"
,
lwd
=
2
,
lty
=
1
)
lines
(
lowess
(
wt
,
mpg
)
,
col
=
"blue"
,
lwd
=
2
,
lty
=
2
)
|
生成的图形中包括散点图、一条最佳拟合直线(abline)和一条平滑曲线(lowess)。
现在使用car包中的scatterplot()函数绘制一个增强的版本,绘制不同气缸数量汽车每加仑英里数对车重的图形,包括散点图、拟合直线和平滑曲线。
1
2
|
library
(
car
)
scatterplot
(
mpg
~
wt
|
cyl
,
data
=
mtcars
,
lwd
=
2
,
main
=
"Scatter Plot of MPG vs. Weight by # Cylinders"
,
xlab
=
"Weight of Car(lbs/1000)"
,
ylab
=
"Miles Per Gallon"
,
legend
.
plot
=
TRUE
,
id
.
method
=
"identify"
,
labels
=
row
.
names
(
mtcars
)
,
boxplots
=
"xy"
)
|
散点图矩阵用于展示多幅散点图,pairs()函数可以创建基础的散点图矩阵,以下代码包含mpg、disp、drat和wt中任意两者的散点图。
1
|
pairs
(
~
mpg
+
disp
+
drat
+
wt
,
data
=
mtcars
,
main
=
"Basic Scatter Plot Matrix"
)
|
car包的scatterplotMatrix()函数也可以生成散点图矩阵,并支持以下操作:
1
2
|
library
(
car
)
scatterplotMatrix
(
~
mpg
+
disp
+
drat
+
wt
,
data
=
mtcars
,
spread
=
FALSE
,
lty
.
smooth
=
2
,
main
=
"Scatter Plot Matrix via car Package"
)
|
spread=FALSE选项表示不添加展示分散度和对称信息的直线。
再来一个scatterplotMatrix()函数的使用例子,主对角线的核密度曲线改为了直方图,并且直方图以汽车气缸数为条件绘制。
1
2
|
library
(
car
)
scatterplotMatrix
(
~
mpg
+
disp
+
drat
+
wt
|
cyl
,
data
=
mtcars
,
spread
=
FALSE
,
diagonal
=
"histogram"
,
main
=
"Scatter Plot Matrix via car Package"
)
|
gclus包中的cpairs()函数提供了一个有趣的散点图矩阵变种,支持重排矩阵中变量的位置,让相关性更高的变量更靠近主对角线,还可以对各单元格进行颜色编码来展示变量间的相关性大小。
首先查看各个变量之间相关性的大小:
1
|
cor
(
mtcars
[
c
(
"mpg"
,
"wt"
,
"disp"
,
"drat"
)
]
)
|
可以发现相关性最高(0.89)的是车重(wt)和排量(disp),以及车重(wt)和每加仑英里数(mpg)。相关性最低(0.68)的是每加仑英里数(mpg)和后轴比(drat)。以下代码根据相关性大小,对散点图矩阵中的这些变量重新排序并着色。
1
2
3
4
5
6
|
library
(
gclus
)
mydata
<
-
mtcars
[
c
(
1
,
3
,
5
,
6
)
]
mydata
.
corr
<
-
abs
(
cor
(
mydata
)
)
mycolors
<
-
dmat
.
color
(
mydata
.
corr
)
myorder
<
-
order
.
single
(
mydata
.
corr
)
cpairs
(
mydata
,
myorder
,
panel
.
colors
=
mycolors
,
gap
=
.
5
,
main
=
"Variables Ordered and Colored by Correlation"
)
|
当散点图中点数量过大时,数据点的重叠将会导致绘图效果显著变差。对于这种情况,可以使用封箱、颜色和透明度等来指定图中任意点上重叠点的数目。
smoothScatter()函数可利用核密度估计生成用颜色密度来表示点分布的散点图。
1
2
3
4
5
6
7
8
|
set
.
seed
(
1234
)
n
<
-
10000
c1
<
-
matrix
(
rnorm
(
n
,
mean
=
0
,
sd
=
.
5
)
,
ncol
=
2
)
c2
<
-
matrix
(
rnorm
(
n
,
mean
=
3
,
sd
=
2
)
,
ncol
=
2
)
mydata
<
-
rbind
(
c1
,
c2
)
mydata
<
-
as
.
data
.
frame
(
mydata
)
names
(
mydata
)
<
-
c
(
"x"
,
"y"
)
smoothScatter
(
mydata
$
x
,
mydata
$
y
,
main
=
"Scatterplot Colored by Smoothed Densities"
)
|
hexbin包中的hexbin()函数将二元变量的封箱放到六边形单元格中。
1
2
3
|
library
(
hexbin
)
bin
<
-
hexbin
(
mydata
$
x
,
mydata
$
y
,
xbins
=
50
)
plot
(
bin
,
main
=
"Hexagonal Binning with 10000 Observations"
)
|
IDPmisc包中的iplot()函数也可以通过颜色来展示点的密度。
1
2
|
library
(
IDPmisc
)
iplot
(
mydata
$
x
,
mydata
$
y
,
main
=
"Image Scatter Plot with Color Indicating Density"
)
|
如果想一次性对三个定量变量的交互进行可视化,那么可以使用scatterplot3d中的scatterplot3d()函数进行绘制。
1
2
3
4
|
library
(
scatterplot3d
)
attach
(
mtcars
)
scatterplot3d
(
wt
,
disp
,
mpg
,
main
=
"Basic 3D Scatter Plot"
)
detach
(
mtcars
)
|
scatterplot3d()函数提供了许多选项,包括设置图形符号、轴、颜色、线条、网格线、突出显示和角度等功能。例如以下代码生成一幅突出显示效果的三维散点图,增强了纵深感并添加了连接点与水平面的垂直线。
1
2
3
4
|
library
(
scatterplot3d
)
attach
(
mtcars
)
scatterplot3d
(
wt
,
disp
,
mpg
,
pch
=
16
,
highlight
.
3d
=
TRUE
,
type
=
"h"
,
main
=
"3D Scatter Plot with Vertical Lines"
)
detach
(
mtcars
)
|
还可以再加上一个回归面。
1
2
3
4
5
6
|
library
(
scatterplot3d
)
attach
(
mtcars
)
s3d
<
-
scatterplot3d
(
wt
,
disp
,
mpg
,
pch
=
16
,
highlight
.
3d
=
TRUE
,
type
=
"h"
,
main
=
"3D Scatter Plot with Vertical Lines and Regression Plane"
)
fit
<
-
lm
(
mpg
~
wt
+
disp
)
s3d
$
plane3d
(
fit
)
detach
(
mtcars
)
|
使用rgl包中的plot3d()函数可创建交互式的三维散点图,通过鼠标即可对图形进行旋转。
1
2
3
4
|
library
(
rgl
)
attach
(
mtcars
)
plot3d
(
wt
,
disp
,
mpg
,
col
=
"red"
,
size
=
5
)
detach
(
mtcars
)
|
Rcmdr包中的scatter3d()函数可以实现类似功能。
1
2
3
4
|
library
(
Rcmdr
)
attach
(
mtcars
)
scatter3d
(
wt
,
disp
,
mpg
)
detach
(
mtcars
)
|
三维散点图用z轴表示第三个变量的大小,另一种思路是:先创建一个二维散点图,然后用点的大小来代表第三个变量的值,即气泡图。
使用symbols()函数来创建气泡图,支持的形状包括圆圈图、方形图、星形图、温度计图和箱线图,以绘制圆圈图为例:
1
|
symbols
(
x
,
y
,
circle
=
radius
)
|
如果想用面积而不是半径来表示第三个变量,则需要进行转换:
1
|
symbols
(
x
,
y
,
circle
=
sqrt
(
z
/
pi
)
)
|
以下代码中,x轴表示车重,y轴表示每加仑英里数,气泡大小表示发动机排量。
1
2
3
4
5
|
attach
(
mtcars
)
r
<
-
sqrt
(
disp
/
pi
)
symbols
(
wt
,
mpg
,
circle
=
r
,
inches
=
.
30
,
fg
=
"white"
,
bg
=
"lightblue"
,
main
=
"Bubble Plot with Point Size Proportional to Displacement"
,
ylab
=
"Miles Per Gallon"
,
xlab
=
"Weight of Car"
)
text
(
wt
,
mpg
,
rownames
(
mtcars
)
,
cex
=
.
5
)
detach
(
mtcars
)
|
一般来说,统计人员使用R时都倾向于避免使用气泡图,原因和避免使用饼图一样:相对于长度的判断,人们对体积/面积的判断通常更加困难。
将散点图上的点从左往右连接起来,即可得到折线图。以基础安装中的Orange数据集为例,绘制第一种树数据的散点图和折线图。
1
2
3
4
5
6
|
opar
<
-
par
(
no
.
readonly
=
TRUE
)
par
(
mfrow
=
c
(
1
,
2
)
)
t1
<
-
subset
(
Orange
,
Tree
==
1
)
plot
(
t1
$
age
,
t1
$
circumference
,
xlab
=
"Age(days)"
,
ylab
=
"Circumference(mm)"
,
main
=
"Orange Tree 1 Growth"
)
plot
(
t1
$
age
,
t1
$
circumference
,
xlab
=
"Age(days)"
,
ylab
=
"Circumference(mm)"
,
main
=
"Orange Tree 1 Growth"
,
type
=
"b"
)
par
(
opar
)
|
两幅图的区别取决于参数type=”b”,折线图一般可用以下两个函数之一来创建:
1
2
|
plot
(
x
,
y
,
type
=
)
lines
(
x
,
y
,
type
=
)
|
type=可选值如下:
以下展示一个更复杂的折线图创建过程,每种树都有自己独有的线条。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Orange
$
Tree
<
-
as
.
numeric
(
Orange
$
Tree
)
ntrees
<
-
max
(
Orange
$
Tree
)
xrange
<
-
range
(
Orange
$
age
)
yrange
<
-
range
(
Orange
$
circumference
)
plot
(
xrange
,
yrange
,
type
=
"n"
,
xlab
=
"Age(days)"
,
ylab
=
"Circumference(mm)"
)
colors
<
-
rainbow
(
ntrees
)
linetype
<
-
c
(
1
:
ntrees
)
plotchar
<
-
seq
(
18
,
18
+
ntrees
,
1
)
for
(
i
in
1
:
ntrees
)
{
tree
<
-
subset
(
Orange
,
Tree
==
i
)
lines
(
tree
$
age
,
tree
$
circumference
,
type
=
"b"
,
lwd
=
2
,
lty
=
linetype
[
i
]
,
col
=
colors
[
i
]
,
pch
=
plotchar
[
i
]
)
}
title
(
"Tree Growth"
,
"example of line plot"
)
legend
(
xrange
[
1
]
,
yrange
[
2
]
,
1
:
ntrees
,
cex
=
.
8
,
col
=
colors
,
pch
=
plotchar
,
lty
=
linetype
,
title
=
"Tree"
)
|
相关图通过对相关系数矩阵的可视化,来回答多个被考察变量之间相关性强弱的问题。
以mtcars数据框为例,其包含了11个变量,每个变量都有32个观测,使用以下代码获得各变量间的相关系数。
1
|
cor
(
mtcars
)
|
仅凭借以上相关系数矩阵难以快速直观得反映出变量间相关性的强弱,corrgram包中的corrgram()函数可以用图形方式展示该相关系数矩阵。
1
2
|
library
(
corrgram
)
corrgram
(
mtcars
,
order
=
TRUE
,
lower
.
panel
=
panel
.
shade
,
upper
.
panel
=
panel
.
pie
,
text
.
panel
=
panel
.
txt
,
main
=
"Correlogram of matchers intercorrelations"
)
|
先解释左下方的单元格:蓝色单元格表示两变量呈正相关,红色单元格表示两变量呈负相关,颜色越深、饱和度越高,相关性越强。为了将有相似相关模式的变量聚集在一起,对矩阵的行和列都重新进行了排序(使用主成分法)。
右上方的饼图原理类似:蓝色表示正相关,红色表示负相关,相关性的强弱用饼图填充的大小来表示。
lower.panel和upper.panel参数指定了左下方和右上方图形的形式,可选的参数有:NULL(无内容)、panel.pie(饼图填充)、panel.shade(阴影深度)、panel.ellipse(置信椭圆)和panel.pts(平滑拟合曲线),还可以通过“diag.panel=panel.minmax”在对角线输出变量的最大最小值。不妨再试试以下例子:
1
2
|
library
(
corrgram
)
corrgram
(
mtcars
,
order
=
TRUE
,
lower
.
panel
=
panel
.
ellipse
,
upper
.
panel
=
panel
.
pts
,
text
.
panel
=
panel
.
txt
,
diag
.
panel
=
panel
.
minmax
,
main
=
"Correlogram of mtcars data using scatter plots and ellipse"
)
|
以上讨论内容解决了可视化定量或连续型变量间关系的方法,如果是类别型变量,而且是多个(单个可以用柱状图或饼图、两个可以用三维柱状图)类别型变量间的关系,可以考虑马赛克图。
在马赛克图中,嵌套矩行面积正比于单元格频率,其中该频率即为多维列联表中的频率,颜色和/或阴影可表示拟合模型的残差值。
vcd包中的mosaic()函数可以绘制马赛克图(R基础安装中的mosaicplot()函数也可以绘制马赛克图,但是功能相对较弱),以基础安装中的Titanic数据集为例,它包含存活或死亡的乘客数、乘客的船舱等级(一等、二等、三等和船员)、性别(男性、女性),以及年龄层(儿童、成人)。
以多维列联表的形式查看Titanic数据集:
1
|
ftable
(
Titanic
)
|
mosaic()函数调用格式如下:
1
|
mosaic
(
table
)
|
其中table是数组形式的列联表,另外也可以用:
1
|
mosaic
(
formula
,
data
=
)
|
其中formula是标准的R表达式,data为数据框或表格,添加shade=TRUE将根据拟合模型的Pearson残差值对图形上色,添加legend=TRUE将展示残差值图例。以下两种方法都可以生成马赛克图,但是使用表达式允许对图形中变量的选择和摆放拥有更多的控制权。
1
2
3
|
mosaic
(
Titanic
,
shade
=
TRUE
,
legend
=
TRUE
)
# or in another way
mosaic
(
~
Class
+
Sex
+
Age
+
Survived
,
data
=
Titanic
,
shade
=
TRUE
,
legend
=
TRUE
)
|
可以从马赛克图中得到很多信息:
数据分析 BY 伦大锤 阅读量 1,934
除了R中的基础图形之外,grid、lattice和ggplot2等软件包也提供了图形系统,它们克服了R基础图形系统的低效性,大大地扩展了R的绘图能力。
grid图形系统可以很容易地控制图形基础单元,给予编程者创作图形极大的灵活性。lattice包通过一维、二维或三维条件绘图,即所谓的栅栏(trellis)图形来对多元变量关系进行直观展示。ggplot2包则基于一种全面的图形“语法”,提供了一种全新的图形创建方法。
R中的四种图形系统即,基础图形系统、grid、lattice和ggplot2,基础图形无须安装和加载即可使用,grid和lattice使用前需要加载对应的包,而ggplot2还需要安装并加载。
在一个或多个其他变量的条件下,栅栏图形展示某个变量的分布或与其他变量间的关系。以lattice包中的singer数据集为例,其包含了合唱成员的身高和声部数据,来看以下代码:
1
2
|
library
(
lattice
)
histogram
(
~
height
|
voice
.
part
,
data
=
singer
,
main
=
"Distribution of Heights by Voice Pitch"
,
xlab
=
"Height(inches)"
)
|
height为因变量,voice.part被称为条件变量,以上代码对八个声部的每一个都创建一个直方图,图形显示男高音和男低音比女低音和女高音身高都要高。
在栅栏图形中,单个面板要依据条件变量的各个水平来创建。如果指定了多个条件变量,那么一个面板将按照各个因子水平的组合来创建。面板将被排成一个阵列以进行比较,用户可对每个面板中展示的图形、面板的格式和位置、面板的摆放、图例的内容和位置以及其他许多图形特征进行控制。
lattice包的高级绘图都服从以下格式:
1
|
graph_function
(
formula
,
data
=
,
options
)
|
其中formula指定要展示的变量和条件变量,data指定一个数据框,options为逗号分隔参数,用来修改图形的内容、摆放方式和标注,graph_function可以是以下函数:
设小写字母代表数值型变量,大写字母代表类别型变量(因子),在高级绘图函数中,表达式形式通常为:
1
|
y
~
x
|
A
*
B
|
竖线左边的变量为主要变量,右边的变量为条件变量。主要变量将变量映射到每个面板的坐标轴上。尝试运行以下代码,加深对以上表达式的理解,图形基于数据框mtcars中的小汽车数据绘制而成。
1
2
3
4
5
6
7
8
9
10
11
12
|
library
(
lattice
)
attach
(
mtcars
)
gear
<
-
factor
(
gear
,
levels
=
c
(
3
,
4
,
5
)
,
labels
=
c
(
"3 gears"
,
"4 gears"
,
"5 gears"
)
)
cyl
<
-
factor
(
cyl
,
levels
=
c
(
4
,
6
,
8
)
,
labels
=
c
(
"4 cylinders"
,
"6 cylinders"
,
"8 cylinders"
)
)
densityplot
(
~
mpg
,
main
=
"Density Plot"
,
xlab
=
"Miles Per Gallon"
)
densityplot
(
~
mpg
|
cyl
,
main
=
"Density Plot by Number of Cylinders"
,
xlab
=
"Miles Per Gallon"
)
bwplot
(
cyl
~
mpg
|
gear
,
main
=
"Box Plots by Cylinders and Gears"
,
xlab
=
"Miles Per Gallon"
,
ylab
=
"Cylinders"
)
xyplot
(
mpg
~
wt
|
cyl
*
gear
,
main
=
"Scatter Plots by Cylinders and Gears"
,
xlab
=
"Car Weight"
,
ylab
=
"Miles Per Gallon"
)
cloud
(
mpg
~
wt
*
qsec
|
cyl
,
main
=
"3D Scatter Plots by Cylinders"
)
dotplot
(
cyl
~
mpg
|
gear
,
main
=
"Dot Plots by Number of Gears and Cylinders"
,
xlab
=
"Miles Per Gallon"
)
splom
(
mtcars
[
c
(
1
,
3
,
4
,
5
,
6
)
]
,
main
=
"Scatter Plot Matrix for Mtcars Data"
)
detach
(
mtcars
)
|
可以将lattice包高级绘图函数生成的图形存储至变量,以进一步操作和管理。
1
2
|
library
(
lattice
)
mygraph
<
-
densityplot
(
~
height
|
voice
.
part
,
data
=
singer
)
|
以上代码创建了一个栅栏密度图并存储在mygraph对象中。此时不会展示任何图形,只有调用plot(mygraph)或mygraph时才会展示图形。通过使用options,可以轻松地修改lattice图形,或者在图形对象生成之后使用update()函数:
1
|
update
(
mygraph
,
col
=
"red"
,
pch
=
16
,
cex
=
.
8
,
jitter
=
.
05
,
lwd
=
2
)
|
lattice图形的一个最强大之处便是可以添加条件变量,并创建和每个条件变量水平对应的图形面板。
通常,条件变量是因子。如果希望以连续型变量为条件,那么一种方法是使用R的cut()函数将连续型变量转换为离散变量,另一种方法是使用lattice包中提供的函数。lattice包提供了一些将连续型变量转化为瓦块(shingle)数据结构的函数,特别的,连续型变量会被分割到一系列(可能)重叠的数值范围中。
1
|
myshingle
<
-
equal
.
count
(
x
,
number
=
#, overlap=proportion)
|
以上函数会把连续型变量x分割到#个区间中,重叠度为proportion,每个数值范围内观测数量相等,并返回为一个变量myshingle,输出或绘制该对象将会展示瓦块区间。
以mtcars为例,将发动机排量转化为一个三水平的瓦块变量并使用,代码还使用选项修改了面板的布局和宽高比,以便于比较。
1
2
|
displacement
<
-
equal
.
count
(
mtcars
$
disp
,
number
=
3
,
overlap
=
0
)
xyplot
(
mpg
~
wt
|
displacement
,
data
=
mtcars
,
main
=
"Miles Per Gallon vs. Weight by Engine Displacement"
,
xlab
=
"Weight"
,
ylab
=
"Miles Per Gallon"
,
layout
=
c
(
3
,
1
)
,
aspect
=
1.5
)
|
lattice包中的每个高级绘图函数都调用了一个默认的绘图函数来绘制面板,如以下两种形式是等价的:
1
2
|
xyplot
(
mpg
~
wt
|
displacement
,
data
=
mtcars
)
xyplot
(
mpg
~
wt
|
displacement
,
data
=
mtcars
,
panel
=
panel
.
xyplot
)
|
你可以使用自定义函数替换默认的函数,或者将一个或多个默认函数整合至自定义函数中,这意味着面板的绘制具备了极大的灵活性。
之前的例子绘制了mtcars数据集中mpg、wt和disp等变量间关系的散点图,如果需要添加回归线、轴须线和网格线,则需要创建自己的面板函数。
1
2
3
4
5
6
7
8
|
displacement
<
-
equal
.
count
(
mtcars
$
disp
,
number
=
3
,
overlap
=
0
)
mypanel
<
-
function
(
x
,
y
)
{
panel
.
xyplot
(
x
,
y
,
pch
=
19
)
panel
.
rug
(
x
,
y
)
panel
.
grid
(
h
=
-
1
,
v
=
-
1
)
panel
.
lmline
(
x
,
y
,
col
=
"red"
,
lwd
=
1
,
lty
=
2
)
}
xyplot
(
mpg
~
wt
|
displacement
,
data
=
mtcars
,
layout
=
c
(
3
,
1
)
,
aspect
=
1.5
,
main
=
"Miles Per Gallon vs. Weight by Engine Displacement"
,
xlab
=
"Weight"
,
ylab
=
"Miles Per Gallon"
,
panel
=
mypanel
)
|
再来看一个例子,绘制以汽车传动类型为条件时每加仑英里数与发动机排量(连续型变量)的关系图。
1
2
3
4
5
6
7
8
9
|
library
(
lattice
)
mtcars
$
transmission
<
-
factor
(
mtcars
$
am
,
levels
=
c
(
0
,
1
)
,
labels
=
c
(
"Automatic"
,
"Manual"
)
)
panel
.
smoother
<
-
function
(
x
,
y
)
{
panel
.
grid
(
h
=
-
1
,
v
=
-
1
)
panel
.
xyplot
(
x
,
y
)
panel
.
loess
(
x
,
y
)
panel
.
abline
(
h
=
mean
(
y
)
,
lwd
=
2
,
lty
=
2
,
col
=
"green"
)
}
xyplot
(
mpg
~
disp
|
transmission
,
data
=
mtcars
,
scales
=
list
(
cex
=
.
8
,
col
=
"red"
)
,
panel
=
panel
.
smoother
,
xlab
=
"Displacement"
,
ylab
=
"Miles Per Gallon"
,
main
=
"MPG vs. Displacement by Transmission Type"
,
sub
=
"Dotted lines are Group Means"
,
aspect
=
1
)
|
当一个lattice图形表达式含有条件变量时,将会生成在该变量各个水平下的面板。若希望将结果叠加在一起,则需要将变量设定为分组变量(grouping variable)。以下代码用核密度图展示手动档和自动挡汽车的每加仑英里数分布情况。
1
2
3
|
library
(
lattice
)
mtcars
$
transmission
<
-
factor
(
mtcars
$
am
,
levels
=
c
(
0
,
1
)
,
labels
=
c
(
"Automatic"
,
"Manual"
)
)
densityplot
(
~
mpg
,
|