R语言数据可视化之美 · 第4章

精读版:概念讲解 + 图 + 代码,看这一页就够了

4.1 散点图系列

一句话:科研最常用的图表:展示两变量之间的关系。

4.1.1 趋势显示的二维散点图

一句话:散点图+拟合线:看两变量关系的趋势,最基础的科研图。

散点图(scatter graph、point graph、X-Yplot、scatter chart或scattergram)是科研绘图中最常见的图形类型之一,通常用于显示和比较数值。散点图是使用一系列的散点在直角坐标系中展示变量的数值分布。在二维散点图中,可以通过观察两个变量的数据变化,发现两者的关系与相关性,如

ch_图4-1-12(c)_气泡图.pngch_图4-1-13(a)不同类型的三维散点图.pngch_图4-1-13(b)不同类型的三维散点图.pngch_图4-1-13不同类型的三维散点图(a).pngch_图4-1-13不同类型的三维散点图(b).pngch_图4-1-14(a)不同类型的四维数据可视化.pngch_图4-1-14(b)不同类型的四维数据可视化.pngch_图4-1-14(c)不同类型的四维数据可视化.pngch_图4-1-14(d)不同类型的四维数据可视化.pngch_图4-1-14不同类型的四维数据可视化(a).pngch_图4-1-14不同类型的四维数据可视化(b).pngch_图4-1-14不同类型的四维数据可视化(b2).pngch_图4-1-14不同类型的四维数据可视化(c).pngch_图4-1-14不同类型的四维数据可视化(c2).pngch_图4-1-14不同类型的四维数据可视化(d).pngch_图4-1-14不同类型的四维数据可视化(d2).png
图4-1-1
#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)
library(ggrepel)
attach(mtcars)

 #-------------------------------(c) 带数据标签的气泡图-------------------------------------------------------------

 ggplot(data=mtcars, aes(x=wt,y=mpg))+
   geom_point(aes(size=disp,fill=disp),shape=21,colour="black",alpha=0.8)+
   scale_fill_gradient2(low="#377EB8",high="#E41A1C",midpoint = mean(mtcars$disp))+
   geom_text_repel(label = disp )+
   scale_size_area(max_size=12)+
   guides(size = guide_legend((title="Value")),
          fill = guide_legend((title="Value")))+
   theme(
     legend.text=element_text(size=10,face="plain",color="black"),
     axis.title=element_text(size=10,face="plain",color="black"),
     axis.text = element_text(size=10,face="plain",color="black"),
     legend.position = "right"
   )


#--------------------------(d) 方块状的气泡图--------------------------------------------------
ggplot(mtcars, aes(wt,mpg))+
  geom_point(aes(size=disp,fill=disp),shape=22,colour="black",alpha=0.8)+
  scale_fill_gradient2(low=brewer.pal(7,"Set1")[2],high=brewer.pal(7,"Set1")[1],
                       midpoint = mean(mtcars$disp))+
  scale_size_area(max_size=12)+
  guides(fill = guide_legend((title="Value")),
         size =  guide_legend((title="Value")))+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",color="black")#,
    #legend.position=c(0.9,0.05)
  )

所示。散点图可以提供三类关键信息:(1)变量之间是否存在数量关联趋势;(2)如果存在关联趋势,那么其是线性还是非线性的;(3)观察是否有存在离群值,从而分析这些离群值对建模分析的影响。回归线离群点数据点变量A通过观察散点图上数据点的分布情况,我们可以推断出变量间的相关性。

如果变量之间不存在相互关系,那么在散点图上就会表现为随机分布的离散的点;如果存在某种相关性,那么大部分的数据点就会相对密集并以某种趋势呈现。数据的相关关系主要分为正相关(两个变量值同时增加)负相关(一个变量值增加另一个变量值下降)无相关、线性相关、指数相关等,表现在散点图上的大致分布如

所示。那些离集群较远的点我们称为离群点或者异常点(outlier)。作为自变量的因素与作为因变量的预测对象是否有关、相关程度如何,以及判断这种相关程度的把握性多大,是进行回归分析必须要解决的问题。

进行相关分析,一般要求出相关关系,以相关系数的大小来判断自变量和因变量的相关的程度:强相关、弱相关和无相关等(见

)正相关负相关无相关线性相关指数相关U形相关强相关弱相关无相关式中,Cov(X,Y)为X,Y的协方差,D(X)、D(Y)分别为X、Y的方差。散点图经常与回归线(lineofbestfit,就是最准确地贯穿所有点的线)结合使用,归纳分析现有数据实现曲线拟合,以进行预测分析。对于那些变量之间存在密切关系,但是这些关系又不像数学公式和物理公式那样能够精确表达的情况,散点图是一种很好的图形工具。

但是在分析过程中需要注意,这两个变量之间的相关性并不等同于确定的因果关系,也可能需要考虑其他的影响因素。可以使用回归分析构建检验因变量与一个或多个自变量的关系的数学模型。这些模型可以用于预测自变量的未观察值和/或未来值的响应。

在简单情况下,从属变量y和独立变量x都是标量变量,给定对于i=1,2,,n的观察值(x,y),f是回归函数,e具有共同方差²的零均值独立随机误差。回归分析的目的是构建f的模型,并基于噪声数据进行估计。1.参数回归模型参数回归模型假定f的形式是已知的。

曲线拟合(curvefitting)是指选择适当的曲线类型来拟合观测数据,并用拟合的曲线方程分析两个变量间的关系。绘图软件一般使用最小二乘法(least squaremethod)实现拟合曲线的计算求取。回归分析(regressionanalysis)是对具有因果关系的影响因素(自变量)和预测对象(因变量)所进行的数理统计分析处理。

只有当自变量与因变量确实存在某种关系时,建立的回归方程才有意义。按照自变量的多少,可分为一元回归分析和多元回归分析;按照自变量和因变量之间的关系类型,可分为线性回归分析和非线性回归分析。比较常用的是多项式回归模型、线性回归模型和指数回归模型。

(1)指数回归模型:y=ae,如

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)

mydata<-read.csv("Scatter_Data.csv",stringsAsFactors=FALSE) 

ggplot(data = mydata, aes(x,y)) +
  geom_point(fill="black",colour="black",size=3,shape=21) +
  #geom_smooth(method="lm",se=TRUE,formula=y ~ splines::bs(x, 5),colour="red")+ #(h)
  #geom_smooth(method = 'gam',formula=y ~s(x))+   #(g)
  geom_smooth(method = 'loess',span=0.4,se=TRUE,colour="#00A5FF",fill="#00A5FF",alpha=0.2)+ #(f)
  scale_y_continuous(breaks = seq(0, 125, 25))+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",hjust=.5,color="black"),
    legend.position="none"
  )

所示;(2)线性回归模型:y=ax+b,如

所示;(3)对数回归模型:y=lnx+b,如

所示:(4)幂回归模型:y=ax°,如

所示;(5)多项式回归模型:y=ax+ax²+.+ax+b,其中n表示多项式的最高次项(见

),回归曲线函数为:y=1.0088x²-3.9231x+399.02,R2=0.818,如

所示。2.非参数回归模型非参数回归模型不采用预定义形式。相反,它对f的定性性质做出假设。

例如,可以假设f是“平滑的”,其不会减少到具有有限数量的参数的特定形式。因此,非参数方法通常更灵活。它们可以揭示数据中可能被遗漏的结构。

数据平滑(datasmoothimg)通过建立近似函数尝试抓住数据中的主要模式,去除噪声、结构细节或瞬时现象,来平滑一个数据集。在平滑过程中,信号数据点被修改,由噪声产生的单独数据点被降低,低于毗邻数据点的点被提升,从而得到一个更平滑的信号。平滑有两种重要形式用于数据分析:①若平滑的假设是合理的,则可以从数据中获得更多信息:2供灵活而且稳健的分析。

数据平滑的方法主要有:局部加权回归(LocallyWeightedScatterplotSmoothing,LOwESS或LOESS)、广义可加模型(GeneralisedAdditiveModel,GAM)、Savitzky-Golay、样条(spline)数据平滑。(1)LOESS数据平滑,主要思想是取一定比例的局部数据,在这部分子集中拟合多项式回归曲线,这样就可以观察到数据在局部展现出来的规律和趋势。曲线的光滑程度与选取数据比例有关:比例越少,拟合越不光滑,反之越光滑,如

所示。(2)GAM数据平滑,在R中调用mgcv包拟合数据得到GAM模型。GAM模型的拟合是通过一个迭代过程(向后拟合算法)对每个预测变量进行样条平滑。

其算法要在拟合误差和自由度之间进行权衡最终达到最优,如

所示。(3)样条数据平滑,如

所示。指数(指数回归曲线)线性(线性回归曲线)对数(对数回归曲线)乘幂(幕回归曲线)多项式(多元回归曲线)LOESS数据平滑曲线GAM数据平滑曲线样条数据平滑曲线二维散点图的不同曲线类型技能带趋势曲线的二维散点图的绘制方法(1)回归曲线:Excel可以实现

的五种数据回归类型,具体方法可以参考《Excel数据之美:科学图表与商业图表的绘制》,Origin、SigmaPlot和GraphadPrism也可以先根据数据绘制二维散点图后,再通过数据“分析(A)”模块的“拟合(F)”命令添加回归线。MATLAB、Python和R可以使用相应的函数(function)拟合数据。总的来说,给二维散点图添加回归曲线,使用Excel是最简单的方法。

(2)平滑曲线:平滑曲线的算法有很多,而且还要设定相应的平滑参数。R中ggplot2包的geom_smooth()函数提供了

等平滑算法,基本能满足平时的实验数据处理要求,使用LOESS方法平滑数据的核心代码如下:geom_smooth(method=loess'span=0.4,se=TRUE,colour="#00A5FF",fll="#00A5FF"alpha=0.2)#使用LOESS方法平滑数据,添加平滑曲线拟合的数值和实际数值就是残差(residual)。残差分析(residualanalysis)就是通过残差所提供的信息,分析出数据的可靠性、周期性或其他干扰。用于分析模型的假定正确与否的方法。

所谓残差是指观测值与预测值(拟合值)之间的差,即实际观察值与回归估计值的差。在回归分析中,测定值与按回归方程预测的值之差,用表示。残差遵从正态分布N(0)。

(6-残差的均值)/残差的标准差,称为标准化残差,用8表示。遵从标准正态分布N(0,1)。实验点的标准化残差落在(-2,2)区间以外的概率≤0.05。

若某一实验点的标准化残差落在(-2,2)区间以外,可在95%置信度将其判为异常实验点,不参与回归线拟合。

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)

mydata<-read.csv("Residual_Analysis_Data.csv",stringsAsFactors=FALSE)

fit <- lm(y2 ~ x, data = mydata)
mydata$predicted <- predict(fit)   # Save the predicted values
mydata$residuals <- residuals(fit) # Save the residual values
mydata$Abs_Residuals<-abs(mydata$residuals)  #

ggplot(mydata, aes(x = x, y = y2)) +
  geom_point(aes(fill =Abs_Residuals, size = Abs_Residuals),shape=21,colour="black") + # size also mapped
  scale_fill_continuous(low = "black", high = "red") +
  geom_smooth(method = "lm", se = FALSE, color = "lightgrey") +
  geom_point(aes(y = predicted), shape = 1) +
  geom_segment(aes(xend = x, yend = predicted), alpha = .2) +# > Color AND size adjustments made here...
  guides(fill = guide_legend((title="Rresidual")),
         size = guide_legend((title="Rresidual")))+
  ylim(c(0,150))+
  xlab("X-Axis")+
  ylab("Y-Axis")+
  theme(text=element_text(size=15,face="plain",color="black"),
        axis.title=element_text(size=10,face="plain",color="black"),
        axis.text = element_text(size=10,face="plain",color="black"),
        legend.position = "right",
        legend.title  = element_text(size=13,face="plain",color="black"),
        legend.text = element_text(size=10,face="plain",color="black"),
        legend.background = element_rect(fill=alpha("white",0)))


#----------------------------------------------------------

