目录
{: .no_toc}
- 目录 {:toc}
开始
我们常常要利用R来绘制简单的时序图,当时间序列间隔以天为单位时,我们可以利用ts()
函数将数据非常方便的转换成R可以识别的时间对象,然后在利用plot.ts()
函数绘制就行了。
但如果我们的时间序列是以更高频的形式呈现,那么简单粗暴的ts()
就显得不够用了,因此今天介绍一下如何绘制高频数据的时序图。
R中除了有Date这种时间格式之外,还有许多姿势任君挑选(手动微笑),下面介绍三种不同的时间格式。
转换成xts格式
f1<-file.choose()
x<-read.csv(f1,header=T,row.names = 1)
head(x)
#> count
#> 2014/8/25 0:00 72
#> 2014/8/25 5:00 56
#> 2014/8/25 6:00 1410
#> 2014/8/25 7:00 5093
#> 2014/8/25 8:00 5257
#> 2014/8/25 9:00 3771
例子中的数据是每天不同时段的车流量大小。
这里需要注意的技巧就是读取数据时设置参数’row.names=1’,意思是将第一列作为数据的‘rownames’,因此可以看到’x’读入之后数据只有一列,其实本来还有一列是时间。可以理解成将时间戳作为了’count’的一个标签。
x_xts<-as.xts(x)
plot.xts(x_xts)
xts作为zoo的扩充,提供了一系列针对时间序列相关的函数。
xts is an R package offering a number of functionalities to work on time-indexed data. xts extends zoo, another popular package for time-series analysis.
转换成zoo格式
x_zoo<-zoo(x,order.by = as.factor(rownames(x)))
plot.zoo(x_zoo)
这里的’zoo()’函数与’as.xts’类似,也是给’count’变量赋予时间标签,’order.by’参数就是指定具体的时间标签索引。
不知道大家有没有疑问,如果出现相同的日期怎么办? 为什么order.by为factor的数据类型?
转换成POSIXct格式
但是私以为上面两幅图还是挺丑的(对黑白没有爱),出于对颜值的追求,是时候祭出绘图包中的神器ggplot2了。但是首先我们要把文本格式的时间转换成ggplot能够识别的对象。
x$time<-strptime(rownames(x), "%Y/%m/%d %H:%M")
# as.POSIXct(rownames(head(x)),format="%Y/%m/%d %H:%M")
这里’strptime()‘的作用就是将各种乱七八糟文本结构的时间数据,转换成ggplot能识别的标准时间格式,需要注意的是第一个参数是我们所拥有的高频数据的时间列,第二个参数是这个时间列的具体写法,如果你的时间列写法是’16-5-29 16:05:00’,那么我们第二个参数设置就是’y%-m%-d% %H:%M:%S’。接下来就可以愉快的画图了。
注:x_xts
的class为xts,其index(x_xts)
为“POSIXct” “POSIXt” ,于是就可以省去了转换这一步。相应的画图代码为:ggplot(x_xts,aes(x=index(x_xts),y=count))+geom_line()
ggplot画图
ggplot(x,aes(x=time,y=count))+geom_line()
进一步细化,不同日期标注不同色块?
解决办法一
# 参考有关教程得到的方案:
#添加一个新的data.frame
day <- unique(strptime(x$time,format = "%Y-%m-%d"))
time_df <- data.frame(min=day,
max=day+60*60*24,
fill=as.factor(as.character(day)))
#一定要注意那两个 NULL,少了就会报错。
ggplot(data=x,aes(x=time,y=count))+
geom_rect(aes(NULL,NULL,
xmin=min,
xmax=max,
ymin=min(x$count),
ymax=max(x$count),
fill=fill),data=time_df) +
geom_line()
#通过上面的例子我相信你已经理解了图层叠加的原理了,
#下面这个例子更直接
ggplot() + geom_rect(data=time_df,
aes(xmin=min,xmax=max,
ymin=min(x$count),ymax=max(x$count),
fill=fill),colour="white") +
geom_line(data=x, aes(x=time,y=count))
解决办法二
小赵摸索出来的方法:
#对数据整体修改,添加变量
x$day<-strptime(x$time,format = "%Y-%m-%d")
#先线再色块, fill 为连续变量,图层叠加原理
ggplot(x,aes(x=time,y=count))+ geom_line()+
geom_rect(aes(xmin=day,
xmax=day + 606024, #一天,单位秒
ymin=min(count),
ymax=max(count),
fill=day),colour="white",alpha=0.1)
#先色块再线 ,fill 为factor
##美化
windowsFonts(myfont=windowsFont("微软雅黑"))
ggplot(x,aes(x=time,y=count)) +
geom_rect(aes(xmin=day,
xmax=day + 606024,
ymin=min(count),
ymax=max(count),
fill=as.factor(as.character(day))),colour="white")+
geom_line() +
labs(title="测试时间格式",fill="日期") +
theme(title=element_text(family = ‘myfont’,face = "bold"),
text=element_text(family = ‘myfont’))
总结
- 在用xts或者zoo的时候,碰到了好多坑。下次会专门写一篇处理时间格式的数据
- 在用ggplot画图的时候,坐标轴的类型一定要是一样的!比如这次横坐标的time是数据类型为
POSIXct
,如果用as.Date
后的类型的话会报错了 - 通过这个例子更深入理解了图层语法
更新
这篇当时写的时候也是刚刚接触ggplot画时间序列的图,在后面的不断学习中又get到新的技能,所以准备补充更新一下。
关于调整x轴时间间隔与标签
scale_x_datetime(date_breaks = "5 mins",
date_labels = %H:%M",
date_minor_breaks = "1 min")
这里的可以写成10 secs
,或者1 hour
等自定义的时间间隔。
关于zooming
# without clipping
coord_cartesian(xlim=c(0,100),ylim=c(10,20))
# with clipping
xlim(0,100) + ylim(10,20)
# or
scale_x_continous(limits=c(0,100) +
scale_y_continous(limits=c(10,20)
不定期更新中