zoukankan      html  css  js  c++  java
  • 时间序列分析工具箱——tibbletime

    翻译自《Demo Week: Tidy Time Series Analysis with tibbletime》

    原文链接:www.business-science.io/code-tools/2017/10/26/demo_week_tibbletime.html

    注意:由于软件包的版本变化,部分代码被修改,文字有删减

    时间序列分析工具箱——tibbletime

    tibbletime 的用途

    1. tidy 时间序列分析的未来:基于 tbl 的新类——tbl_time,为 tibble 对象添加时间轴,赋予处理时间的能力。
    2. 时间序列函数:为 tbl_time 对象专门设计的一系列函数,例如:
      • filter_time():根据日期简便快捷地过滤一个 tbl_time 对象。
      • as_period():转换时间周期(例如月度变为年度),让用户能将数据聚合到低粒度水平上。
      • time_collapse():当使用 time_collapse 时,tbl_time 对象中落入相同周期的索引将被修改成相同的日期。
      • rollify():修改一个函数,使其能够在特定时间区间上计算一个或一组值。可以用来计算滚动均值,或其他 tidyverse 框架下的滚动计算。
      • create_series():根据规则时间序列,用简化标记快速初始化一个带有 datetbl_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-012014-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 年所有日期的数据。

    # time filter bracket [] notation
    FANG_tbl_time_d[~ '2014'] %>%
        # Plotting
        ggplot_facet_by_symbol(
            mapping = aes(
                x = date, y = adjusted, color = symbol)) +
        labs(
            title = "Time Filter: Bracket Notation Works Too",
            subtitle = "FANG_tbl_time_d[~ 2014]")
    

    filter_time() 有许多功能和简化标记,感兴趣的读者可以查看 filter_time vignettefilter_time function documentation

    as_period

    函数 as_period() 可以改变 tbl_time 对象的周期。与传统方法相比,使用此方法有两个优点:

    1. 函数标记非常灵活:yearly == y == 1 y
    2. 函数标记提供了无数周期转换的可能,例如:
      • 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

  • 相关阅读:
    U盘支持启动windows和Linux
    emacs安装
    npm 安装指定的第三方包
    npm安装第三方包
    npm 安装淘宝镜像
    ssm 环境搭建
    gitBook安装简介
    git 博客搭建
    git 多人开发
    git ssh提交
  • 原文地址:https://www.cnblogs.com/xuruilong100/p/9575824.html
Copyright © 2011-2022 走看看