d<-mydata
fit <- lm(y5 ~ x+I(x^2), data = d)

# Obtain predicted and residual values
d$predicted <- predict(fit)   # Save the predicted values
d$residuals0 <- residuals(fit) # Save the residual values
d$Residuals<-abs(d$residuals0 )

ggplot(d, aes(x = x, y = y5)) +
  geom_smooth(method = "lm",formula = y ~ x+I(x^2), se = FALSE, color = "lightgrey") +
  geom_segment(aes(xend = x, yend = predicted), alpha = .2) +
  geom_point(aes(fill =Residuals, size = Residuals),shape=21,colour="black") + # size also mapped
  scale_fill_continuous(low = "black", high = "red") +
  #scale_color_gradient2(low = "blue", mid = "white", high = "red") +
  geom_point(aes(y = predicted), shape = 1) +  # Size legend also removed
  #ylim(c(0,150))+
  xlab("X-Axis")+
  ylab("Y-Axis")+
  geom_point(aes(y = predicted), shape = 1) +
  guides(fill = guide_legend((title="Rresidual")),
         size = guide_legend((title="Rresidual")))+
  theme(text=element_text(size=15,face="plain",color="black"),
        axis.title=element_text(size=10,face="plain",color="black"),
        axis.text = element_text(size=10,face="plain",color="black"),
        legend.position = "right",
        legend.title  = element_text(size=13,face="plain",color="black"),
        legend.text = element_text(size=10,face="plain",color="black"),
        legend.background = element_rect(fill=alpha("white",0)))

为使用R绘制的残差分析图,分别对应

。采用黑色到红色渐变颜色和气泡面积大小两个视觉暗示对应残差的绝对值大小,用于实际数据点的表示:而拟合数据点则用小空心圆圈表示,并放置在灰色的拟合曲线上。用直线连接实际数据点和拟合数据点。

残差的绝对值越大,颜色越红、气泡也越大,连接直线越长,这样可以很清晰地观察数据的拟合效果。技能残差分析图的绘制方法如果省去气泡颜色和面积大小两个视觉特征,直接使用实际和拟合数据点的连接线表示残差,那么可以使用Excel、Origin等软件。在R中,先根据拟合曲线计算预测值和残差,再使用实际值与预测值绘制散点图,最后使用残差作为实际值的误差线长度,添加误差线,这样就可以实现实际值与预测值的连接,同时将实际值的气泡面积大小与颜色映射到该点的残差数值,

的核心代码如下:

所示的梅丽尔·斯特里普的艺术人生。梅丽尔·斯特里普是史上获得奥斯卡提名最多的演员,达到了难以置信的17次,更是3次捧得“小金人”,仅次于凯特林·赫本,与杰克·尼克尔森、英格丽·褒曼等人并驾齐驱。在她多年的电影生涯中饰演过的角色不计其数,而且跨度很大。

Vulture把这些角色按照从冷酷(cold)到温情(warm),从严肃(serious)和随性(frivolous)分类,绘制成了散点图。29个角色尽收眼底,看起来温情的比较多,严肃的也稍稍多过随性的。R中的ggimage包提供了geom_image()函数可以将对应的圆形数据点使用图片替代展示。

但是需要预先借助图像处理软件把图片处理成圆形状。1ggimage包的参考手册:https://cran.r-project.org/web/packages/ggimage/vignettes/ggimage.html

4.1.2 分布显示的二维散点图

一句话:P-P图/Q-Q图:检验数据是否符合某分布(如正态分布)。

1.单数据系列关于统计分布的检验方法有很多种,例如K-S检验、卡方检验等,从图形的角度来说,我们也可以使用Q-Q图或P-P图来检查数据是否服从某种分布。P-P图(或Q-Q图)可检验的分布包括:贝塔分布(betadistribution)、1分布(t-distribution)、卡方分布(chi-square)、伽马分布(gammadistribution)正态分布(normaldistribution)均匀分布(uniformdistribution)帕累托分布(Paretodistribution)逻辑斯谛分布(logisticdistribution)等。Q-Q图(Quantile-Quantileplot)是一种通过画出分位数来比较两个概率分布的图形方法。

首先选定区间长度,点(xy)对应于第一个分布(X轴)的分位数和第二个分布(Y轴)相同的分位数。因此画出的是一条含参数的曲线,参数为区间个数。对应于正态分布的Q-Q图,就是以标准正态分布的分位数为横坐标、样本值为纵坐标的散点图。

要利用Q-Q图鉴别样本数据是否近似于正态分布,只需看Q-Q图上的点是否近似地在一条直线附近,而且该直线的斜率为标准差,截距为均值,如

#EasyChartsŶӳƷñؾ
#ʹѧϰϵ΢ţEasyCharts


library(ggplot2)
library(RColorBrewer)
library(scales)

x <- rnorm(250 , mean=10 , sd=1) #(a2) ֲ̬ԭʼ

#x <-sample(1:20, 250, replace = TRUE) #(a1) Ӿȷֲԭʼ

step<-0.2
breaks<- seq(min(x)-step,max(x)+step,step)#"sturges"

hg <- hist(x, breaks = breaks , plot = FALSE) # Make histogram data but do not plot

bins <- length(hg$counts) # How many bin categories are needed?
yvals <- numeric(0)                  # A blank variable to fill in
xvals <- numeric(0) 
for(i in 1:bins) {                  # Start a loop
  yvals <- c(yvals, hg$counts[i]:0)  # Work out the y-values
  xvals <- c(xvals, rep(hg$mids[i], hg$counts[i]+1))  # Work out x-values
}    # End the loop
                                                   # End the loop
dat <- data.frame(xvals, yvals)  # Make data frame of x, y variables
dat <- dat[yvals > 0, ]          # Knock out any zero y-values

colormap <- colorRampPalette(rev(brewer.pal(11,'Spectral')))(32)

#------------------------------------״tile---------------------------------------
ggplot(dat, aes(x=xvals,y=yvals,fill=yvals))+
  geom_tile(colour="black")+
  scale_fill_gradientn(colours=colormap)+
  ylim (0, max(yvals)*1.3)+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",hjust=.5,color="black"),
    legend.background = element_blank(),
    legend.position=c(0.9,0.75)
  )

#-----------------------------------ԲȦpoint-----------------------------------------
ggplot(dat, aes(x=xvals,y=yvals,fill=yvals))+
  geom_point(colour="black",shape=21,size=4)+
  scale_fill_gradientn(colours=colormap)+
  ylim (0, max(yvals)*1.3)+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",hjust=.5,color="black"),
    legend.background = element_blank(),
    legend.position=c(0.9,0.75)
  )

(b2)所示。原始数据服从正态分布如

(a2)所示,且标准差为1.0,均值为10.0。Q-Q图的用途不仅在于检查数据是否服从某种特定理论分布,它也可以推广到检查数据是否来自某个位置参数分布族。如果被比较的两个分布比较相似,则其Q-Q图近似地位于y=x上。

如果两个分布线性相关,则Q-Q图上的点近似地落在一条直线上,但并不一定是y=x这条线。Q-Q图可以比较概率分布的形状,从图形上显示两个分布的位置、尺度和偏度等性质是否相似或不同。一般来说,当比较两组样本时,Q-Q图是一种比直方图更加有效的方法,但是理解Q-Q图则需要更多的背景知识。

P-P图(Probability-Probabilityplot或Percent-Percentplot)是根据变量的累积比例与指定分布的累积比例之间的关系所绘制的图形。通过P-P图可以检验数据是否符合指定的分布。当数据符合指定分布时,P-P图中各点近似地呈一条直线。

如果P-P图中各点不呈直线,但有一定规律,则可以对变量数据进行转换,使转换后的数据更接近指定分布。P-P图和Q-Q图的用途完全相同,只是检验方法存在差异[22]。1http://www.cdadata.com/92320.40.00.20.40.60.81.0(a1)服从均匀分布的原始数据0.60.40.00.20.40.60.81.0(a2)服从正态分布的原始数据技能Q-Q图的绘制方法geom_qq_line()函数结合可以绘制Q-Q图:另外,ggplot2包结合ggpubr包可以绘制如

所示的Q-Q图,其核心代码如下所示

常用的聚类分析方法包括k-means、FCM、KFCM、DBSCAN、MeanShift等3]。Python的scikit-learn包中专门对多种聚类(clustering)算法进行实现与对比。同时也向读者推荐一本关于R语言聚类算法的书籍:AlboukadelKassambara.Practical Guideto ClusterAnalysis inR[24,里面有对各种聚类算法的详细说明。

对于高密度的散点图可以利用数据点的透明度观察数据的形状和密度,如

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)  

#-----------------------------(b) 带透明度设置的散点图------------------------------
mydata<-read.csv("HighDensity_Scatter_Data.csv",stringsAsFactors=FALSE)

ggplot(data = mydata, aes(x,y)) +
  geom_point( colour="black",alpha=0.1)+
  labs(x = "Axis X",y="Axis Y")+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",hjust=.5,color="black"),
    legend.position="none"
  )

#-----------------------------------(c) kmeans聚类的散点图-----------------------------

kmeansResult<- kmeans(mydata, 2, nstart = 20)

mydata$cluster <- as.factor(kmeansResult$cluster)

ggplot(data = mydata, aes(x,y,color=cluster)) +
  geom_point( alpha=0.2)+
  scale_color_manual(values=c("#00AFBB",  "#FC4E07"))+
  labs(x = "Axis X",y="Axis Y")+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",color="black"),
    legend.background=element_blank(),
    legend.position=c(0.85,0.15)
  )

#---------------------------------(d) 带椭圆标定的聚类散点图--------------------------------------------------

ggplot(data = mydata, aes(x,y,color=cluster)) +
  geom_point (alpha=0.2)+
  # 绘制透明度为0.2 的散点图
  stat_ellipse(aes(x=x,y=y,fill= cluster), geom="polygon", level=0.95, alpha=0.2) +
  #绘制椭圆标定不同类别,如果省略该语句,则绘制图3-1-7(c)
  scale_color_manual(values=c("#00AFBB","#FC4E07")) +#使用不同颜色标定不同数据类别
  scale_fill_manual(values=c("#00AFBB","#FC4E07"))+  #使用不同颜色标定不同椭类别
  labs(x = "Axis X",y="Axis Y")+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",color="black"),
    legend.background=element_blank(),
    legend.position=c(0.85,0.15)
  )

所示。技能高密度散点图的绘制方法使用ggplot2包的geom_point()函数可以绘制散点图:先根据数据(x,y)映射到散点,如

所示,然后设置数据点的透明度,就可以实现如

所示的效果。算法的实现:k-means算法是很常见的聚类算法,k-means(k-均值聚类)算法是一种基于距离的聚类算法,属于非监督学习方法,是很常见的一种聚类算法[25]。它用质心(centroid)到属于该质1scikit-learn包聚类算法的对比:http://scikit-learn.org/stable/modules/clustering.html#clustering心的点距离这个度量来实现聚类,通常可以用于N维空间的对象。

k-means算法接受输入参数k;然后将n个数据对象划分为k个聚类以便使所获得的聚类满足:同一聚类中的对象相似度较高:而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。MATLAB、Python和R可以通过k-means相关函数实现,R中的stats包实现k-means算法的核心代码如下。

mydata<-read.csv("HighDensity_Scatter_Data.csv"stringsAsFactors=FALSE)kmeansResult<-kmeans(mydata,2,nstart=20)#mydata为x和y两列数据组成,k-means聚类算法mydata$cluster<-as.factor(kmeansResult$cluster)#将分类结果转变成类别变量(categoricalvariables)#绘制透明度为0.2的散点图stat_ellipse(aes(x=x,y=y.fill=cluster).geom="polygon",level=0.95,alpha=0.2)+#绘制椭圆标定不同类别,如果省略该语句,则绘制

