目录
- 0.问题导入
- 1.示例数据
- 2.数据导入
- 3.日数据转月均数据(文末附转换函数daily2monthly)
- 4.日序列趋势提取(函数附于文末 daily_trend)
- 5.本文小结
- 6.本文所使用的软件包,没有需要安装
- 7.daily2monthly函数
- 8.daily_trend函数
0. 问题导入
我们有时候会拿到一些日数据,比如日气温数据(中国气象信息网),股票价格数据等,但是日间变化太小,数据点离得太近,数据序列长度短还好说,但是当它变长了的时候,往往是这个鬼样子的(图1)。
就好像一团乱麻,完全无从下手,有没有!
那今天本篇就跟大家说说如何从日数据中挖出点东西~
1. 示例数据
今天我们用1960~2012年单点日气温数据与京东的近五年的日股价数据来进行示例说明。
点我下载:日气温数据
点我下载:京东近5年股价数据
2. 数据导入
导入气温数据
input_tas = 'station.csv'
tas_daily = read.csv(input_tas,header = T)
date_tas = seq(as.Date('1960-08-01'),
as.Date('2012-07-31'),'day')
tas_df = data.frame(
date= date_tas,
tas = tas_daily[,4]/10
)
导入京东闭市股价数据
input_jd = 'JD.csv'
jd_daily = read.csv(input_jd, header =T)
jd_daily$Date = as.Date(jd_daily$Date)
jd_df = data.frame(
date = jd_daily$Date,
close_price = jd_daily$Close
)
日数据可视化(图2)
pl_df_daily_m1 = melt(tas_df,'date')
pl_df_daily_m2 = melt(jd_df,'date')
pl_df_daily_m1$type = "(a) TAS_MON (\u00B0C)"
pl_df_daily_m2$type = "(b) JD Close Price (yuan)"
pl_df_daily_m = rbind(pl_df_daily_m1,pl_df_daily_m2)
p1 = ggplot()+
geom_line(data = pl_df_daily_m,aes(x= date,y = value,color = variable),
linetype = 1,size = 1)+
theme(panel.background = element_rect(fill = 'transparent',color = 'black'),
axis.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
axis.title = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
legend.position=c('bottom'),
legend.direction = c('horizontal'),
strip.background = element_rect(fill = 'transparent'),
strip.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5))+
facet_wrap(~ type, nrow = 2,scales = 'free')+
xlab('Time (month)')+
ylab('Index')
png('p1.png',
height = 20,
width = 20,
units = 'cm',
res = 800)
print(p1)
dev.off()
如果说长序列日数据信息量过于密集,那么将其转化为月均序列便是一种减少信息量的方法之一。但是如何做呢?请看第三节~
3. 日数据转月均数据(文末附转换函数daily2monthly)
特别说明下,文末所附转换函数需要在Rstudio 中source后才能使用
source('~/Documents/JianShu_Project/20191209/daily2monthly.R')
daily2monthly(index, start_date = '1960-08-01',end_date = '2012-07-01')函数:
输入项:
- index,日时间序列
- start_date,日时间序列的起始日期
- end_date, 日时间序列的终止日期
日数据转月均数据
source('~/Documents/JianShu_Project/20191209/daily2monthly.R')
tas_month = daily2monthly(tas_df)
jd_month = daily2monthly(jd_df)
月数据可视化(图3)
date_tas_month = seq(as.Date('1960-08-01'),
as.Date('2012-07-31'),'month')
date_jd_month = seq(as.Date('2014-12-01'),
as.Date('2019-12-01'),'month')
pl_df1 = data.frame(date = date_tas_month, TAS_MON = tas_month$tas)
pl_df2 = data.frame(date = date_jd_month, JD_P = jd_month$close_price)
pl_df1_m = melt(pl_df1,'date')
pl_df2_m = melt(pl_df2,'date')
pl_df1_m$type = "(a) TAS_MON (\u00B0C)"
pl_df2_m$type = "(b) JD Close Price (yuan)"
pl_df_m = rbind(pl_df1_m,pl_df2_m)
p2 = ggplot()+
geom_line(data = pl_df_m,aes(x= date,y = value,color = variable),
linetype = 1,size = 1)+
theme(panel.background = element_rect(fill = 'transparent',color = 'black'),
axis.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
axis.title = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
legend.position=c('bottom'),
legend.direction = c('horizontal'),
strip.background = element_rect(fill = 'transparent'),
strip.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5))+
facet_wrap(~ type, nrow = 2,scales = 'free')+
xlab('Time (month)')+
ylab('Index')
png('p2.png',
height = 20,
width = 20,
units = 'cm',
res = 800)
print(p2)
dev.off()
通过对比图2与图3,我们可以发现通过将日数据序列转化月数据序列后,气温及股价时间序列明显变得更加平滑。但是对比气温与股价的月数据,我们可以发现将日数据转化为月数据这种方式对于长时间序列的日数据显然无法起到明显的信息提取的作用。
那么,当我们在处理长时间序列数据的时候我们应该如何处理呢,请阅读第4节~
4. 日序列趋势提取(函数附于文末 daily_trend)
daily_trend(df, start_year = 1960)
- df: 日序列矩阵,共两列,第一列为date,第二列为指标列,如:
- start_year, 数据序列起始年份,numeric
head(tas_df)
date tas
1: 1960-08-01 15.7
2: 1960-08-02 17.7
3: 1960-08-03 16.2
4: 1960-08-04 16.1
5: 1960-08-05 15.6
6: 1960-08-06 17.0
日数据序列趋势项提取
source('~/Documents/JianShu_Project/20191209/daily_trend.R')
tas_trend = daily_trend(tas_df,start_year = 1960)
jd_trend = daily_trend(jd_df,start_year = 2014)
日数据序列趋势项可视化
pl_df_trend1 = melt(tas_trend,'date')
pl_df_trend2 = melt(jd_trend,'date')
pl_df_trend1$type = "(a) TAS_MON (\u00B0C)"
pl_df_trend2$type = "(b) JD Close Price (yuan)"
pl_df_trend = rbind(pl_df_trend1,pl_df_trend2)
p3 = ggplot()+
geom_line(data = pl_df_trend,aes(x= date,y = value,color = variable),
linetype = 1,size = 1)+
theme(panel.background = element_rect(fill = 'transparent',color = 'black'),
axis.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
axis.title = element_text(face='bold',colour='black',size=fontsize,hjust=.5),
legend.position=c('bottom'),
legend.direction = c('horizontal'),
strip.background = element_rect(fill = 'transparent'),
strip.text = element_text(face='bold',colour='black',size=fontsize,hjust=.5))+
facet_wrap(~ type, nrow = 2,scales = 'free')+
xlab('Time (month)')+
ylab('Index')
png('p3.png',
height = 20,
width = 20,
units = 'cm',
res = 800)
print(p3)
dev.off()
通过对比图3-4,我们可以发现,长时间序列的日数据通过趋势项提取后,可显著体现出其在时间尺度的变化规律。
5. 总结
本篇主要解决了三个问题:
- 如何将日时间序列数据转化为月尺度数据?
- 如何从日时间序列数据中提取趋势项?
- 如何从日时间序列数据中挖掘规律?
6. 本文所使用的软件包没有需要安装
library(stats)
library(ggplot2)
library(data.table)
7. daily2monthly函数
daily2monthly <-function(
daily_data
){
library(data.table)
df = daily_data
df_mon_mean = setDT(df)[,lapply(.SD, mean), by = .(year(date),month(date))]
return(df_mon_mean)
}
8. daily_trend函数
daily_trend<-function(
df,
start_year= 1960
){
ts_df = ts(df[,2],start = c(start_year,as.numeric(format(df$date[1],"%j"))),frequency = 365)
ts_trend = decompose(ts_df)$trend
ts_trend_df = data.frame(date = df$date,trend = ts_trend)
return(ts_trend_df)
}