日历图可以反应一年中每天的全部数据,使用阶梯渐变的颜色填充,这样一面中比较突出的数据就更加容易被察觉。并且日历图对比常规的时序图也更加直观,充满了高级感。
导入绘图包
library(ggplot2)
library(data.table) #提供data.table()函数
library(ggTimeSeries)
library(RColorBrewer)
library(dplyr)
其中data.table库可以方便我们整理数据,因为日历图想做精细化对数据有一定的要求。
ggTimeSeries是专门用于将数据转为时间序列数据,并且会将原本的格式转化为更为标准的时间序列格式。
数据处理
dat <- data.table(
date = seq(as.Date("1/01/2014", "%d/%m/%Y"),
as.Date("31/12/2017", "%d/%m/%Y"),"days"),#构造时间格式
ValueCol = runif(1461)#构造对应的值
)
dat[, ValueCol := ValueCol + (strftime(date,"%u") %in% c(6,7) * runif(1) * 0.75), .I]#添加周末效应
dat[, ValueCol := ValueCol + (abs(as.numeric(strftime(date,"%m")) - 6.5)) * runif(1) * 0.75, .I]#添加月度效应
dat$Year<- as.integer(strftime(dat$date, '%Y')) #构造年份
dat$month <- as.integer(strftime(dat$date, '%m')) #构造月份
dat$week<- as.integer(strftime(dat$date, '%W')) #构造周将周转换为数值方便给横坐标做尺度
MonthLabels <- dat[,list(meanWkofYr = mean(week)), by = c('month') ]#按月分组构造一个两列变量
MonthLabels$month <-month.abb[MonthLabels$month]#month.abb()函数用作将数字变为月份缩写
这里是自定义了一个时间序列的数据包括其中的列包括年份、月份、周、然后又对月份值进行了中英文的互换。
绘制日历图
ggplot(data=dat,aes(date=date,fill=ValueCol))+
stat_calendar_heatmap()+
scale_fill_gradientn(colours= rev(brewer.pal(11,'Spectral')))+ #实现渐变色
facet_wrap(~Year, ncol = 1,strip.position = "right")+#按年进行分面
scale_y_continuous(breaks=seq(7, 1, -1),labels=c("Mon","Tue","Wed","Thu","Fri","Sat","Sun"))+ #构造纵坐标
scale_x_continuous(breaks = MonthLabels[,meanWkofYr], labels = MonthLabels[, month],expand = c(0, 0))+ #构造横坐标
xlab(NULL)+
ylab(NULL)+
theme( panel.background = element_blank(),
panel.border = element_rect(colour="grey60",fill=NA),
strip.background = element_blank(),#设置分面头背景色
strip.text = element_text(size=13,face="plain",color="black"),#设置分面头文本
axis.line=element_line(colour="black",size=0.25),
axis.title=element_text(size=10,face="plain",color="black"),
axis.text = element_text(size=10,face="plain",color="black"))#设置轴标签的字体大小为10,不使用粗体,颜色为黑色。
上面的图反应的是2014-2017年的数据,具体的值是随机序列,并没有实际含义,我们可以把它当作某个事情发生的概率,或者出现的次数都可以。
有时候我们可能不需要这么多年的数据,只想对其中某一年的数据进行分析,那么这里可以在整个数据中进行筛选。
数据筛选
dat17 <- filter(dat,Year==2017)[,c(1,2)]
dat17$month <- as.integer(strftime(dat17$date, '%m')) #月份
dat17$monthf<-factor(dat17$month,levels=as.character(1:12),
labels=c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),
ordered=TRUE)#将月份转化为缩写并定义排序方式,直接缩写会导致月份乱序
dat17$weekday<-as.integer(strftime(dat17$date, '%u'))#周数
dat17$weekdayf<-factor(dat17$weekday,levels=(1:7),
labels=(c("Mon","Tue","Wed","Thu","Fri","Sat","Sun")),
ordered=TRUE)#将星期按顺序排
dat17$yearmonth<- strftime(dat17$date, '%m%Y') #月份
dat17$yearmonthf<-factor(dat17$yearmonth)
dat17$week<- as.integer(strftime(dat17$date, '%W'))#周数
dat17<-dat17 %>% group_by(monthf)%>%mutate(monthweek=1+week-min(week))
dat17$day<-strftime(dat17$date, "%d")
上面对2017年的数据进行了筛选,去除了其他年份的数据并对数据进行了月份等的提取。
2017年份日历图
ggplot(dat17, aes(weekdayf, monthweek, fill=ValueCol)) +
geom_tile(colour = "white") +
scale_fill_gradientn(colours=rev(brewer.pal(11,'Spectral')))+
geom_text(aes(label=day),size=3)+
facet_wrap(~monthf ,nrow=3) +
scale_y_reverse()+#翻转坐标
xlab("Day") +
ylab("Week of the month") +
theme(strip.text = element_text(size=11,face="plain",color="black"))
最终效果图如上可见数据就如日历一般被排列在一张图上以十二月和一月数据的值较高。四五六月份值较低,如果将数据看作是营业额的反应,可以清晰的直观的观察到12月份营业额较高一些。
(本篇的分享到此结束,如果大家关于文章数据分析图的需求可以私信我:qicong0719)