(c2)scale_color_manual(values=c(#00AFBB"#FC4E07"))+#使用不同颜色标定不同数据类别2.多数据系列多数据系列的散点图需要使用不同的填充颜色和数据点形状两个视觉特征来表示数据系列。图4-1-9(a)只使用不同的填充颜色区分数据系列,

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)


mydata<-read.csv("HighDensity_Scatter_Data.csv",stringsAsFactors=FALSE)
mydata<-mydata[round(runif(300,0,10000)),]

kmeansResult<- kmeans(mydata, 2, nstart = 20)

mydata$cluster <- as.factor(kmeansResult$cluster)

ggplot(data = mydata, aes(x,y,fill=cluster,shape=cluster)) +
  geom_point(size=4,colour="black",alpha=0.7)+
  scale_shape_manual(values=c(21,23))+
  scale_fill_manual(values=c("#00AFBB",  "#FC4E07"))+
  labs(x = "Axis X",y="Axis Y")+
  scale_y_continuous(limits = c(-5, 10))+
  scale_x_continuous(limits = c(-5, 10))+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",color="black"),
    legend.background=element_blank(),
    legend.position=c(0.85,0.15)
  )

就是使用不同填充颜色和不同形状两个视觉特征,同时区分数据系列,即使在黑白印刷时也能保证读者清晰地区分数据系列。R中ggplot2包可供选择总共20种不同类型的形状。Excel、Origin、Python等软件中也存在不同的形状,最常用就是圆形。

、菱形、方形口、三角形△等。技能多数据系列散点图的绘制方法多数据系列散点图只是在单数据系列上添加新的数据系列,使用不同的填充颜色或形状区分数据系列,R中ggplot2包的geom_point()函数可以根据数据类别映射到不同的填充颜色与形状,以及边框颜色,实现

多数据系列散点图的核心代码如下所示。#mydata为x、y和cluster三列数据组成,cluster表示类别geom_point(size=4.colour="black"alpha=0.7)+#绘制透明度为0.7的散点图scale_shape_manualvalues=c(21.23)+#使用不同的形状标定不同数据类别scale_fil_manual(values=c(“#00AFBB",“#FC4E07"))#使用的不同颜色标定不同数据类别

4.1.3 气泡图

一句话:气泡图=散点图+第三维:气泡大小=第三个变量。

气泡图是一种多变量图表,是散点图的变体,也可以认为是散点图和百分比区域图的组合。气泡图最基本的用法是使用三个值来确定每个数据序列,和散点图一样,气泡图将两个维度的数据值分别映射为笛卡儿坐标系上的坐标点,其中X轴和Y轴分别代表不同的两个维度的数据,但是不同于散点图的是,每个气泡的面积代表第三个维度的数据。气泡图通过气泡的位置及面积大小,可分析数据之间的相关性。

需要注意的是,圆圈状气泡的大小是映射到面积(circlearea)而不是半径(circleradius)或者直径(circlediameter)绘制的。因为如果是基于半径或者直径,那么圆的大小不仅会呈指数级变化,而且还会导致视觉误差。CircleArea=πx(CircleDiameter/2)²CircleDiameter-(SQRT(Area/π))x2

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)
library(ggrepel)
attach(mtcars)

 #-------------------------------(c) 带数据标签的气泡图-------------------------------------------------------------

 ggplot(data=mtcars, aes(x=wt,y=mpg))+
   geom_point(aes(size=disp,fill=disp),shape=21,colour="black",alpha=0.8)+
   scale_fill_gradient2(low="#377EB8",high="#E41A1C",midpoint = mean(mtcars$disp))+
   geom_text_repel(label = disp )+
   scale_size_area(max_size=12)+
   guides(size = guide_legend((title="Value")),
          fill = guide_legend((title="Value")))+
   theme(
     legend.text=element_text(size=10,face="plain",color="black"),
     axis.title=element_text(size=10,face="plain",color="black"),
     axis.text = element_text(size=10,face="plain",color="black"),
     legend.position = "right"
   )


#--------------------------(d) 方块状的气泡图--------------------------------------------------
ggplot(mtcars, aes(wt,mpg))+
  geom_point(aes(size=disp,fill=disp),shape=22,colour="black",alpha=0.8)+
  scale_fill_gradient2(low=brewer.pal(7,"Set1")[2],high=brewer.pal(7,"Set1")[1],
                       midpoint = mean(mtcars$disp))+
  scale_size_area(max_size=12)+
  guides(fill = guide_legend((title="Value")),
         size =  guide_legend((title="Value")))+
  theme(
    text=element_text(size=15,color="black"),
    plot.title=element_text(size=15,family="myfont",face="bold.italic",color="black")#,
    #legend.position=c(0.9,0.05)
  )

只使用面积大小(1个视觉特征)来表示气泡图,为了避免数据的重叠遮挡,一般设置气泡的透明度。添加填充颜色渐变的气泡图(2个视觉特征),如

所示,第三维变量“disp”不仅映射到气泡大小,而且还映射到填充颜色,这样能使读者更加清晰地观察数据的变化关系。在

气泡图的基础上添加数据标签(第三维变量“disp”,即气泡的面积大小),如图4-1-10(c)所示;但是需要注意,不要出现太严重的数据标签的重叠(overlap)。

只是在图4-1-10(b)的基础上把圆圈状的气泡换成方块状,给人的视觉感受与

截然不同。

并不能判断谁更好看,“萝卜白菜,各有所爱”,你喜欢使用哪种类型,就可以绘制哪种类型。口75.795.1口口技能气泡图的绘制方法

圆圈状的气泡图可以使用Excel绘制,但是其最大的一个问题是没有图例。使用R中ggplot2包实现

所示带数据标签的气泡图的核心代码如下所示,但是ggplot2包自带的添加数据标签函数geom_text()容易出现数据标签重叠的情况,所以使用ggrepel包的geom_textrepel()函数。geom_point(aes(size=disp,fil=disp),shape=21,colour=“black",alpha=0.8)+#绘制气泡图,填充颜色和面积大小都映射到dispscale_filL_gradient2(low="#377EB8"high="#E41A1C".limits=c(0.max(mtcars$ disp)).midpoint=mean(mtcars$disp)+#设置填充颜色映射主题(colormap)scale_size_area(max_size=12)+#设置显示的气泡图气泡最大面积geom_text_repellabel=disp)#添加数据标签“disp气泡图的数据大小容量有限,气泡太多会使图表难以阅读。静态的气泡图最好只表达三个维度的数据:X轴和Y轴分别代表不同的两个维度的数据;同时使用气泡的面积和颜色,或者只使用气泡面积,代表第三个维度的数据。

多数据系列气泡图(第四个维度为数据类别),虽然可以使用不同的颜色区分不同类别,但是推荐使用后面章节讲解的栅栏图展示数据。使用交互可视化的气泡图,可以通鼠标点击或者悬浮时显示气泡信息,或者添加选项控件用于重组或者过滤分组类别,但是使用交互可视化方法制作的图表几乎不应用在学术图表中。对于时间维度的气泡图可以结合动画来表现数据随着时间的变化情况。

4.1.4 三维散点图

一句话:三维散点图:三维坐标系展示三个变量的关系。

我们也可有将气泡图的三维数据绘制到三维坐标系中,这就是通常所称的三维散点图,即用于在三维X-Y-Z图上针对一个或多个数据序列绘出三个度量的一种图表。

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(plot3D)
library(scales)
library(RColorBrewer)
library(fields) 

#---------------------------------------------------------------------------------------------
df<-read.csv("ThreeD_Scatter_Data.csv",header=T)

pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = 1.5,col="black",bg="#F57446",
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)

#---------------------------------------------------------------------------------------
colormap <- colorRampPalette(rev(brewer.pal(11,'RdYlGn')))(100)#

index <- ceiling(((prc <- 0.7 * df$Power/ diff(range(df$Power))) - min(prc) + 0.3)*100)
for (i in seq(1,length(index)) ){
  prc[i]=colormap[index[i]]
}
pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                       pch = 21, cex = 1.5,col="black",bg=prc,
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                       ticktype = "detailed",bty = "f",box = TRUE,
                       #panel.first = panelfirst,
                       theta = 60, phi = 20, d=3,
                       colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)
colkey (col=colormap,clim=range(df$Power),clab = "Power", add=TRUE, length=0.5,side = 4)

#----------------------------------------------------------------------------------------
index <- ceiling(((prc <- 0.7 * df$Weight/ diff(range(df$Weight))) - min(prc) + 0.3)*100)
for (i in seq(1,length(index)) ){
  prc[i]=colormap[index[i]]
}
pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = 1.5,col="black",bg=prc,
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)
colkey (col=colormap,clim=range(df$Weight),clab = "Weight", add=TRUE, length=0.5,side = 4)

#-----------------------------------------------------------------------------------------
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = rescale(df$Weight, c(.5, 5)),col="black",bg="#ED5E3C",
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)

breaks<-round(seq(500,2000,length.out=4),3)

legend("right",title =  "Weight",legend=breaks,pch=21,
       pt.cex=rescale(breaks, c(.5, 5)),y.intersp=1.6,cex=1,
       pt.bg = "#ED5E3C",bg="white",bty="n")

#-------------------------------------------------------------------------------------
index <- ceiling(((prc <- 0.7 * df$Weight/ diff(range(df$Weight))) - min(prc) + 0.3)*100)
for (i in seq(1,length(index)) ){
  prc[i]=colormap[index[i]]
}
pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = rescale(df$Weight, c(.5, 5)),col="black",bg=prc,
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)
)
#colkey (col=colormap,clim=range(df$Weight),clab = "Weight", add=TRUE, length=0.5,side = 4)

breaks<-round(seq(500,2000,length.out=4),3)

legend_index <- ceiling(((legend_prc <- 0.7 *breaks/ diff(range(breaks))) - min(legend_prc) + 0.3)*100)
for (i in seq(1,length(legend_index)) ){
  legend_prc[i]=colormap[legend_index[i]]
}
legend("right",title =  "Weight",legend=breaks,pch=21,
       pt.cex=rescale(breaks, c(.5, 5)),y.intersp=1.6,
       pt.bg = legend_prc,bg="white",bty="n")


#-----------------------------------¶àÊý¾ÝϵÁÐ--------------------------------
library(wesanderson)
pmar <- par(mar = c(5.1, 4.1, 4.1, 7.1))
colors0 <-  wes_palette(n=3, name="Darjeeling1")
colors <- colors0[as.numeric(iris$Species)]
with(iris, scatter3D(x = Sepal.Length, y = Sepal.Width, z = Petal.Length, #bgvar = mag,
                   pch = 21, cex = 1.5,col="black",bg=colors,
                   xlab = "longitude", ylab = "latitude",
                   zlab = "depth, km", 
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 140, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)

legend("right",title =  "Species",legend=c("setosa", "versicolor", "virginica"),pch=21,
       cex=1,y.intersp=1,pt.bg = colors0,bg="white",bty="n")

所示为不同类型的三维散点图。

是普通的三维散点图,X、Y和Z轴分别对应三个不同的变量。

是在

(a)基础上,将Z轴变量数据“Power(KW)”映射到数据点颜色,这样可以更加清晰地观察Z轴变量与X、Y轴变量数据的变化关系。需要注意的是:

三维图表投影方式选择都为正交投影(orthographicprojection)。技能三维散点图的绘制方法在编程语言方面,R中scatterplot3d包的scatterplot3dO函数、rgl包的plot3dO函数、plot3D包的scatter3D0函数等都可以绘制三维散点图。在R中,三维图表的绘制只能通过函数编程实现,比较难控制到每个图表元素,比如X-Y-Z坐标轴标题的位置、网格线等。

rgl包的plot3dO函数绘制的三维图表可以实现图表的旋转,能供用户从不同视角(view)去观察数据关系。使用R中plot3D包的scatter3D0函数可以实现

所示效果,具体代码如下所示

(b)就相对来说比较复杂一些,需要将数据点映射到颜色。我们先自己构造一个颜色映射的颜色条RdYIGn,再绘制三维散点图,然后根据映射的数值添加图例颜色条,代码如下所示。#构造颜色映射colormap<-colorRampPalette(rev(brewer.pal(11,RdYiGn')(100)index<-ceiling((prc<-0.7+df$Power/diff(range(df$Power))-min(prc)+0.3)*100)pmar<-par(mar=c(5.1,4.1,4.1,6.1))pch=21,cex=1.5.col="black"bg=prcylab =“Gas Mileage (mpg)"ticktype=“detailed"bty=“f",box=TRUE,1R中plot3D包的更多三维图表可以参考:http://www.rforscience.com/rpackages/visualisation/oceanviewcolkey=FALSE)#list(length=0.5,width=0.5,cex.clab=0.75))三维散点图可以展示三维数据,如果添加一维数据,则使图表展示四维数据。

第1种方法就是将

ch_图4-1-12(c)_气泡图.png
图4-1-12
#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(plot3D)
library(scales)
library(RColorBrewer)
library(fields) 

#---------------------------------------------------------------------------------------------
df<-read.csv("ThreeD_Scatter_Data.csv",header=T)


#----------------------------------------------------------------------------------------
index <- ceiling(((prc <- 0.7 * df$Weight/ diff(range(df$Weight))) - min(prc) + 0.3)*100)
for (i in seq(1,length(index)) ){
  prc[i]=colormap[index[i]]
}
pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = 1.5,col="black",bg=prc,
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)
colkey (col=colormap,clim=range(df$Weight),clab = "Weight", add=TRUE, length=0.5,side = 4)

