最近在写深度学习系列文章时遇到了一些瓶颈, 不少统计分析结果和函数激活图像都须要可视化显示, 可是不太擅长这方面的相关技术, 因此先暂停理论知识更新, 准备用2天时间, 掌握一下基于R的ggplot2的可视化分析技术.git
图形语法部分计划写的的大纲以下:算法
图形语法由Wilkinson建立, 这里不作形而上学的晦涩描述, 简单来说, 图形语法回答了"什么是统计图形"这一问题.express
那么, 什么是统计图形?
一个图形就是一种映射再加一些补充信息:app
几个重要名词的补充说明:
几何对象: 点, 线, 多边形;
标度: 数据取值映射到图形空间;
统计变换: 对数据的某种汇总, 如数据分组计数建立直方图;
分面: 绘图窗口拆分红多个子窗口, 也叫网格做图.框架
注:
该小节只是对图形与发的几个名词作了基本解释, 后面将对ggplot2的图形语法作深刻讲解.ide
qplot()是ggplot2的一个入门级做图函数, 意思是quick plot. 利用它可方便作出各类复杂图形.
qplot和R的plot很像, 使用方法也差很少, 完整的参数列表可经过help(qplot)
或者?qplot
来获取.函数
安装tidyverse包并加载:工具
install.packages('tidyverse') library(tidyverse)
注意:
tidyverse是一个集合各类经常使用R包的综合大礼包。安装并library(tidyverse)
后, 默认导入如下包括ggplot2在内的多个依赖包:学习
# console output: ─────── Attaching packages ──────── ✔ ggplot2 2.2.1 ✔ purrr 0.2.4 ✔ tibble 1.3.4 ✔ dplyr 0.7.4 ✔ tidyr 0.7.2 ✔ stringr 1.2.0 ✔ readr 1.1.1 ✔ forcats 0.2.0
或者也能够单独安装ggplot2:大数据
install.packages('ggplot2') library(ggplot2)
使用qqplot2自带的diamonds
数据集.
建立一个小数据集:
set.seed(1000) dsmall <- diamonds[sample(nrow(diamonds), 100), ]
qplot() usage:
qplot(x, y = NULL, ..., data, facets = NULL, margins = FALSE, geom = "auto", xlim = c(NA, NA), ylim = c(NA, NA), log = "", main = NULL, xlab = deparse(substitute(x)), ylab = deparse(substitute(y)), asp = NA, stat = NULL, position = NULL)
require(ggplot2) set.seed(1410) dsmall <- diamonds[sample(nrow(diamonds),100),] qplot(carat, price, data=diamonds) # 注: carat, price是diamonds数据集的两列, 分别映射到qplot()的x和y上
qplot(log(carat), log(price), data=diamonds) # 求log(carat)关于log(price)的关系
添加颜色:
qplot(carat, price, data=dsmall, colour=color)
添加形状:
qplot(carat, price, data=dsmall, shape=cut, colour=color)
颜色, 形状和大小都是图形属性的具体例子,每一个图形属性都对应了一个标度函数,将数据取值映射到图形属性的有效取值上, 如上图, dsmall数据集中cut列每个取值都被映射成了一种散点形状, 右侧图形标度除了各类颜色和图形的映射关系.
使用透明度控制颜色和取值的映射, 能够有效减轻图形元素重叠现象, 使用alpha
的图形属性, 取值从0到1, 一般透明度用分数表示, 如1/10, 1/20, 分母表示重叠多少次后颜色将不透明:
qplot(carat, price, data=diamonds, alpha=(1/10))
gplot()经过改变几何对象, 几乎能够画出任何一种类型的图形, 不一样的几何对象描述了数据展现的不一样方式, 特别地, 有些几何对象须要关联相应的统计变换, 如频率直方图须要先分组计数再加上条形几何对象.
常见的二维变量关系:
常见的一维分布:
数据平滑曲线可用来展现大量数据点的某种趋势, 能够利用c()
函数将多个几何对象组成向量传给geom
, 几何对象的堆叠顺序和传递顺序一致:
qplot(carat, price, data = diamonds, geom = c("point", "smooth")) qplot(carat, price, data = diamonds, geom = c("point", "smooth"), se = FALSE) # 不包含标准偏差
下图展现了默认参数的的平滑曲线:
i) 包含标准偏差:
ii) 不包含标准偏差:
从平滑曲线中咱们能够看出carat和price之间近似的指数关系;
ggplot内置了不少平滑器:
小数据集:
n<= 1000, 默认平滑器为method = 'loess'
算法: 局部回归
取值: 曲线平滑程度由span参数控制,取值0(很不平滑)->1(很平滑)
大数据集
n>1000, Loess对大数据集并不合适(内存消耗O(n^2)), 此时使用的平滑器为method = 'gam'
算法: formula = y ~ s(x)
调用mgcv包拟合一个广义加和模型, 标准平滑公式: y~s(x, bs='cs')
线性拟合
拟合一条直线, method = 'lm', 也能够经过formula = y ~ poly(x,2)
拟合一个二次多项式.
method = 'rlm'和前者相似, 可是更稳健, 对异常值不太敏感.
假设横轴x = c('D','E','F','G','H','I','J')是一个包含7种颜色的分类变量, y是一个或多个连续变量.
经过箱线图和扰动点图能够知道连续变量是如何随着分类变量的变化而变化的:
扰动点图:
qplot(color, price/carat, data = diamonds, geom = 'jitter', alpha = I(1/40))
箱线图:
qplot(color, price/carat, data = diamonds, geom = 'boxplot', alpha = I(1/5))
总结:
直方图
频数直方图:
qplot(carat, data = diamonds, geom = 'histogram')
密度直方图:
qplot(carat, ..density.., data = diamonds, geom = 'histogram')
密度直方图将数据分组求密度后映射到Y轴, 而频数直方图将数据分组计数后映射到Y轴.
分组(fill
)及平滑度(binwidth
)调整:
qplot(carat, data = diamonds, geom = 'histogram', binwidth=0.1, fill=color)
密度曲线
qplot(carat, data = diamonds, geom = 'density')
分组(colour
)及平滑度(adjust
)调整:
qplot(carat, data = diamonds, geom = 'density', adjust = 0.8, colour = color)
总结
频率条形图
qplot(color, data = diamonds, geom = 'bar')
按值加权条形图
qplot(color, data = diamonds, geom = 'bar', weight = carat) + scale_y_continuous("carat")
注意:
上述两图纵坐标不一样,第一张图展现了各颜色的频率分布, 第二张图展现carat属性的值在各类颜色上的加权和, 物理意义: 每种颜色的钻石的总重量.
线条图和路径图经常使用来可视化时间序列数据.
新数据集
ggplot2自带economics数据集, 该数据集包含美国过去40年的经济数据, 有时间变量.
线条图
qplot(date, unemploy/pop, data = economics, geom = 'line')
上图展现了失业率($unemploy/pop$)随时间变化趋势, 由于线条图只能从左到右绘制, 故时间变化的方向被隐藏了.
路径图
经过路径图, 将年份映射到colour属性上, 这样便能看清楚时间的行进方向:
# 定义一个函数, 将字符串类型的date('1968-08-09')转换成YYYY格式的数字(1968) year <- function(x) as.POSIXlt(x)$year + 1900 qplot(unemploy/pop, uempmed, data = economics, geom = c('point','path'), colour = year(date))
图中uempmed是失业星期数取中位数, 表明了失业时长. 从图中能够看出, 失业率和失业时间是高度相关的, 且最近几年(浅蓝色), 相同的失业率下, 失业时长急剧增加.
比较不一样分组的方法:
y轴变换
..density..
的形式告诉ggplot2将密度映射到y轴# Y轴:频数 qplot(carat, data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3)) # Y轴:密度 qplot(carat, ..density.., data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3))
qplot()中默认分面方法: 经过row_var ~ col_var
建立一个图形矩阵.
# 这里咱们限制了下每一个子图的横轴范围xlimi, 组距设置为0.1 qplot(carat, data = diamonds, facets = color ~ cut, geom = 'histogram', binwidth=0.1, xlim = c(0,3))
图示建立了一个行为color, 列为cut的图形矩阵, 每一个分面的纵轴均为钻石重量carat.
只指定列, 不指定行
# 用.做为row_var的占位符 qplot(carat, data = diamonds, facets = . ~ color, geom = 'histogram', binwidth=0.1, xlim = c(0,3))
只指定行, 不指定列
qplot(carat, data = diamonds, facets = color ~ ., geom = 'histogram', binwidth=0.1, xlim = c(0,3))
坐标轴区间
xlim, ylim控制, 例: xlim = c(0,20), ylim =c(-0.9, 0.9)
图形标题
main控制主标题, xlab, ylab分别控制x轴和y轴的标签(label), 这三个值均可以是字符串或者数学表达式
log
log是个字符型向量,log='x'表示x轴取对数, log = 'xy'表示x轴和y轴都取对数.
完整的示例:
qplot(carat, price/carat, data = diamonds, geom = 'point', xlim = c(.2, 1), # x轴显示区间: 0.2~1.0 log = 'y', # log变换 xlab = 'Weight (carats)', # xlab: 字符串 ylab = expression(frac(price,carat)), # ylab: 数学表达式 main='Small diamonds' # 主标题: 字符串 )
ggplot2的图层语法基于Wilkinson的图形语法, 且在此基础上添加了不少新功能.
要点
咱们要明白图层语法的精髓--图层语法给了咱们一个基本的做图框架, 使咱们能够从更高的视角审视图形的构成,且每一个图形组件均可以被修改.
咱们能够按需添加所需图形组件, 其它现存的图形组件能够继续使用--在已有的几何对象基础上, 添加了新的统计变换后, 原有的几何对象依然可使用.
下面将以以标准散点图为例, 来进一步解释几个核心概念:
qplot(carat, price, data = dsmall, colour = cut)
标度转换
把数据单位(升, 英里/加仑等)转换成可识别物理单位(像素, 颜色)的过程称为标度转换(scaling).
标度转换后的数据对于电脑是可识别的, 好比颜色用十六进制表示(#FF6C91), 大小, 形状分别用数字和整数来表示, 下面的图形属性中将给出grid绘图函数中(ggplot2底层使用了grid绘图函数)的图形属性的基本标度转换形式.
图形属性
在散点图中, 每一个观测数据都用一个点来表示, 点的位置有两个变量的值来决定, 每一个点有横坐标, 纵坐标, 还有大小, 颜色和形状, 这些都称为图形属性.
总结一下, 图形属性的构成及grid绘图函数中的表示方式:
注: 每一个图形属性都是一个常数或者变量, 是须要用数字填充的!!
几何对象
几何对象决定了图形的类型, 举例来说, 对于常见的只含一种几何对象的图, geom='point'时就是散点图, geom='bar'则是条形图.
常见的几何对象:
注: 多种几何对象组合而成的图形每每没有名字.
坐标系统
常见的坐标系统是笛卡尔坐标系, 此外还有极坐标和底图中的球投影坐标.
ggplot2在用绘图系统的grid函数昨晚标度转换后, 最后将根据数据点的值(x,y)来肯定其在途中的位置,此时由坐标系统Coord来完成.
标度变换
标度变换在ggplot2绘图过程当中很是重要, 包含多个步骤
在绘制复杂图形时, 标度变换须要额外的步骤, 由于在添加了统计变换后,绘图系统须要保证标度转换多个数据集里都是相同的.
好比以下包含多分面多图层的复杂图形:
qplot(displ, hwy, data = mpg, facets = .~year) + geom_smooth()
说明:
ggplot2绘图过程包含以下几步:
注意如下几点:
标度(scale)控制数据到图形属性的映射, 每种标度都是一个数据空间定义域到图形属性空间值域的映射函数.
标度有两项基本功能:
定义域
标度的定义域对应着该标度变量的取值范围, 标度的定义域多是离散型或者连续型.
值域
标度的值域包含可感知的R能理解的图形属性:位置, 颜色,形状, 大小, 线条类型. 标度的, 标度的值域也能够是离散型或者连续型的.
定义域到值域的映射
1.变换(transformation)
只针对连续型定义域.如, 对数据取对数或开根号.变换完成后生成新的数据, 此后将对每一层作统一摘要, 摘要保证了变换后的图形和变换前在线性尺度上一致.
2.训练(training)
标度训练主要完成标度的定义域计算.
对于单图层原始数据图形绘制中, 连续性变量,只须要获得变换后数据最大值和最小值便可,离散型更简单, 只须要列出全部不重复的类别性变量.
对对于横跨多个数据集的多个图层, 标度定义域计算将更复杂, 但本质上仍是统一各图层的变量域, 保证最终画到图形上时, 各图层的标度定义域一致.
定义域经过手动设置参数limits输入时, 训练过程将被跳过.
3.映射(mapping)
执行映射函数, 将标度的值域和训练后的定义域数据映射到图形属性.
标度分位四组:
标度相关内容请参考R帮助文档: ?scale_brewer
设置坐标轴或者图例上的标签, 支持指定字符串或者数学表达式. 经常使用的辅助函数: xlab(), ylab(), labs()
默认标签为数据字段名:
p <- qplot(cty, hwy, data = mpg, colour = displ) p
注意x,y轴及图例上的标签均为输入数据字段名.
连续性数据位置标签:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + scale_x_continuous('City mpg') + scale_y_continuous('Highway')
xlab, ylab指定的标签:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + xlab('City labx') + ylab('Highway laby')
labs指定的标签:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + labs(x = 'city labx', y = 'Highway laby ', colour ='labcolour')
expression指定的标签:
p <- qplot(cty, hwy, data = mpg, colour = displ) p + xlab(expression(frac(miles, gallon))) + ylab(expression(frac(miles, 'denom')))
固定标度的定义域, 连续性标度接受一个长度为2的数值型向量如c(0.4, 5.2), 离散型标度接受一个字符型向量如c('red','black').
一旦设定了limits, 数据将不会进行任何训练.
无limits:
p <- qplot(cyl, wt, data = mtcars, colour = drat) p
设定了limits:
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5))
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5)) + scale_colour_gradient(limits = c(4.0, 5.5))
控制坐标轴或者图例上哪些刻度线上的值应该显示, 或者连续性标度在图例上如何被分段, labels指定了断点处显示的标签.
p <- qplot(cyl, wt, data = mtcars, colour = drat) p + scale_x_continuous(limits = c(5.5, 6.5)) + scale_colour_gradient(breaks = c(3.0,4.5))
若是没有指定任何标签, 将在每一个断点处自动调用formatter()
来格式化生成标签, 连续性标度的标签刷为comma, percent, dollar, scientific
, 离散型标度的标签刷为abbreviate
.
每张图形有两个位置标度: x标度和y标度. ggplot2提供连续性, 离散型(因子,字符,逻辑型向量)和日期型标度.
相关的辅助函数: xlim(), ylim()和lims()
标度举例:xlim(10,20)
: 从10到20的连续型标度ylim(20,10)
: 20到10翻转后的连续型y轴标度xlim("a","b","c")
: 离散型标度xlim(as.Data(c("2008-06-01","2008-04-01"))
: 日期型标度
连续型位置标度
常见: scale_x_continuous
和scale_y_continuous
每一个连续型标度均可接受一个trans参数, 裕兴线性或非线性变化.
常见的变换器: asn($tanh^{-1}(x)$), exp, identity, log, log10, log2, logit, pow10, probit,, recip, reverse, sqrt
变换器经常使用来修改位置标度, 而且有渐变写法:scale_x_continuous(trans='log10')
等价于scale_x_log10()
注意: 区分对标度变换和对数据变换是不一样的, 即对数据取对数和对标度进行对数变换是不一样的:
对数据变换:
qplot(log10(carat), log10(price), data = diamonds)
对标度变换:
qplot(carat, price, data = diamonds) + scale_x_log10()+ scale_y_log10()