作者:徐瑞龙,量化分析师,R语言中文社区专栏作者
博客专栏:
https://www.cnblogs.com/xuruilong100
本文翻译自《Demo Week: Tidy Time Series Analysis with tibbletime》
原文链接:www.business-science.io/code-tools/2017/10/26/demo_week_tibbletime.html
注意:由于软件包的版本变化,部分代码被修改,文字有删减
tibbletime
的用途
tidy 时间序列分析的未来:基于
tbl
的新类——tbl_time
,为tibble
对象添加时间轴,赋予处理时间的能力。时间序列函数:为
tbl_time
对象专门设计的一系列函数,例如:
filter_time()
:根据日期简便快捷地过滤一个tbl_time
对象。as_period()
:转换时间周期(例如月度变为年度),让用户能将数据聚合到低粒度水平上。time_collapse()
:当使用time_collapse
时,tbl_time
对象中落入相同周期的索引将被修改成相同的日期。rollify()
:修改一个函数,使其能够在特定时间区间上计算一个或一组值。可以用来计算滚动均值,或其他tidyverse
框架下的滚动计算。create_series()
:根据规则时间序列,用简化标记快速初始化一个带有date
列tbl_time
对象。
加载包
tibbletime
目前还在活跃开发阶段,可以用常规方法安装,也可以借助 devtools
从 github 上安装最新开发版。
# Get tibbletime version with latest features devtools::install_github("business-science/tibbletime")
安装完成后,加载下面的包:
tibbletime
:创建带时间轴的tibble
对象,可以使用tbl_time
函数。tidyquant
:加载tidyverse
框架,用tq_get()
获取数据。
# Load libraries library(tibbletime) # Version: 0.1.1, Future of tidy time series analysis library(tidyquant) # Loads tidyverse, tq_get()
数据
用 tq_get()
下载 FANG(脸书、亚马逊、网飞、谷歌)每天的股票价格。
# Stock Prices from Yahoo! Finance FANG_symbols <- c("FB", "AMZN", "NFLX", "GOOG") FANG_tbl_d <- FANG_symbols %>% tq_get( get = "stock.prices", from = "2014-01-01", to = "2016-12-31") FANG_tbl_d <- FANG_tbl_d %>% group_by(symbol) FANG_tbl_d
## # A tibble: 3,024 x 8 ## # Groups: symbol [4] ## symbol date open high low close volume adjusted ## <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 FB 2014-01-02 54.83 55.22 54.19 54.71 43195500 54.71 ## 2 FB 2014-01-03 55.02 55.65 54.53 54.56 38246200 54.56 ## 3 FB 2014-01-06 54.42 57.26 54.05 57.20 68852600 57.20 ## 4 FB 2014-01-07 57.70 58.55 57.22 57.92 77207400 57.92 ## 5 FB 2014-01-08 57.60 58.41 57.23 58.23 56682400 58.23 ## 6 FB 2014-01-09 58.65 58.96 56.65 57.22 92253300 57.22 ## 7 FB 2014-01-10 57.13 58.30 57.06 57.94 42449500 57.94 ## 8 FB 2014-01-13 57.91 58.25 55.38 55.91 63010900 55.91 ## 9 FB 2014-01-14 56.46 57.78 56.10 57.74 37503600 57.74 ## 10 FB 2014-01-15 57.98 58.57 57.27 57.60 33663400 57.60 ## # ... with 3,014 more rows
我们设计了一个函数来按股票代码分块绘图,可以在本文中重复使用。没有必要深究这些代码,只要认识到我们正在创建一个 ggplot2
对象,它通过指定数据框、x、y 和 group(如果存在)等要素来创建根据“symbol”分块的信息图。
# Setup plotting function that can be reused later ggplot_facet_by_symbol <- function(data, mapping) { if (is.null(mapping$group)) { # No groups g <- data %>% ggplot( mapping = mapping) + labs(x = quo_name(mapping$x), y = quo_name(mapping$y)) } else { # Deal with groups g <- data %>% ggplot( mapping = mapping) + labs(x = quo_name(mapping$x), y = quo_name(mapping$y), group = quo_name(mapping$group)) } # Add faceting and theme g <- g + geom_line() + facet_wrap( ~ symbol, ncol = 2, scales = "free_y") + scale_color_tq() + theme_tq() return(g) }
我们可以使用绘图函数 ggplot_facet_by_symbol
快速可视化我们的数据。让我们看一下“除权调整的”股票价格。
# Plot adjusted vs date FANG_tbl_d %>% ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + labs( title = "FANG Stocks: Adjusted Prices 2014 through 2016")
上图所显示就是我们要处理的数据,下面让我们进入 tibbletime
的教程。
教程:tibbletime
本教程将介绍下列函数的用法:
filter_time
:对时间索引的过滤as_period
:改变数据的周期rollify
:将任意函数转换成为滚动函数
初始化一个 tbl_time
对象
在我们使用这些新函数之前,我们需要创建一个 tbl_time
对象。新类的操作几乎与普通的 tibble
对象相同。然而,它会在背后自动跟踪时间信息。
使用 as_tbl_time()
函数初始化对象。指定 index = date
,这告诉 tbl_time
对象要跟踪哪个索引。
# Convert to tbl_time FANG_tbl_time_d <- FANG_tbl_d %>% as_tbl_time(index = date)
我们可以打印 tbl_time
对象。看起来几乎与分组的 tibble
相同。请注意,“Index: date”通知我们“time tibble”已正确初始化。
# Show the tbl_time object we created FANG_tbl_time_d
## # A time tibble: 3,024 x 8 ## # Index: date ## # Groups: symbol [4] ## symbol date open high low close volume adjusted ## <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 FB 2014-01-02 54.83 55.22 54.19 54.71 43195500 54.71 ## 2 FB 2014-01-03 55.02 55.65 54.53 54.56 38246200 54.56 ## 3 FB 2014-01-06 54.42 57.26 54.05 57.20 68852600 57.20 ## 4 FB 2014-01-07 57.70 58.55 57.22 57.92 77207400 57.92 ## 5 FB 2014-01-08 57.60 58.41 57.23 58.23 56682400 58.23 ## 6 FB 2014-01-09 58.65 58.96 56.65 57.22 92253300 57.22 ## 7 FB 2014-01-10 57.13 58.30 57.06 57.94 42449500 57.94 ## 8 FB 2014-01-13 57.91 58.25 55.38 55.91 63010900 55.91 ## 9 FB 2014-01-14 56.46 57.78 56.10 57.74 37503600 57.74 ## 10 FB 2014-01-15 57.98 58.57 57.27 57.60 33663400 57.60 ## # ... with 3,014 more rows
我们可以使用绘图函数 ggplot_facet_by_symbol()
绘制它,我们看到 tbl_time
对象与 tbl
对象的反应相同。
# Plot the tbl_time object FANG_tbl_time_d %>% ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + labs( title = "Working with tbltime: Reacts same as tbl class")
时间序列函数
让我们看看可以用新的 tbl_time
对象做些什么。
filter_time
filter_time()
函数根据按日期简便快捷地过滤 tbl_time
对象,它使用一个函数格式(例如 'date_operator_start' ~ 'date_operator_end'
)。我们使用标准日期格式 YYYY-MM-DD + HH:MM:SS
指定日期运算符,但也有强大的简化标记来更有效地指定日期子集。
假设我们想要过滤出 2014-06-01
和 2014-06-15
之间的所有观察结果。我们可以使用函数标记 filter_time('2014-06-01' ~ '2014-06-15')
来完成。
# filter_time by day FANG_tbl_time_d %>% filter_time('2014-06-01' ~ '2014-06-15') %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + geom_point() + labs( title = "Time Filter: Use functional notation to quickly subset by time", subtitle = "2014-06-01 ~ 2014-06-15")
我们可以按月完成同样的工作。假设我们只想在 2014 年 3 月进行观察。使用简化函数标记 ~ '2014-03'
。
# filter_time by month FANG_tbl_time_d %>% filter_time(~ '2014-03') %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + geom_point() + labs( title = "Time Filter: Use shorthand for even easier subsetting", subtitle = "~ 2014-03")
tbl_time
对象也响应括号符号运算符——[
。在这里,我们提取 2014 年所有日期的数据。
# filter_time by month FANG_tbl_time_d %>% filter_time(~ '2014-03') %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + geom_point() + labs( title = "Time Filter: Use shorthand for even easier subsetting", subtitle = "~ 2014-03")
filter_time()
有许多功能和简化标记,感兴趣的读者可以查看 filter_time vignette 和 filter_time function documentation。
as_period
函数 as_period()
可以改变 tbl_time
对象的周期。与传统方法相比,使用此方法有两个优点:
函数标记非常灵活:
yearly == y == 1 y
函数标记提供了无数周期转换的可能,例如:
15 d
:以 15 天为一周期2 m
:以 2 月为一周期4 m
:以 4 月为一周期6 m
:以半年为一周期
首先,让我们做一个简单的月度周期性变化。
# Convert from daily to monthly periodicity FANG_tbl_time_d %>% as_period(period = "month") %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + labs( title = "Periodicity Change from Daily to Monthly") + geom_point()
让我们提升一个档次。那么每两个月一次呢? 只需使用函数标记 2 m
即可。
# Convert from daily to bi-monthly periodicity FANG_tbl_time_d %>% as_period(period = '2 m') %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + labs( title = "Periodicity Change to Daily to Bi-Monthly", subtitle = "2~m") + geom_point()
让我们继续。那么每半年一次呢? 只需使用 6 m
即可。
# Convert from daily to bi-annually periodicity FANG_tbl_time_d %>% as_period(period = '6 m') %>% # Plotting ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + labs( title = "Periodicity Change to Daily to Bi-Annually", subtitle = "6~m") + geom_point()
函数标记几乎提供了无限可能,感兴趣的话可以查看 vignette on periodicity change with tibbletime。
rollify
rollify()
函数是一个副词(tidyverse
中的一种特殊类型的函数,用于修改另一个函数)。rollify()
的作用是将任何函数转换为自身的滚动版本。
# Rolling 60-day mean roll_mean_60 <- rollify( mean, window = 60) FANG_tbl_time_d %>% mutate( mean_60 = roll_mean_60(adjusted)) %>% select(-c(open:volume)) %>% # Plot ggplot_facet_by_symbol( mapping = aes( x = date, y = adjusted, color = symbol)) + geom_line( aes(y = mean_60), color = palette_light()[[6]]) + labs( title = "Rolling 60-Day Mean with rollify")
我们甚至可以做出更复杂的滚动功能,例如相关性。我们在 rollify()
中使用函数形式 .f = ~fun(.x,.y,...)
。
# Rolling correlation roll_corr_60 <- rollify( ~ cor(.x, .y, use = "pairwise.complete.obs"), window = 60) FANG_tbl_time_d %>% mutate( cor_60 = roll_corr_60( open, close)) %>% select(-c(open:adjusted)) %>% # Plot ggplot_facet_by_symbol( mapping = aes( x = date, y = cor_60, color = symbol)) + labs( title = "Rollify: 60-Day Rolling Correlation Between Open and Close Prices")
我们甚至可以返回多个结果。例如,我们可以创建滚动分位数。
首先,创建一个返回分位数的函数。
# Quantile tbl function quantile_tbl <- function(x) { q <- quantile(x) tibble( quantile_name = names(q), quantile_value = q) } # Test the function quantile_tbl(1:100)
## # A tibble: 5 x 2 ## quantile_name quantile_value ## <chr> <dbl> ## 1 0% 1.00 ## 2 25% 25.75 ## 3 50% 50.50 ## 4 75% 75.25 ## 5 100% 100.00
很好,它可以工作。接下来,使用 rollify
创建滚动版本。我们设置 unlist = FALSE
来返回列表列。
# Rollified quantile function roll_quantile_60 <- rollify( quantile_tbl, window = 60, unlist = FALSE)
接下来,在 mutate()
中应用滚动分位数函数来获得滚动分位数。确保你已经用 select()
、filter()
和 unnest()
删除了不必要的列,过滤了 NA
值,并展开列表列。现在每个日期有五个分位数值。
# Apply rolling quantile FANG_quantile_60 <- FANG_tbl_time_d %>% mutate( rolling_quantile = roll_quantile_60(adjusted)) %>% select(-c(open:adjusted)) %>% filter(!is.na(rolling_quantile)) %>% unnest() FANG_quantile_60
## # A time tibble: 13,940 x 4 ## # Index: date ## # Groups: symbol [4] ## symbol date quantile_name quantile_value ## * <chr> <date> <chr> <dbl> ## 1 FB 2014-03-28 0% 53.5300 ## 2 FB 2014-03-28 25% 57.8750 ## 3 FB 2014-03-28 50% 64.2100 ## 4 FB 2014-03-28 75% 68.6275 ## 5 FB 2014-03-28 100% 72.0300 ## 6 FB 2014-03-31 0% 53.5300 ## 7 FB 2014-03-31 25% 57.9350 ## 8 FB 2014-03-31 50% 64.2100 ## 9 FB 2014-03-31 75% 68.6275 ## 10 FB 2014-03-31 100% 72.0300 ## # ... with 13,930 more rows
最后,画出结果。
FANG_quantile_60 %>% ggplot_facet_by_symbol( mapping = aes( x = date, y = quantile_value, color = symbol, group = quantile_name)) + labs( title = "Rollify: Create Rolling Quantiles")
如果想继续探索 rollify
的用法,可以查看 vignette on rolling functions with rollify。
往期回顾
公众号后台回复关键字即可学习
回复 爬虫 爬虫三大案例实战
回复 Python 1小时破冰入门回复 数据挖掘 R语言入门及数据挖掘
回复 人工智能 三个月入门人工智能
回复 数据分析师 数据分析师成长之路
回复 机器学习 机器学习的商业应用
回复 数据科学 数据科学实战
回复 常用算法 常用数据挖掘算法