#-----------------------------------------------------------------------------------------
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = rescale(df$Weight, c(.5, 5)),col="black",bg="#ED5E3C",
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   #panel.first = panelfirst,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)

breaks<-round(seq(500,2000,length.out=4),3)

legend("right",title =  "Weight",legend=breaks,pch=21,
       pt.cex=rescale(breaks, c(.5, 5)),y.intersp=1.6,cex=1,
       pt.bg = "#ED5E3C",bg="white",bty="n")

#-------------------------------------------------------------------------------------
index <- ceiling(((prc <- 0.7 * df$Weight/ diff(range(df$Weight))) - min(prc) + 0.3)*100)
for (i in seq(1,length(index)) ){
  prc[i]=colormap[index[i]]
}
pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))
with(df, scatter3D(x = mph, y = Gas_Mileage, z = Power, #bgvar = mag,
                   pch = 21, cex = rescale(df$Weight, c(.5, 5)),col="black",bg=prc,
                   xlab = "0-60 mph (sec)",
                   ylab = "Gas Mileage (mpg)",
                   zlab = "Power (kW)", 
                   zlim=c(40,180),
                   ticktype = "detailed",bty = "f",box = TRUE,
                   theta = 60, phi = 20, d=3,
                   colkey = FALSE)
)
#colkey (col=colormap,clim=range(df$Weight),clab = "Weight", add=TRUE, length=0.5,side = 4)

breaks<-round(seq(500,2000,length.out=4),3)

legend_index <- ceiling(((legend_prc <- 0.7 *breaks/ diff(range(breaks))) - min(legend_prc) + 0.3)*100)
for (i in seq(1,length(legend_index)) ){
  legend_prc[i]=colormap[legend_index[i]]
}
legend("right",title =  "Weight",legend=breaks,pch=21,
       pt.cex=rescale(breaks, c(.5, 5)),y.intersp=1.6,
       pt.bg = legend_prc,bg="white",bty="n")


#-----------------------------------¶àÊý¾ÝϵÁÐ--------------------------------
library(wesanderson)
pmar <- par(mar = c(5.1, 4.1, 4.1, 7.1))
colors0 <-  wes_palette(n=3, name="Darjeeling1")
colors <- colors0[as.numeric(iris$Species)]
with(iris, scatter3D(x = Sepal.Length, y = Sepal.Width, z = Petal.Length, #bgvar = mag,
                     pch = 21, cex = 1.5,col="black",bg=colors,
                     xlab = "longitude", ylab = "latitude",
                     zlab = "depth, km", 
                     ticktype = "detailed",bty = "f",box = TRUE,
                     #panel.first = panelfirst,
                     theta = 140, phi = 20, d=3,
                     colkey = FALSE)#list(length = 0.5, width = 0.5, cex.clab = 0.75))
)

legend("right",title =  "Species",legend=c("setosa", "versicolor", "virginica"),pch=21,
       cex=1,y.intersp=1,pt.bg = colors0,bg="white",bty="n")

的填充颜色渐变映射到第四维数据,而不是原来的第三维数据,如

所示。第2种方法就是将第四维数据映射到数据点的大小上,即三维气泡图,如

所示。第3种方法就是结合

,绘制带颜色渐变映射的三维气泡图,将第四维数据映射到数据点的大小和颜色上,如

所示。

从本质上讲,是属于三维气泡图类型。

ch_图4-1-14(a)不同类型的四维数据可视化.pngch_图4-1-14(b)不同类型的四维数据可视化.pngch_图4-1-14(c)不同类型的四维数据可视化.pngch_图4-1-14(d)不同类型的四维数据可视化.pngch_图4-1-14不同类型的四维数据可视化(a).pngch_图4-1-14不同类型的四维数据可视化(b).pngch_图4-1-14不同类型的四维数据可视化(b2).pngch_图4-1-14不同类型的四维数据可视化(c).pngch_图4-1-14不同类型的四维数据可视化(c2).pngch_图4-1-14不同类型的四维数据可视化(d).pngch_图4-1-14不同类型的四维数据可视化(d2).png
图4-1-14

是多数据系列的三维散点图,用不同颜色表示不同的数据系列。2.53.5

4.0 技能

一句话:技能:三维气泡图与多系列三维散点图的绘制方法(图例自定义、类别着色)。

三维气泡图的绘制方法所示效果,具体代码如下所示。其主要存在两个关键问题:①气泡图例的添加:2颜色映射图例的添加,需要使用begend()函数自定义生成图例

所示的多数据系列的三维散点图,需要把类别变量iris$Species映射到不同的颜色,然后赋值给数据点的填充参数bg。最后使用legend()函数构造图例,具体代码如下所示

4.2 曲面拟合图

一句话:曲面拟合图:二维变量与目标函数的关系,看两因素如何共同影响结果。

通常,曲线拟合法只适用于单一变量与目标函数之间的关系分析,而曲面拟合则多用于二维变量与目标函数之间关系的分析。所谓曲面拟合,就是根据实验测试数据,求取函数fxy)与变量x及y之间的解析式,使其通过或近似通过所有的实验测试点。也就是说,使所有实验数据点能近似地分布在函数fxy)所表示的空间曲面上。

曲面拟合通常采用两种方式,即插值方式和逼近方式来实现。两者的共同点是均利用曲面上或接近曲面的一组离散点寻求良好的曲面方程。两者主要的区别是:插值方式得到的方程所表示的曲面全部通过这组数据点,比如LOESS曲面拟合:而逼近方式,只要求在某种准则下其方程表示的曲面与这组数据点接近即可,比如多项式曲面拟合。

逼近方式一般使用最小二乘法实现。最小二乘法是一种逼近理论,也是采样数据进行拟合时最常用的一种方法。曲面一般不通过已知数据点,而是根据拟合的曲面在取样处的数值与实际值之差的平均和达到最小时求得,它的主旨思想就是使拟合数值与实际数值之间的偏平方和达到最小[26]

ch_图4-2-1_曲面拟合方法.png
图4-2-1
#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(plot3D)
library(gridExtra)
library(reshape2)
library(RColorBrewer)

colormap<-colorRampPalette(rev(brewer.pal(11,'RdYlGn')))(100)

#--------------------------------------------------多项式拟合------------------------------------------
mydata <- read.csv("Surface_Data.csv", sep= ",", header=T)

#多项式拟合z=f(x,y)=a+bx+cy+dxx+eyy
x <- mydata$x
y <- mydata$y
z <- mydata$z
x2<-x*x
y2<-y*y
poly_z <- lm(z ~ x + y +x2+y2)
print(poly_z)

#设定为30X30的网格数据(x, y),并根据拟合方程求其数值
N<-30
xmar <- seq(min(x),max(x),(max(x)-min(x))/N)
ymar <- seq(min(y),max(y),(max(y)-min(y))/N)
Grid_xy<-expand.grid(list(x=xmar,y=ymar))
Grid_xy$x2<-Grid_xy$x*Grid_xy$x
Grid_xy$y2<-Grid_xy$y*Grid_xy$y
Grid_z <- predict.lm(poly_z, newdata=Grid_xy)  


pred_z<-matrix(Grid_z, length(xmar), length(ymar))


persp3D (xmar, ymar, pred_z,
      theta = 150, phi = 40, d=3, 
      col = colormap, 
      scale = TRUE, border = "black", 
       bty = "f",box = TRUE,ticktype = "detailed",#nticks=5,
      ylab = "0-60 mph (sec)", 
      xlab = "Gax Mileage (mpg)",
      zlab="Power (KW)",
      clab="Power (KW)",
      zlim=c(20,180),
      add=TRUE,
      colkey = list(length = 0.5, width = 1))


fitpoints <- predict(poly_z) 

scatter3D(z = z, x = x, y = y, pch = 21, cex = 1, 
          theta = 150, phi = 40, d=3,ticktype = "detailed",
          col = colormap,
          surf = list(x = xmar, y = ymar, z = pred_z,border = "black",shade=0,ffit = fitpoints), # fit参数增加预测值与真实值之间的连线
          bty = "f", col.panel = NA,
          xlab = "0-60 mph (sec)", 
          ylab = "Gax Mileage (mpg)",
          zlab="Power (KW)",
          clab="Power (KW)",
          zlim=c(20,180),colkey = list(length = 0.5, width = 1))# col.panel = NA则panel透明

#-#--------------------------------------------------loess回归式拟合------------------------------------------
mydata <- read.csv("Surface_Data.csv", sep= ",", header=T)

x <- mydata$x
y <- mydata$y
#z <- mydata$z


elev.loess <- loess(z ~ x * y, mydata,span=0.95)
print(elev.loess)


xmar <- seq(min(x),max(x),(max(x)-min(x))/30)
ymar <- seq(min(y),max(y),(max(y)-min(y))/30)
# get fitted (interpolated) values
elev.interp <- predict(elev.loess, expand.grid(list(x=xmar,y=ymar)))

pred_z<-matrix(elev.interp, length(xmar),length(ymar))

# 显示曲面网格,网格边线颜色为洋红,显示box框线
persp3D (xmar, ymar, pred_z,
         theta = 150, phi = 40, d=3, 
         col = colormap, 
         scale = TRUE, border = "black", 
         bty = "f",box = TRUE,ticktype = "detailed",#nticks=5,
         xlab = "0-60 mph (sec)", 
         ylab = "Gax Mileage (mpg)",
         zlab="Power (KW)",
         zlim=c(20,180))


fitpoints <- predict(elev.loess ) 

scatter3D(z = z, x = x, y = y, pch = 21, cex = 1, 
                      theta = 150, phi = 40, d=3,ticktype = "detailed",
                      col = colormap,
                      surf = list(x = xmar, y = ymar, z = pred_z,border = "black",shade=0,ffit = fitpoints), # fit参数增加预测值与真实值之间的连线
                      bty = "f", col.panel = NA,
                      ylab = "0-60 mph (sec)", 
                      xlab = "Gax Mileage (mpg)",
                      zlab="Power (KW)",
                      zlim=c(20,180))# col.panel = NA则panel透明


所示为相同数据、不同曲面拟合方法所示的结果图,

为三维散点与曲面拟合组合图,分别为多项式曲面拟合和LOESS曲面拟合。其中,三维散点展示了实际数值(x,y,z),拟合曲面映射到的颜色渐变主题方案为RdYIGn。二元二次多项式拟合的方程为:z-f(x,y)=a+bx+cy+dx²+ey²,其中x和y为自变量,z为因变量,a、b、c、d、e为拟合参数。

ch_图4-2-2_等高线分布图.png
图4-2-2

为二维散点与等高线组合图,二维散点图展示了实际数值(x,y),z变量数值映射到渐变颜色:拟合曲面使用二维等高线表示,拟合的x,y数值映射到相同的渐变颜色,这样就可以使用二维图表展示三维的曲面拟合结果。

