先做个散点图
对于我这个不经常用R作图的人来说,当我决定通过用R做一张图的时候,我开始搜索R的语法。因为我不习惯系统学习并搞懂整体的逻辑后再去作图。但当我搜索一会儿后我就会得出一个结论:R是“反人类”的。
因为我要做的是这么一个图。这个图的数据来自一本教科书,利用https://automeris.io/WebPlotDigitizer/ 可以将从图片中提取数据,当然,是手动的。
这个图中有7个不同的数据来源,有的数据来源中的数据有两个不同的温度。例如Westphal (in Evans, 1965)的数据。不同的温度的数据,需要通过两种颜色区分开,不同来源的数据需要通过点的形状区分开。我首先想到的思路是把数据根据要区分的属性分成不同的类,每一类分别用语句画到图上,如果用MATLAB我就想这么干。然而R不是这么想的。以下是我个人的理解,不是从书中系统学来的。
R作二维散点图时,一个图只能做一组XY对应的数据。不能把很多组数据依次画上去。那就只能把所有不同属性的数据放到同样的列,把属性作为对应的列。整理后,我的数据是这样的:
首先,要把这个数据导入RStudio
library(ggplot2) # 把用到的包导入环境
library(openxlsx)
setwd("~/Downloads/graphdata") #更改工作文件夹到数据Excel文件所在的路径,否则找不到文件
# 读取文件中的数据,需要指定文件名和数据页名(或数据页的编号)
dcdata<- read.xlsx(xlsxFile ="Book1.xlsx", sheet = "Sheet1")
然后后面,就费了大劲了,因为我根本不熟悉ggplot的语法。只能从网上搜例子。
遇到了一下困难:
- 摄氏度℃这个符号在图例中显示不了;
- 如何更改坐标轴为对数;
- 以点的形状区分数据,默认只能有6个。要向要更多的形状类型,就得用上
scale_shape_manual
这个命令。
最后的代码是这样的。
ggplot(dcdata,aes(x=Fre,y=Imag,shape=ref,color=temp))+
scale_x_log10()+ # 更改x轴为对数形式
scale_y_log10()+
geom_point(size=2)+ #设置点的大小
scale_shape_manual(values = 1:7)+ #手动设置点的形状,编号1到7
scale_color_discrete(labels=c("-1°C", "-15&-20°C")) # 手动更改legend标签文字,显示摄氏度单位
挑简单的说吧。先说℃这个符号的显示。
咱也没计算机基础,反正就知道用中文输入法打ssd
就能打出这个符号来。但在图中它就是显示不出来。后来搜到,原来这个摄氏度有两种写法:
- 一种是中文中的写法,就是刚说的中文输入法中能打出来的,它对应的是的Unicode代码是2103。是个整体的符号。但之前我用R作图的时候,坐标轴可以直接输出。但现在图例中却显示不出来。
- 另一种是英文的写法,实际上是”度“这个单位加上大写字母C。而°这个符号对应的Unicode代码是00B0。中文输入法下输入“du”也能输出这个符号。但我用Mac的Unicode Hel Input输入法输入“00B0”(不用管大小写)无论如何也输出不了“°”这个符号。到现在也无法解决这个问题。所以,除了用中文输入法直接输入“°”,可以从别的地方复制一个度过来。
散点图上再增加几条独立的线
实际上,这个图中还应该有一个模拟的曲线,和实验测量的数据去比较。而模拟的曲线需要通过程序模拟出一组X-Y数据画出来。又是折腾了很长时间才摸索出来怎么画。因为,我对语法背后的逻辑没弄懂,都是照葫芦画瓢。所以,想变化了,就不知道怎么变。
目前,画出来的效果是这样的。
在之前的图上,我又增加了两条线。这两条线都是基于模型模拟出来的数据画的。模型模拟的数据我先放到第二个Excel的sheet里,数据样式如下:
Imag2和Imag3是同一个模型模拟的不同参数设置的结果,Fre2是自变量。
代码进行了修改,如下:
library(ggplot2)
library(openxlsx)
setwd("~/Downloads/graphdata")
#把数据从Excel中导入环境
dcdata<- read.xlsx(xlsxFile ="Book1.xlsx", sheet = "Sheet1")
simdata2<- read.xlsx(xlsxFile ="Book1.xlsx", sheet = "Sheet2")
a<-ggplot()+ # 因为要在图中画来自不同数据组的数据,所以这里什么都不设置了
scale_x_log10()+
scale_y_log10()+
geom_line(simdata2,mapping=aes(x=Fre2,y=Imag2),color="red")+ #画一条线,数据来自模拟数据,”mapping=“是必须有的,否则会报错
geom_line(simdata2,mapping=aes(x=Fre2,y=Imag3),color="blue")+ #再画一条线,给线赋予不同的颜色
geom_point(dcdata,mapping=aes(x=Fre,y=Imag,shape=ref,color=temp))+ # 画点,
scale_shape_manual(values = 1:7)+ #设置点的形状
scale_color_discrete(labels=c("-1°C", "-15&-20°C")) #设置点颜色的图例,因为原数据中的摄氏度符号显示不出来,所以这里单独再设置一下
到了这一步,实际上还有没解决的。我先休息休息,太tm累了。好希望有个人给我用人话讲讲ggplot的逻辑。
最后,调整一些杂项
上面做完后,还有一些小问题,比如调整坐标轴的内容、字体等,两条曲线没有图例。
图例的问题我实在是不想弄了,所以想办法凑合了一下,不会弄。
调整字体的从网上搜搜就能搜到,比较简单。
省略前面导入数据的代码,最后作图的代码如下:
ggplot()+
scale_x_log10()+
scale_y_log10()+
geom_point(dcdata,mapping=aes(x=Fre,y=Imag,shape=ref,color=temp),size=3)+
scale_shape_manual(values = 1:7)+
scale_color_discrete(labels=c("-1°C", "-15&-20°C"))+
geom_line(simdata2,mapping=aes(x=Fre2,y=Imag2),color="red")+
geom_line(simdata2,mapping=aes(x=Fre2,y=Imag3),color="blue")+
labs(x="Frequncy/GHz",y="Imaginary part",size=16)+ #修改坐标轴文字
#给两条曲线加个箭头,加个文字,因为我实在不知道怎么给他们加个图例
#请高手看到后,留言告诉我怎么给这两条曲线加图例
geom_segment(aes(x = 0.35,
y = 0.004,
xend = 0.2,
yend = 0.00297649316), #箭头的起始位置得一点点儿试着调整
arrow = arrow(length = unit(0.2, "cm")))+
annotate(geom="text",
x=0.5,y=0.0043, # 文字的位置也得一点儿点儿调整
size=5,
label="Modle Simulated @-1°C")+
geom_segment(aes(x = 0.65,
y = 0.00022,
xend = 0.8,
yend = 0.00026500395458),
arrow = arrow(length = unit(0.2, "cm")))+
annotate(geom="text",
x=0.35, y=0.0002,
size=5,label="Modle Simulated @-15&-20°C")+
#调整一下坐标轴刻度和标题的文字大小,字体就让它默认吧,好烦。
theme(axis.text.x=element_text(size=14),
axis.text.y=element_text(size=14),
axis.title.x=element_text(size=16),
axis.title.y=element_text(size=16),
legend.text =element_text(size=12))
做出的图是这样的。
为了做这张图,耽误了我好几天的时间。但也对ggplot作图语言背后的逻辑稍微多了解点儿。当然这个图还有很多可以调整和改进的地方,以后继续了解,继续骂ggplot。等我不骂它了,说明我真正了解了。