的主要区别在于使用颜色视觉特征表示第三维z变量。具体绘制方法可以参照4.3节。技能曲面拟合图MATLAB和Origin都提供了交互操作的曲面拟合工具箱,如MATLAB的CurveFitting,MATLAB提供的fit()函数能拟合数据,再使用surf()函数绘制如

的图表。在R中,rgl包的surface3d0函数、scatterplot3d包的plane3dO函数、lattice包的wireframe()函数,或者plot3D包的persp3D0函数都可以绘制曲面拟合。本节推荐使用lattice包的wireframe()函数绘制曲面图:先使用lm()或loess()函数根据已有的(x,y,z)数据求取拟合方程;再根据自定义的网格数据(x,y),求取每个数据点的z数值;最后使用persp3D0函数绘制生成的(x,y,z)数据。

(a)曲面拟合的具体代码如下所示

4.3 等高线图

一句话:等高线图:三维数据压成二维+颜色,像地图等高线。

等高线图(contourmap)是可视化二维空间标量场的基本方法,可以将三维数据使用二维的方法可视化,同时用颜色视觉特征表示第三维数据,如地图上的等高线、天气预报中的等压线和等温线等。假设f(x,y)是在点(x,y)处的数值,等值线是在二维数据场中满足fx,y)=c的空间点集按一定的顺序连接而成的线。数值为c的等值线可以将二维空间标量场分为两部分:如果fxy)c,则该点在等值线内;如果fxy)>c,则该点在等值线外。

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library( directlabels)
library(RColorBrewer)

rf <- colorRampPalette(rev(brewer.pal(11,'Spectral')))
colormap <- colorRampPalette(rev(brewer.pal(11,'Spectral')))(32)

z<-as.matrix(read.table("等高线.txt",header=TRUE))
colnames(z)<-seq(1,ncol(z),by=1)
max_z<-max(z)
min_z<-min(z)
breaks_lines<-seq(min(z),max(z),by=(max_z-min_z)/10)
map<-melt(z)
colnames(map)<-c("Var1","Var2","value")
head(map)
Contour<-ggplot(map,aes(x=Var1,y=Var2,z=value))+
          geom_tile(aes(fill=value))+#根据高度填充
          scale_fill_gradientn(colours=colormap)+
          geom_contour(aes(colour= ..level..),breaks=breaks_lines,color="black")+#
          labs(x="X-Axis",y="Y-Axis",fill="Z-Value")+
         theme(
           axis.title=element_text(size=15,face="plain",color="black"),
           axis.text = element_text(size=13,face="plain",color="black"),
           legend.title=element_text(size=13,face="plain",color="black"),
           legend.text = element_text(size=11,face="plain",color="black"),
           legend.background = element_blank(),
           legend.position =c(0.15,0.2)
  )
Contour

direct.label(Contour, list("bottom.pieces", cex=0.8, #"far.from.others.borders",
                  fontface="plain", fontfamily="serif", colour='black'))

(a)为热力分布图,只是将三维数据(x,y,,z)中(x,y)表示位置信息,z映射到颜色。

(b)是在

的基础上添加等高线,同一轮廓上的数值相同。

是在

的基础上添加等高线的具体数值,从而不需要颜色映射的图例,同一轮廓上的数值相同。在二维屏幕上,等高线可以有效地表达相同数值的区域,揭示走势和陡峭程度及两者之间的关系,寻找坡、峰、谷等形状。技能等高线图R中的ggplot2包提供的geom_tile()函数和geom_raster()函数都可以绘制如

所示的热力分布图,其主要区别在于geom_raster()函数中存在interpolate=TRUE/FALSE这个参数,决定是否对热力图进行平滑处理。添加geom_contour()函数,从而可以添加如

所示的等高线。使用directlabels包的direct.label()函数可以添加等高线的数值标签,如

所示,其核心代码如下所示

一个标量场u可以用一个标量函数来表示。在直角坐标系中,可将u表示为u=u(x,y,2)。令u=u(x,y,z)=C,其中C是任意常数,则该式在几何上表示一个曲面,在这个曲面上的各点,虽然坐标(x,y,2)不同,但函数值相等,称此曲面为标量场u的等值面。

随着C的取值不同,得到一系列不同的等值面。同理,对于由二维函数v=v(x,y)所给定的平面标量场,可按v=v(x,y)=C得到一系列不同值的等值线。标量场的等值面或等值线,可以直观地帮助我们了解标量场在空间中的分布情况。

例如,根据地形图上等高线及其所标出的高度,我们就能了解到该地区的高低情况,根据等高线分布的疏密程度可以判断该地区各个方向上地势的陡度。与标量不同,矢量除了要指明其大小还要指明其方向的物理量,如速度、力、电场强度等;矢量的严格定义是建立在坐标系的旋转变换基础上的。常见的矢量场包括Maxwell场、重矢量场。

而在一定的单位制下,用一个实数就足以表示的物理量是标量,如时间、质量、温度等;在这里,实数表示的是这些物理量的大小。

4.4 切面图

一句话:切面图:三维坐标+第四维色彩,展示四维数据。

切面图(slicechart)可以展示四维数据v=f(x,y,z),将前三维数据展现在三维直角坐标系f(x,y,z),通过对图形的线型、立面、色彩、渲染、光线、视角等的控制,可形象地表现数据四维特性v。任何一个在三维坐标系中绘制的数据体,都可以使用分割得到平行于X-Y、X-Z和Y-Z的三个切面。然后每个切面上的数据点都可以通过3-D插值获得,如

ch_图4-4-1_切面图(a).pngch_图4-4-1_切面图(b).png
图4-4-1
#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(plot3D)
library(RColorBrewer)

x <- y <- z <- seq(-4, 4, by = 0.2)
M <- mesh(x, y, z)
R <- with (M, sqrt(x^2 + y^2 + z^2))
p <- sin(2*R) /(R+1e-3)

colormap <- colorRampPalette(rev(brewer.pal(11,'Spectral')),alpha = TRUE)(32)

slice3D(x, y, z, colvar = p, facets = FALSE,
        col = ramp.col(colormap,alpha = 0.9), 
        clab="p vlaue",
        xs = 0, ys = c(-4, 0, 4), zs = NULL, 
        ticktype = "detailed",bty = "f",box = TRUE,
        theta = -120, phi = 30, d=3,
        colkey = list(length = 0.5, width = 1, cex.clab = 1))

所示。在切面图中,v=fx,y,z)这个函数对于每一个给定的(x,y,z)都对应一个v,然后映射到渐变颜色,那么v=f(x,y,z)就可以得到一个有颜色变化(其颜色分布按给定的函数表达式变化)的立体图形。给定(x,y,2)中的某个值,就可以得到某一个切面上的颜色分布,根据颜色映射大致可以看出其函数值的变化。

中,展示了x=0,y=(4,0,4)的4个切面颜色变化情况。1.51.51.01.00.50.50.00.0技能切面图在R中可以使用plot3D包的slice3DO函数绘制切面图,其中facets参数TRUE绘制的效果如图4-4-1(b)所示,FALSE绘制的效果如

所示,其核心代码如下:

4.5 三元相图

一句话:三元相图:三角坐标内一点=三种成分的一个配比。

三元相图(ternaryphasediagram)指独立组分数为3的体系,该体系最多可能有4个自由度。三元相图成分通常用浓度(或成分)三角形(concentration/compositiontriangle)表示。常用的成分三角形有等边成分三角形、等腰成分三角形或直角成分三角形。

其中,对于等边成分三角形(见

),在等边成分三角形中,三角形的三个顶点分别代表三个组元A、B、C,三角形的三个边的长度定为0~100%,分别表示三个二元系(A-B系、B-C系、C-A系)的成分坐标,则三角形内任一点都代表三元系的某一成分。其成分确定方法如下:由三角形所给定点s,分别向A、B、C顶点所对应的边BC、CA、AB绘制平行线(sa、sb、sc),相交于三边的c、a、b点,则A、B、C组元的比例数值W分别为:WA=sc=Ca,WB=sa=Ab,Wc=sb=Bc,其中:sa+sb+sc=1,Ca+Ab+Bc=1。

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggtern)
library(grid)
library(RColorBrewer)

#---------------------------------------(a) 三元相散点图-----------------------------------------------------
data(Fragments)
arrangement = list()
for(base in c('ilr')){
  y = ggtern(Fragments,aes(Qm,Qp,M)) +
    theme_showarrows()+
    geom_point(size=3) + 
    ggtitle(sprintf("Basis: %s",base)) +
    limit_tern(.5,1,.5)
  arrangement[[length(arrangement) + 1]] = y
}
grid.arrange(grobs = arrangement,nrow=1)


#----------------------------------(a) -三元相等高线图-----------------------------------------------------
data(Fragments)
arrangement = list()
for(base in c('ilr')){
  x = ggtern(Fragments,aes(Qm,Qp,M)) +
    stat_density_tern(geom='polygon',
                      aes(fill=..level..),
                      base=base,  
                      colour='grey50') + 
    theme_showarrows()+
    geom_point() + 
    ggtitle(sprintf("Basis: %s",base)) +
    scale_fill_gradientn(colours=c(brewer.pal(7,"Set1")[2],"white",brewer.pal(7,"Set1")[1]),na.value=NA)+
    limit_tern(.5,1,.5)
  arrangement[[length(arrangement) + 1]] = x
}
grid.arrange(grobs = arrangement,nrow=1)



分别为三元相散点图和三元相等高线图,与直角坐标系的散点图和等高线图类似,只是表达的是三维数据信息。0.300.250.200.150.10技能三元相图在R中可以使用ggtern包的ggtern()函数,结合ggplot2包的geom_point()函数可以绘制如图4-5-2(a)所示的三元相散点图。使用ggtern()函数和stat_density_tern()函数,以及ggplot2包的geom_point()函数,可以绘制如

所示的三元相等高线图,其核心代码如下所示。x=ggtern(fragments,aes(qm,qp.m))+stat_density_tern(geom=polygon,aes(fil=.level.),base=base,colour=grey50)+scale_fill_gradientn(colours=c(brewer.pal(7."set1")[2]."white",brewer.pal(7,"set1")[1]),na.value=na)+

4.6 散点曲线图系列

一句话:散点曲线图:平滑曲线连接散点,突出整体趋势。

带曲线的散点图就是使用平滑的曲线将散点依次连接,重点体现数据的趋势,如

ch_图4-6-1_瀑布图(a).pngch_图4-6-1_瀑布图(a0).pngch_图4-6-1_瀑布图(a1).pngch_图4-6-1_瀑布图(b).pngch_图4-6-1_瀑布图(c).png
图4-6-1
#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(ggalt)
#----------------------------------------图4-6-1 散点曲线图系列(a)-------------------------------------------------------
mydata<-read.csv("Line_Data.csv",header=T)

ggplot(mydata, aes(x, y) )+
  geom_xspline(spline_shape=-0.5, size=0.25)+
  geom_point(shape=21,size=4,color="black",fill="#F78179") +
  xlab("X-Axis")+
  ylab("Y-Axis")+
  ylim(0, 50)+
  theme_gray()+
  theme(
    text=element_text(size=15,face="plain",color="black"),
    axis.title=element_text(size=10,face="plain",color="black"),
    axis.text = element_text(size=10,face="plain",color="black")
  )

#----------------------------------------图4-6-1 散点曲线图系列(d)-------------------------------------------------------
library(splines)
newdata <- data.frame(spline(mydata$x,mydata$y,n=300,method="hyman" ))

ggplot(newdata, aes(x, y) )+
  geom_line(size=0.5,color="black")+
  geom_area(fill="#F78179",alpha=0.9)+
  geom_point(data=mydata,aes(x,y),shape=21,size=3,color="black",fill="white") +
  xlab("X-Axis")+
  ylab("Y-Axis")+
  ylim(0, 50)+
  theme_gray()+
  theme(
    text=element_text(size=15,face="plain",color="black"),
    axis.title=element_text(size=12,face="plain",color="black"),
    axis.text = element_text(size=12,face="plain",color="black")
  )

#The following rules apply for the methods called to interpolate:
#  Method	Description
#"fmm"	The spline used is that of Forsythe, Malcolm, and Moler.
#"periodic"	Periodic splines are used. The period is taken to be diff(range(x)), and it is expected that the y values corresponding to the extrema of x are equal.
#"natural"	Natural splines are used. The second derivative is zero at the endpoints.
#"monoH.FC"	The monotone piecewise cubic interpolation method of F.N. Fritsch and R.E. Carlson (with modifications by Butland and Brodlie) is used. (This is the Fortran routine DPCHIP from the slatec library.)
#"hyman"	Also gives a monotone spline: the "fmm" spline is initially calculated, and then the method of J.M. Hyman is used to force it to be monotone.

所示。曲线图就是不带数据标记而只带平滑曲线的散点图,

所示。带面积填充的曲线图就是在

(b)的基础上在曲线下面的部分使用颜色填充,使图表能更好地展示数据的变化趋势。图4-6-1(d)是在

的基础上在曲线下面的部分使用颜色填充。对于这几种图表的应用情况,

和4-6-1(b)同时适应于单数据系列和多数据系列;图4-6-1(c)和

更适用于单数据系列,因为使用面积填充的多数据系列会存在遮挡效果,从而降低读者对数据的可读性。技能散点曲线图由于R中ggplot2包的geom_line()函数只能绘制折线图,但是R中ggalt包提供的geom_xspline()函数可以绘制带光滑曲线的散点图,

的核心代码如下所示。需要注意的是:geom_line()函数是先对数据根据X轴变量的数值排序,然后使用直线依次连接,常用于直角坐标系中。geom_path()函数是直接根据给定的数据点顺序,使用直线将各点连接,常用于地理空间坐标系中。

mydata<-read.csv("Line_Data.csv"header=T)geom_xspline(spline_shape=-0.5,size=0.25)+geom_point(shape=21,size=4,color="black",fill="#F78179")+对于

带填充颜色的散点曲线图,可以使用数据预处理的方法先用算法平滑曲线,然后根据平滑数据绘制面积图,再添加散点曲线。R中splines包的spline()函数可以使用样条函数实现曲线的光滑与插值(interpolation),其核心代码如下所示。其中,spline()函数的method方法参数有“fmm”、“natural"、“periodic”、“monoH.FC"和"hyman”四种类型。

“hyman"只适应于单调递增或递减的数据插值,“natural"使用自然样条插值方法,“periodic"使用周期样条插值方法,在使用该函数时,读者自己可以根据数据,尝试或者选择不同的数据平滑差值方法

4.7 瀑布图

一句话:瀑布图:增减分解利器——从基准到最终值每步变化一目了然。

瀑布图(waterfallplot)用于展示拥有相同的X轴变量数据(如相同的时间序列)不同的Y轴离散型变量(如不同的类别变量)和Z轴数值变量,可以清晰地展示不同变量之间的数据变化关系。如

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(plot3D)

library(RColorBrewer)

mydata0<-read.csv("Facting_Data.csv",check.names =FALSE)

N<-ncol(mydata0)-1

mydata<-data.frame(x=numeric(),y=numeric(),variable=character())

for (i in 1:N){
  newdata<-data.frame(spline(mydata0[,1],mydata0[,i+1],n=300,method= "natural"))
  newdata$variable<-colnames(mydata0)[i+1]
  mydata<-rbind(mydata,newdata)
}


mydata$variable<-as.numeric(mydata$variable)
group<-unique(mydata$variable)
M<-length(group)

gg_color_hue <- function(n) {
  hues = seq(15, 375, length = n + 1)
  hcl(h = hues, l = 65, c = 100)[1:n]
}

colormap <- rev(gg_color_hue(M))#brewer.pal(M,'RdYlGn')

pmar <- par(mar = c(5.1, 4.1, 4.1, 6.1))

perspbox(z=as.vector(0),#add=TRUE,
          xlim=c(20,70),ylim=c(360,750),zlim=c(0,15),
          ticktype = "detailed",bty = "f",box = TRUE,colkey = FALSE,
          theta = -110, phi = 20, d=3)

for (i in 1:M){
  df0<-mydata[mydata$variable==group[i],]
  Ndf<-nrow(df0)
  df<-rbind(df0,c(df0$x[1],df0$y[Ndf],df0$variable[Ndf]))
  with(df,polygon3D(x=variable,y=x, z=y, alpha=0.6,
                     col=colormap[i],lwd = 3,add=TRUE,colkey = FALSE))
  
  with(df0,lines3D(x=variable,y=x, z=y, 
                  lwd = 0.5,col="black",add=TRUE))
}

所示为三维瀑布图。三维瀑布图可以看成是多数据系列三维面积图。使用分面图的可视化方法也可以展示瀑布图的数据信息,关于分面图可视化方法的具体讲解请见所示的行分面的带填充的曲线图,所有数据共用X轴坐标,每个数据类别拥有自己的Y轴坐标,数据类别显示在最右边。

相对三维瀑布图,分面瀑布图可以更好地展示数据信息,避免不同类别之间数据重叠引起的遮挡问题,但是不能很直接地比较不同类别之间的数据差异。

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)  
library(reshape2)

#-----------------------------------图4-7-2 行分面的带填充的曲线图(a)-------------------------------------------
mydata0<-read.csv("Facting_Data.csv",stringsAsFactors=FALSE)

colnames(mydata0)<-c("X_Axis",seq(60,25,-5))
mydata<-melt(mydata0,id.vars = "X_Axis")

ggplot(mydata,aes(X_Axis,value,fill=variable))+
  geom_area(color="black",size=0.25)+
  facet_grid(variable~.)+
  theme(
    text=element_text(size=15,face="plain",color="black"),
    axis.title=element_text(size=10,face="plain",color="black"),
    axis.text = element_text(size=10,face="plain",color="black"),
    legend.position="none"
  )

#-----------------------------------图4-7-2 行分面的带填充的曲线图(b)-------------------------------------------
library(RColorBrewer)
colormap <- colorRampPalette(rev(brewer.pal(11,'Spectral')))(32)
mydata0<-read.csv("Facting_Data.csv",stringsAsFactors=FALSE)

N<-ncol(mydata0)-1

colnames(mydata0)<-c("X_Axis",seq(60,25,-5))

mydata<-data.frame(x=numeric(),y=numeric(),variable=character())

for (i in 1:N){
  newdata<-data.frame(spline(mydata0[,1],mydata0[,i+1],n=300,method= "natural"))
  newdata$variable<-colnames(mydata0)[i+1]
  mydata<-rbind(mydata,newdata)
}

mydata$variable<-factor(mydata$variable,levels=seq(60,25,-5))

ggplot(mydata,aes(x,y,group=variable))+
  geom_bar(aes(fill=y),color=NA,size=0.25,stat="identity")+
  geom_line(color="black",size=0.5)+
  scale_fill_gradientn(colours=colormap)+
  facet_grid(variable~.)+
  theme(
    text=element_text(size=15,face="plain",color="black"),
    axis.title=element_text(size=10,face="plain",color="black"),
    axis.text = element_text(size=10,face="plain",color="black"),
    legend.position="right"
  )



的基础上将每个数据的Z变量进行颜色映射,这样有利于比较不同类别之间的数据差异。品10.07.55.0使用峰峦图也可以很好地展示瀑布图的数据信息,如

#EasyCharts团队出品,如有商用必究,
#如需使用与深入学习,请联系微信:EasyCharts

library(ggplot2)
library(RColorBrewer)  

colormap <- colorRampPalette(rev(brewer.pal(11,'Spectral')))(32)

mydata0<-read.csv("Facting_Data.csv",check.names =FALSE)

N<-ncol(mydata0)-1
labels_Y<-colnames(mydata0)[1:N+1]
colnames(mydata0)<-c("x",seq(1,N,1))
mydata<-data.frame(x=numeric(),y=numeric(),variable=character()) #创建空的Data.Frame

for (i in 1:N){
  newdata<-data.frame(spline(mydata0[,1],mydata0[,i+1],n=300,method= "natural"))
  newdata$variable<-colnames(mydata0)[i+1]
  mydata<-rbind(mydata,newdata)
}

Step<-5
mydata$offest<--as.numeric(mydata$variable)*Step
mydata$V1_density_offest<-mydata$y+mydata$offest

p<-ggplot()
for (i in 1:N){
  p<-p+ geom_linerange(data=mydata[mydata$variable==i,],aes(x=x,ymin=offest,ymax=V1_density_offest,group=variable,color=y),size =1, alpha =1) +
    geom_line(data=mydata[mydata$variable==i,],aes(x=x, y=V1_density_offest),color="black",size=0.5)
}
#ggplot() + 
#  geom_linerange(aes(x=x,ymin=offest,ymax=V1_density_offest,group=variable,color=y),mydata,size =1, alpha =1) +
p+scale_color_gradientn(colours=colormap)+
  #geom_line(aes(x, V1_density_offest,group=variable),mydata,color="black")+
  scale_y_continuous(breaks=seq(-Step*N,-Step,Step),labels=rev(labels_Y))+
  xlab("Time")+
  ylab("Class")+
  theme(
    panel.background=element_rect(fill="white",colour=NA),
    panel.grid.major.x = element_line(colour = "grey80",size=.25),
    panel.grid.major.y = element_line(colour = "grey60",size=.25),
    axis.line = element_blank(),
    text=element_text(size=13),
    plot.title=element_text(size=15,hjust=.5),
    legend.position="right"
  )

#------------------------------------------------------------------------------------------------------

ggplot() + 
  geom_ribbon(aes(x, ymin=offest,ymax=V1_density_offest, fill=variable),mydata, alpha=1,colour=NA)+
  geom_line(aes(x, V1_density_offest, color=variable,group=variable),mydata, color="black")+
  scale_y_continuous(breaks=seq(-40,-5,5),labels=rev(labels_Y))+
  theme_classic()+
  theme(
    panel.background=element_rect(fill="white",colour=NA),
    panel.grid.major.x = element_line(colour = "grey80",size=.25),
    panel.grid.major.y = element_line(colour = "grey60",size=.25),
    axis.line = element_blank(),
    text=element_text(size=15),
    plot.title=element_text(size=15,hjust=.5),#family="myfont",
    legend.position="none"
  )

所示。

可以看成是在

的基础上将Y轴坐标移除,并缩小数据类别之间的距离,这样可以有效地缩小图表的占有面积,同时可以很好地展示数据的完整信息,包括不同类别之间的数据差异比较。10.07.55.02.5技能瀑布图R中plot3D包的polygon3D0函数和segments3D0函数可以绘制三维面积图,lines3D0函数可以绘制三维曲线图,所以,综合这几个函数可以绘制三维瀑布图,其中图47-1(a)的具体代码如下所示。mydata()<-read.csv(Facting_Data.csv",check.names=FALSE)mydata<-data.frame(x=numericO.y=numeric0.variable=character())newdata$variable<-colnames(mydata())[i+1]mydata<-rbind(mydata,newdata)mydata$variable<-as.numeric(mydata$variable)group<-unique(mydata$variable)#获取ggplot2包默认的颜色方案gg_color_hue<-function(n)[hues=seq(15.375,length=n+1)colormap<-rev(gg_color_hue(M))pmar<-par(mar=c(5.1,4.1,4.1,6.1)df()<-mydata[mydata$variable==group[i]df<-rbind(df0.c(dfo$x[1],dfo$y[Ndf],dfo$variable[Ndf]))R中的ggplot2包提供的facet_grid()函数可以绘制如

所示行分面的带填充的曲线图。ggplot2包中的facet_grid()函数可以根据数据框的变量分行或者分列,以并排子图的形式绘制图表。

所示的行分面的带填充的曲线图具体代码如下所示。mydata()<-read.csv("Facting_Data.csV"stringsAsFactors=FALSE)mydata<-melt(mydata(),id.vars=“X_Axis")geom_area(color="black"size=0.25)+可以使用geom_linerange()函数或者geom_ribbon()函数绘制实现时间序列的峰峦图。其中geom_linerange(函数的参数(x,y,ymax),表示用直线连接(x,y)和(x,ymax)两点:geom_ribbon()函数的参数(x,y,ymax),表示用直线连接数据系列的(x,y)和(x,ymax)上所有的点,并使用颜色填充。

所示的峰峦图使用geom_linerange()函数实现绘制,其中关键是使用spline()函数对每条曲线插值得到N个数据点,其实现代码如下所示

有意思的是,这个专辑在2017年又重新流行了,因为那个设计极为特殊的封面(见

)。这里说的封面流行是指在数据可视化领域,其实它在流行文化里本就很流行。很多人用这个类似波谱的图来指征一种波动、起伏的感受,恰恰应和UnknownPleasueres中那种迷茫而强烈的情感,同时封面设计师又开放了版权,所以我们可以看到其在很多场景中的再现。

例如3D打印版、服装版、电影版等。甚至有人制作了一个网站来用鼠标生成类似风格的图。不过这个图仔细看是很有问题的:坐标轴是什么?

线的间隔是固定的吗?有什么意义?这图又是怎么做出来的?

《科学美国人》曾经对这张封面的源头进行过探索,据封面设计师PeterSaville的说法,这张图是从1977年出版的TheCambridgeEncyclopaediaofAstronomy里面的一幅关于脉冲星CP1919所发出的脉冲波叠加图(不是山峰,也不是波浪)上获取灵感进行的创作,但这所谓的“创作”实质上就是把颜色做了反转还去掉了坐标轴。不过这就说明源头是这本书吗?不,顺着这本书,有人追溯到了1974年出版的Graphis diagrams:Thegraphicvisualizationofabstract data一书。

进一步追溯,会发现更早出版的《科学美国人》(1971年1月刊)上也使用了这幅图。也就是《科学美国人》的“考古队”出门绕了个圈,又回到起点了。那么,《科学美国人》又是哪里搞到这幅图的呢?

事实上,1971年的文章之所以要用这幅图,是因为要介绍脉冲星这个20世纪60年代的重大发现,而这个发现的确切时间是1967年,也就是说这个图的出生日期就在1967年到1971年之间。然后我们就找到了HaroldD.Craft,Jr.在康奈尔大学的博士论文RadioObservationsofthePulseProfilesandDispersionMeasuresofTwelvePulsars,到这个时候真正的源头才出现(见

)。cutive pulsesfrom the pulsar CP1grg.Time increasestop.Pulsar period is 1.34 seconds.

UnknownPleasuers封面的源头,HaroldD.Craft,Jr.的博士论文插图当《科学美国人》联系到HaroldD.Craft,Jr时,他也顺道说了这幅图背后的故事。刚开始脉冲星在剑桥大学被发现后,他所在的团队就意识到自己其实拥有当时世界上最好的测量脉冲星的设备,也就是电子设备。然后,从测量结果上他们很快就发现脉冲星的脉冲存在一些漂移,也就是大脉冲里有小脉冲,这个结果发表在《自然》杂志上。

但他们觉得需要一个更直观的方式来观察这些脉冲的模式,然后就做了一些叠加图,很快就发现这种图前后的遮挡太过严重。作为一个程序员,遮挡问题其实就是一个漂移问题,所以他操起键盘(也可能是打孔卡)做出了一个漂移版,这样,当峰强度足够时才会出现遮挡,而这类峰正是我们想看的模式。不过不要高估那个年代的技术,他还得再找人用墨水重新勾描一遍才能清晰地放到博士论文里。

不过他显然不是流行文化爱好者,因为直到他同事有天闲逛时发现后告诉他,他才发现自己的图这么流行,然后他毫不犹豫地买下了有这张图的专辑与海报:it‘'s my image,and I ought to have a copy ofit.Radio Observations of thePulseProfiles and Dispersion Measures ofTwelvePulsars,Harold D. Craft,Jr[27].PhDThesis,September1970pages214-216),CornellUniversity

4.8 相关系数图

一句话:相关系数图:相关系数矩阵可视化,变量间相关性一眼可见。

相关系数图就是相关系数矩阵的可视化。相关系数矩阵(correlationmatrix)也叫相关矩阵,是由矩阵各列间的相关系数构成的。也就是说,相关矩阵第i行第列的元素是原矩阵第i列和第j列的相关系数。

如果一个数据集有P个相关变量,求两变量之间的相关系数,共可得C=P(P-1)/2个相关系数。如按变量的编号顺序,依次将它们排列成一数字方阵,此方阵就称为相关矩阵。常用字母R表示。

从左上到右下方向的对角线上,均是两个相同变量的相关,其数值均是1,对角线以上部分的相关系数与以下部分的相关系数是对称的。在概率论和统计学中,相关也称相关系数或关联系数,显示两个随机变量之间线性关系的强度和方向。在统计学中,相关的意义是用来衡量两个变量相对于其相互独立的距离。

在这个广义的定义下,有许多根据数据特点而定义的用来衡量数据相关的系数。对于不同数据特点,可以使用不同的系数。最常用的是皮尔逊积差相关系数。

其定义是两个变量协方差除以两个变量的标准差(方差)。相关系数矩阵的可视化图表类型如

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(ggplot2)  
library(RColorBrewer)  
library(reshape2) 

#------------------------------------------(a)热力图 --------------------------------------------------------
data("mtcars")
mat <- round(cor(mtcars), 1)
mydata <- melt(mat)  
colnames(mydata)<-c("Var1","Var2","value")
ggplot(mydata, aes(x = Var1, y = Var2, fill = value,label=value)) +  
  geom_tile(colour="black") +
  geom_text(size=3,colour="white")+
  coord_equal()+
  scale_fill_gradientn(colours=c(brewer.pal(7,"Set1")[2],"white",brewer.pal(7,"Set1")[1]),na.value=NA)+
  theme(panel.background=element_rect(fill="white",colour=NA),
        panel.grid.major = element_line(colour = "grey60",size=.25,linetype ="dotted" ),
        panel.grid.minor = element_line(colour = "grey60",size=.25,linetype ="dotted" ),
        text=element_text(size=15),
        plot.title=element_text(size=15,family="myfont",hjust=.5)
  )


#------------------------------------------(b) 气泡图 --------------------------------------------------------

mydata$AbsValue<-abs(mydata$value)


ggplot(mydata, aes(x= Var1 , y=Var2)) +
  geom_point(aes(size=AbsValue,fill = value), shape=21, colour="black") +
  scale_fill_gradientn(colours=c(brewer.pal(7,"Set1")[2],"white",brewer.pal(7,"Set1")[1]),na.value=NA)+
  scale_size_area(max_size=12, guide=FALSE) +
  theme(
    text=element_text(size=15,face="plain",color="black"),
    axis.title=element_text(size=13,face="plain",color="black"),
    axis.text = element_text(size=12,face="plain",color="black"),
    legend.position="right"
  )

#------------------------------------------(d) 椭圆图-------------------------------------------------------
library(corrplot)
library(matlab)

color<-colorRampPalette(c(brewer.pal(7,"Set1")[2],"white",brewer.pal(7,"Set1")[1]))(100)

corrplot(mat, method="ellipse",order ="alphabet",pch.col = "black",col=color)

#------------------------------------------ (e)气泡标签图-------------------------------------------------------
corrplot.mixed(mat,order ="alphabet",pch.col = "black",bg = "grey80", lower.col = color, upper.col = color)

所示,主要包括热力图、气泡图或方块图、椭圆图。(1)热力图。热力图就是将一个网格矩阵映射到指定的颜色序列上,恰当地选取颜色来展示数据,如

所示。在相关矩阵中,所有的数据都在一1到1之间,我们不仅要关注相关系数的绝对值大小,同时更加看重它们的正负号。因此,相关矩阵的颜色图和一般矩阵的颜色图应该有所区别:即应当选取两种色差较大的颜色序列来展示不同符号的相关系数。

其中,红色表示正相关系数,蓝色表示负相关系数。也可以在

热力图的基础上添加数据标签(相关系数的数值)如

所示。这样可以使读者更加清晰地观察数据。(2)气泡图。

气泡图是将一个网格矩阵映射到气泡的面积大小和颜色序列上,这样使用两个视觉特征表示数据,可以让读者更加清晰地观察数据,如

所示。具体做法是:①用气泡的面积来表示相关矩阵的绝对值大小。②两种色差较大的颜色序列来展示不同符号的相关系数,其中,红色表示正相关系数,蓝色表示负相关系数。

也可以将圆圈换成方块,如

所示。或者在上半部分使用气泡图显示相关系数,而下半部分使用相关系数数值展示结果,这样也可以比较清晰、全面地表达数据,如

所示。(3)椭圆图。椭圆图是利用椭圆的形状来表示相关系数:离心率越大,椭圆越扁,对应绝对值较大的相关系数:离心率越小,椭圆越圆,对应绝对值较小的相关系数。

椭圆长轴的方向来表示相关系数的正负:右上一左下方向对应正值,左上一右下方向对应负值,如

所示。观察图4-8-1(d可以发现:椭圆图比较失败,因为它将最大的面积留给了相关性最弱的数据,给其他信息的获取造成了干扰。所以不建议大家使用椭圆图表示相关系数矩阵。

1.00.50.00.00.5mpgcyldisphp dratwqsecvsamgearcarbam carb cydisp dratgear hp mpg qsecvstamcarbcyl disp drat gear hp mpgqsecswt0.81.00.50.00.6am carb cyl disp drat gear hp mpg qsecvswt技能相关系数图R中ggplot2包提供的geom_tile()函数和geom_point()函数可以绘制

(f),使用corrplot包提供的corrplot()函数可以绘制

(e),其中

的核心代码如下所示

f相关系数热力图geom_tile(colour="black")+geom_text(size=3.colour=“white")+scale_fill_gradientn(colours=c(brewer.pal(7."Set1")[2]."white",brewer.pal(7,Set1")[1]),na.value=NA)#绘制

相关系数气泡图mydata$AbsValue<-abs(mydata$value)geom_point(aes(size=AbsValue,fill =value),shape=21,colour="black")+scale_fill_gradientn(colours=c(brewer.pal(7."Set1")[2],"white",brewer.pal(7."Set1")[1]).na.value=NA)+scale_size_area(max_size=12.guide=FALSE))

4.9 韦恩图

一句话:韦恩图:集合重叠关系,几组数据共有多少。

韦恩图(venndiagram),也叫温氏图、维恩图、范氏图,用于显示元素集合重叠区域的图表(见

#EasyCharts团队出品,
#如有问题修正与深入学习,可联系微信:EasyCharts

library(VennDiagram)
library(RColorBrewer)
venn.diagram(list(B = 1:1800, A = 1571:2020,c=500:1100),fill = c(brewer.pal(7,"Set1")[1:3]),
             alpha = c(0.5, 0.5,0.5), cex = 2,
             cat.cex=3,cat.fontface = 4,lty =2, fontfamily =3, 
             resolution =300, filename = "trial2.tiff")

)。韦恩图是关系型图表,通过图形与图形之间的层叠关系,来表示集合与集合之间的相交关系。每个集合通常以一个圆圈表示。

每个集合都是一组具有共同之处的物件或数据。当多个圆圈(集)相互重叠时,称为交集(intersection),里面的数据同时具有重叠集中的所有属性。集合;③内部文本标签。

一般来说,超过5个集合的场景,不适合使用韦恩图。适合场景1:表示两个集合相交关系,有一个集合A,有一个集合B,相交集合为C。两个维度数据,分类数据映射集合名,关系数据映射集合关系。

适合场景2:表示3个集合相交关系,有集合A、B、C。两个维度数据,分类数据映射集合名,关系数据映射集合关系。适合场景3:表示4个集合相交关系,有集合A、B、C、D。

两个维度数据,分类数据映射集合名,关系数据映射集合关系。技能韦恩图R中VennDiagram包的venn.Diagram()函数、gplots包的venn()函数、limma包的vennDiagram()函数、venneuler包的venneuler()函数都可以绘制韦恩图,但是以VennDiagram包的venn.Diagram()函数绘制的韦恩图效果最佳,具体实现代码如下所示。venn.diagram(list(B=1:1800.A=1571:2020,c=500:1100),fill =c(brewer.pal(7,Set1")[1:3]).alpha=c(0.5,0.5,0.5),cex=2,cat.cex=3,cat.fontface=4.Ity =2,fontfamily=3.resolution=300,filename="trial2.tiff")

4.10 树形图

一句话:树形图:聚类结果的树状展示,看样品/变量如何一步步合并。

树形图(dendrogram)是表示连续合并的每对类之间的属性距离的示意图。为避免线交叉,示意图将以图形的方式进行排布,使得要合并的每对类的成员在示意图中相邻,如

所示。树形图工具采用等级聚类算法。程序首先会计算输入特征文件中每对类之间的距离。

然后迭代式地合并最近的一对类,完成后继续合并下一对最近的类,直到合并完所有的类。在每次合并后,每对类之间的距离会进行更新。合并类特征时采用的距离将用于构建树形图。

ch_图4-10-2(a)_树形图.pngch_图4-10-2(c)环形树形图.png
图4-10-2

所示为4种不同类型的树形图,分别为纵向树形图、横向树形图、环形树形图和进化树形图。Dodge Challenger PontiacFirebird技能树形图"dendrogram”)、factoextra包的fviz_dend()函数都可以绘制树形图,factoextra包绘制的树形图更加美观,

所示树形较长都是使用factoextra包绘制的,其中

的具体代码如下所示。当horiz=TRUE时,坐标轴转置,效果如

所示。调节参数type=c("rectangle",“circular","phylogenic")),可以得到不同类型的树形图,其中“rectangle"对应

(b),"circular对应

(c),“phylogenic"对应

也可以使用circlize包的circlize_dendrogram()函数绘制

4.11 圆堆积图

一句话:圆堆积图:圆套圆表示层次结构,面积可表达第三维。

圆堆积图(circlepackingchart)是树形图的变体,使用圆形(而非矩形)一层又一层地代表整个层次结构:树木的每个分支由一个圆圈表示,而其子分支则以圆圈内的圆圈来表示(见

)每个圆形的面积也可用来表示额外任意数值,如数量或文件大小。我们也可用颜色将数据进行分类,或通过不同色调表示另一个变量,如

所示。技能圆堆积图R中ggraph包的ggraph()函数可以绘制圆堆积图。edges和vertices的数据结构如

(a)所示,把层次关系的数据转换成两列的数据,每行左边from列的数据隶属于右边to列的数据。使用graph_from_data_frame()函数可以将数据框(data.frame)的数据转换成graph类型的数据,并可以使用ggraph()函数绘制,其中核心参数layout=circlepack(圆堆积图);geom_node_circle()函数表示圆圈的视觉通道映射设定,geomnodetext()函数表示圆圈的标签添加与设定。

中圆堆积图的核心代码如下所示。其中,ggraph()函数的核心参数layout有很多种选择,可以绘制网络图(networkchart)Hive图、矩形树状图(treemap)旭日图、树形图(dendrogram)。#过滤选择数据集vertices$size<-runif(nrow(vertices))#构造graph类型的数据结构mygraph<-graph_from_data_frame(edges,vertices=vertices)geom_node_circle(aes(fill =depth))+1ggraph包的参考网址:https://www.data-imaginist.com/2017/ggraph-introduction-layoutsgeom_node_text(aes(label=shortName,filter=leaf,fill=depth,size=size))+

4.12 和弦图

一句话:和弦图:实体间关系强度,节点圆周分布、弧线连接。

和弦图(chorddiagram)可以显示不同实体之间的相互关系和彼此共享的一些共通之处,因此这种图表非常适合用来比较数据集或不同数据组之间的相似性。节点围绕着圆周分布,点与点之间以弧线或贝塞尔曲线彼此连接以显示当中关系,然后再给每个连接分配数值(通过每个圆弧的大小比例表示)。此外,也可以用颜色将数据分成不同类别,有助于进行比较和区分,如

所示。和弦图的特点在于,它有助于我们看出数据之间的关系,适用于比较数据集或不同数据组之间的相似性。连接两个数据点的弧线可以以颜色、弧线与圆的接触面积大小为不同的维度,表达不同的数值。

正因为和弦图能在表达大量复杂数据的同时,尽可能把这种复杂的关系可视化,所以和弦图被广泛应用于各个方面。和弦图的缺点是过于混乱,尤其是当要显示太多连接的时候。刻度线表示尺度条带触及行分段末刻度线表示分根据行分段设定一条带未触及行分段段的大小条带颜色条带根据分段大小排序显示为了区分和弦图在数据表达复杂程度上的不同,我们尝试把它分成几个等级,如

ch_图4-12-2(a)和弦图.png
图4-12-2

所示。(1)入门级:在单纯的数据关系展示上,弧线的意义就在于表达两个数据之间存在一定的关系。弧线与圆的接触面积和颜色没有数值的意义,它可以指示简单的关系(A-B)具有位置信息(A-C)或单向关系(A-D),如

所示。(2)普通级:你也可以在弧线与圆的接触面积上赋予数值意义,表示两个数据之间的关系程度或者比例关系,如

所示。1有关和弦图更加详细的内容可以参考:http://circos.ca/presentations/articles/vis_tables1/?report-reader(3)高手级:当弧线根据相关数据着色时,我们会更容易发现数据间的关系。值得注意的一点是,弧线可以根据源数据或目标数据着色。

同样是展示A与B的关系,但弧线的颜色可以由A决定(见

),也可以由B决定(见

)。(4)殿堂级:有的弧线与表示比例关系的弧线非常相似,也是两端粗细不同,却是两个数据的集合表现。

表现的是(A,B)的值为2,(B,A)的值为10,分别由两条粗细不一的弧线表示。

将两个数值结合起来,根据弧线与圆接触面积的大小,表达不同的数值,C则表达了两倍的数值。(5)神话级:更进一步,我们可以通过设计弧线是否接触到圆来区分数据类别。

(f中弧线与圆相触的为数据的行,相反则为列。技能和弦图R中circlize包提供了chordDiagram()函数可以绘制和弦图,该函数既可以使用数据框(data.frame)类型的数据,又可以使用矩阵(matrix)类型的数据。矩阵的数据结构如

所示,矩阵中的数据M表示变量Y第i个类别和变量X第j个类别的关系数值,比如两者的相似性。图4-12-3所示和弦图的具体实现代码如下所示。特别强调的是,circlize包可以绘制更加复杂的和弦图,比如添加环状分布(极坐标)分布的散点图、柱形图等,更多内容可以参考并学习官方网站。

1[28]mat=matrix(sample(18,18),3,6)df=data.frame(from=rep(rownames(mat),times=ncol(mat),to=rep(colnames(mat),each=nrow(mat)1http://zuguang.de/circlize_book/book和弦图的故事虽然和弦图的名字与几何学密切相关,但最初开始使用和弦图的却是生物学家[29]。面对纷繁复杂的基因组数据,生物学家巧妙地利用和弦图展示基因组之间的关系。这种类型的图表最先于2007年在《纽约时报》基因组的信息图表中出现(见

)。Close-Ups of the Genome,Species by Species by SpeciesScientists aresequencing thegenomesofmore than 70 organismsTheavallablity ofthe largedegreoof similaritybetweenthe firstchromosomes affouranimals to thatofaanswer questions about one animal's genome usng normation derivea fram another.Ahuman.Not surprisingty.the humansis ciosest to the chimp'sCanadiangenomics scientistMartin Kzywinskihas createda computer program calledOuter bandpresents eacspecesitTodownload thefreeprogramorviewctherchtornosom.Numbers representmiignexamples:http://mkweb.bcgsc.ca/circos/of base pais on the chromosome,Line charts show what percentissmar oeach f theother fiveThe chart aove shows the similanity of theBRCA1protein.implicated inearly breastcancer to other genesonhuman chromoThe image above illustrates the duplicaton wthun the human genome Here.chromosomes1.2.4and7areshowngenome.thereisreason tosuspectfhat theseTwetegionsDothgenerafebasic functionsthal are vitalto bothspeciesanddonot perit variationor banarepresere.How chromosomeooks.wfien stamed.和弦图的特点在于,它有助于我们看出数据之间的关系,适用于比较数据集或不同数据组之间的相似性(猴子、老鼠、猩猩、鸡与人的染色体实验就是发现不同数据组的相似性)。连接两个数据点的弧线可以以颜色、弧线与圆的接触面积大小为不同的维度,表达不同的数值。

4.13 桑基图

一句话:桑基图:数据流动的路径与流量可视化。

对于该图的称呼莫衷一是:有直接根据象形定名它为“决策树”(decisiontree):或者根据线段的层级流动称之为“流程图/作业图”(flowdiagram):还有一些图形网站称其为“冲击图”(alluvialdiagram),但对其最准确的定义应当是:桑基图(sankeydiagram)。桑基图的名称来源于爱尔兰船长。1898年,爱尔兰船长马修·亨利·菲尼亚斯·里亚尔·桑基(MatthewHenryPhineasRiall Sankey)使用了这种类型的图表展示了蒸汽的能源效率。

与此同时,这个图也以船长的名字命名为“桑基图”。在今天的数据可视化领域,桑基图有利于展现分类维度间的相关性,以流的形式呈现共享同一类别的元素数量。特别适合表达集群的发展,比如展示特定群体的人数分布等,通常应用于能源、材料成分、金融等数据的可视化分析。

所示,桑基图主要由边、流量和支点组成,其中边代表了流动的数据,流量代表了流动数据的具体数值,节点代表了不同分类。桑基图最明显的特征如下。(1)起始流量和结束流量相同,所有主支宽度的总和与所有分出去的分支宽度总和相等,保持能量的平衡;(2)在内部,不同的线条代表了不同的流量分流情况,边的宽度与流量成比例地显示,边越宽,数值越大。

边流量节点数值:180所以,在使用桑基图的过程中,桑基图要保持能量的守恒。无论数据怎样流动,数据的总量从开始到结束都不能有任何变化,不能在中间过程创造出数据,流失(损耗)的数据应该流向表示损耗的支点(见

)。技能桑基图R中的ggalluvial包提供了geom_flow()函数和geom_stratu()函数,可以结合ggplot2包的ggplot()函数绘制桑基图。其中,geom_stratu()函数控制节点的视觉通道映射设定,主要数值由stratum和weight决定;geom_flow()函数控制边的视觉通道映射设定,主要由alluvium和weight决定。

(a)的实现代码如下所示。fill=response,label=response))+geom_flow(alpha=0.7,color=“darkgray")+geom_text(stat=“stratum".size=3.5)+axis.text.x=element_text(color="black",size=12).axis.title.x=element_blankO.axis.text.y=element_blankO.axis.line =element_blank(.axis.ticks =element_blank()桑基图的故事最著名的桑基图是查尔斯·米纳德(CharlesMinard)绘制的1812年拿破仑俄国战役地图。这张战役地图将一张桑基图叠加到一张地图上,是一张流程图与地图结合的图表(见

)。TABLEAUCRAPHl()UEdea tanpratate dghestherimetre dReaur dess桑基图中的土黄色部分描绘了拿破仑军队在欧洲的移动和数量变化情况,显示了在1812年6月,拿破仑带领了42万人入侵俄国。然而随着战争不断深入,军队人数一路减少,到了战败撤退时,只剩下1万人。

这张最早的桑基图创建于1869年,但它那时候还不叫桑基图。29年后,到了1898年,爱尔兰船长马修·亨利·菲尼亚斯·里亚尔·桑基使用了这种类型的图表展示了蒸汽的能源效率。与此同时,这个图也以船长的名字命名为“桑基图”。

1图片来源:https://en.wikipedia.org/wiki/Sankey_diagram#/media/File:Minard.png

本章一句话总结:数据关系选图:散点图加拟合线看趋势、气泡图用大小加第三维、等高线/切面图看曲面、瀑布图看增减分解、Venn图看集合重叠。
×