Convert a tbl_time object from daily to monthly, from minute data to hourly, and more. This allows the user to easily aggregate data to a less granular level by taking the value from either the beginning or end of the period.

as_period(
  .tbl_time,
  period = "year",
  start_date = NULL,
  side = "start",
  include_endpoints = FALSE,
  ...
)

Arguments

.tbl_time

A tbl_time object.

period

A character specification used for time-based grouping. The general format to use is "frequency period" where frequency is a number like 1 or 2, and period is an interval like weekly or yearly. There must be a space between the two.

Note that you can pass the specification in a flexible way:

  • 1 Year: '1 year' / '1 Y'

This shorthand is available for year, quarter, month, day, hour, minute, second, millisecond and microsecond periodicities.

Additionally, you have the option of passing in a vector of dates to use as custom and more flexible boundaries.

start_date

Optional argument used to specify the start date for the first group. The default is to start at the closest period boundary below the minimum date in the supplied index.

side

Whether to return the date at the beginning or the end of the new period. By default, the "start" of the period. Use "end" to change to the end of the period.

include_endpoints

Whether to include the first or last data point in addition to the transformed data.

...

Not currently used.

Details

This function respects dplyr::group_by() groups.

The side argument is useful when you want to return data at, say, the end of a quarter, or the end of a month.

include_endpoints can be useful when calculating a change over time. In addition to changing to monthly dates, you often need the first data point as a baseline for the first calculation.

Examples


# Basic usage ---------------------------------------------------------------

# FB stock prices
data(FB)
FB <- as_tbl_time(FB, date)

# Aggregate FB to yearly data
as_period(FB, "year")
#> # A time tibble: 4 × 8
#> # Index:         date
#>   symbol date        open  high   low close   volume adjusted
#>   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#> 1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28  
#> 2 FB     2014-01-02  54.8  55.2  54.2  54.7 43195500     54.7
#> 3 FB     2015-01-02  78.6  78.9  77.7  78.4 18177500     78.4
#> 4 FB     2016-01-04 102.  102.   99.8 102.  37912400    102. 

# Aggregate FB to every 2 years
as_period(FB, "2 years")
#> # A time tibble: 3 × 8
#> # Index:         date
#>   symbol date        open  high   low close   volume adjusted
#>   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#> 1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28  
#> 2 FB     2014-01-02  54.8  55.2  54.2  54.7 43195500     54.7
#> 3 FB     2016-01-04 102.  102.   99.8 102.  37912400    102. 

# Aggregate FB to yearly data, but use the last data point available
# in that period
as_period(FB, "year", side = "end")
#> # A time tibble: 4 × 8
#> # Index:         date
#>   symbol date        open  high   low close   volume adjusted
#>   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#> 1 FB     2013-12-31  54.1  54.9  53.9  54.7 43076200     54.7
#> 2 FB     2014-12-31  79.5  79.8  77.9  78.0 19935400     78.0
#> 3 FB     2015-12-31 106   106.  105.  105.  18298700    105. 
#> 4 FB     2016-12-30 117.  117.  115.  115.  18600100    115. 

# Aggregate FB to yearly data, end of period, and include the first
# endpoint
as_period(FB, "year", side = "end", include_endpoints = TRUE)
#> # A time tibble: 5 × 8
#> # Index:         date
#>   symbol date        open  high   low close   volume adjusted
#>   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#> 1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28  
#> 2 FB     2013-12-31  54.1  54.9  53.9  54.7 43076200     54.7
#> 3 FB     2014-12-31  79.5  79.8  77.9  78.0 19935400     78.0
#> 4 FB     2015-12-31 106   106.  105.  105.  18298700    105. 
#> 5 FB     2016-12-30 117.  117.  115.  115.  18600100    115. 

# Aggregate to weekly. Notice that it only uses the earliest day available
# in the data set at that periodicity. It will not set the date of the first
# row to 2013-01-01 because that date did not exist in the original data set.
as_period(FB, "weekly")
#> # A time tibble: 209 × 8
#> # Index:         date
#>    symbol date        open  high   low close   volume adjusted
#>    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#>  1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28  
#>  2 FB     2013-01-07  28.7  29.8  28.6  29.4 83781800     29.4
#>  3 FB     2013-01-14  32.1  32.2  30.6  31.0 98892800     31.0
#>  4 FB     2013-01-22  29.8  30.9  29.7  30.7 55243300     30.7
#>  5 FB     2013-01-28  31.9  32.5  31.8  32.5 59682500     32.5
#>  6 FB     2013-02-04  29.1  29.2  28.0  28.1 92362200     28.1
#>  7 FB     2013-02-11  28.6  28.7  28.0  28.3 37361800     28.3
#>  8 FB     2013-02-19  28.2  29.1  28.1  28.9 49396400     28.9
#>  9 FB     2013-02-25  27.2  27.6  27.2  27.3 34652000     27.3
#> 10 FB     2013-03-04  27.8  28.1  27.4  27.7 32400700     27.7
#> # … with 199 more rows

# FB is daily data, aggregate to minute?
# Not allowed for Date class indices, an error is thrown
# as_period(FB, "minute")

# Grouped usage -------------------------------------------------------------

# FANG contains Facebook, Amazon, Netflix and Google stock prices
data(FANG)
FANG <- as_tbl_time(FANG, date)

FANG <- dplyr::group_by(FANG, symbol)

# Respects groups
as_period(FANG, "year")
#> # A time tibble: 16 × 8
#> # Index:         date
#> # Groups:        symbol [4]
#>    symbol date         open   high    low  close   volume adjusted
#>    <chr>  <date>      <dbl>  <dbl>  <dbl>  <dbl>    <dbl>    <dbl>
#>  1 FB     2013-01-02   27.4   28.2   27.4   28   69846400     28  
#>  2 FB     2014-01-02   54.8   55.2   54.2   54.7 43195500     54.7
#>  3 FB     2015-01-02   78.6   78.9   77.7   78.4 18177500     78.4
#>  4 FB     2016-01-04  102.   102.    99.8  102.  37912400    102. 
#>  5 AMZN   2013-01-02  256.   258.   253.   257.   3271000    257. 
#>  6 AMZN   2014-01-02  399.   399.   394.   398.   2137800    398. 
#>  7 AMZN   2015-01-02  313.   315.   307.   309.   2783200    309. 
#>  8 AMZN   2016-01-04  656.   658.   628.   637.   9314500    637. 
#>  9 NFLX   2013-01-02   95.2   95.8   90.7   92.0 19431300     13.1
#> 10 NFLX   2014-01-02  367.   368.   361.   363.  12325600     51.8
#> 11 NFLX   2015-01-02  344.   352.   341.   349.  13475000     49.8
#> 12 NFLX   2016-01-04  109    110    105.   110.  20794800    110. 
#> 13 GOOG   2013-01-02  719.   727.   717.   723.   5101500    361. 
#> 14 GOOG   2014-01-02 1115.  1118.  1108.  1113.   3656400    556. 
#> 15 GOOG   2015-01-02  529.   531.   524.   525.   1447500    525. 
#> 16 GOOG   2016-01-04  743    744.   731.   742.   3272800    742. 

# Every 6 months, respecting groups
as_period(FANG, "6 months")
#> # A time tibble: 32 × 8
#> # Index:         date
#> # Groups:        symbol [4]
#>    symbol date        open  high   low close   volume adjusted
#>    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
#>  1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28  
#>  2 FB     2013-07-01  25.0  25.1  24.6  24.8 20582200     24.8
#>  3 FB     2014-01-02  54.8  55.2  54.2  54.7 43195500     54.7
#>  4 FB     2014-07-01  67.6  68.4  67.4  68.1 33243000     68.1
#>  5 FB     2015-01-02  78.6  78.9  77.7  78.4 18177500     78.4
#>  6 FB     2015-07-01  86.8  87.9  86.5  86.9 25260000     86.9
#>  7 FB     2016-01-04 102.  102.   99.8 102.  37912400    102. 
#>  8 FB     2016-07-01 114.  115.  114.  114.  14980000    114. 
#>  9 AMZN   2013-01-02 256.  258.  253.  257.   3271000    257. 
#> 10 AMZN   2013-07-01 279   283.  277.  282.   2888200    282. 
#> # … with 22 more rows

# Using start_date ----------------------------------------------------------


#### One method using start_date

# FB stock prices
data(FB)
FB <- as_tbl_time(FB, date)

# The Facebook series starts at 2013-01-02 so the 'every 2 day' counter
# starts at that date as well. Groups become (2013-01-02, 2013-01-03),
# (2013-01-04, 2013-01-05) and so on.
as_period(FB, "2 day")
#> # A time tibble: 619 × 8
#> # Index:         date
#>    symbol date        open  high   low close    volume adjusted
#>    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
#>  1 FB     2013-01-02  27.4  28.2  27.4  28    69846400     28  
#>  2 FB     2013-01-03  27.9  28.5  27.6  27.8  63140600     27.8
#>  3 FB     2013-01-07  28.7  29.8  28.6  29.4  83781800     29.4
#>  4 FB     2013-01-09  29.7  30.6  29.5  30.6 104787700     30.6
#>  5 FB     2013-01-11  31.3  32.0  31.1  31.7  89598000     31.7
#>  6 FB     2013-01-14  32.1  32.2  30.6  31.0  98892800     31.0
#>  7 FB     2013-01-15  30.6  31.7  29.9  30.1 173242600     30.1
#>  8 FB     2013-01-17  30.1  30.4  30.0  30.1  40256700     30.1
#>  9 FB     2013-01-22  29.8  30.9  29.7  30.7  55243300     30.7
#> 10 FB     2013-01-23  31.1  31.5  30.8  30.8  48899800     30.8
#> # … with 609 more rows

# Specifying the `start_date = "2013-01-01"` might be preferable.
# Groups become (2013-01-01, 2013-01-02), (2013-01-03, 2013-01-04) and so on.
as_period(FB, "2 day", start_date = "2013-01-01")
#> # A time tibble: 619 × 8
#> # Index:         date
#>    symbol date        open  high   low close    volume adjusted
#>    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
#>  1 FB     2013-01-02  27.4  28.2  27.4  28    69846400     28  
#>  2 FB     2013-01-03  27.9  28.5  27.6  27.8  63140600     27.8
#>  3 FB     2013-01-07  28.7  29.8  28.6  29.4  83781800     29.4
#>  4 FB     2013-01-09  29.7  30.6  29.5  30.6 104787700     30.6
#>  5 FB     2013-01-11  31.3  32.0  31.1  31.7  89598000     31.7
#>  6 FB     2013-01-14  32.1  32.2  30.6  31.0  98892800     31.0
#>  7 FB     2013-01-15  30.6  31.7  29.9  30.1 173242600     30.1
#>  8 FB     2013-01-17  30.1  30.4  30.0  30.1  40256700     30.1
#>  9 FB     2013-01-22  29.8  30.9  29.7  30.7  55243300     30.7
#> 10 FB     2013-01-23  31.1  31.5  30.8  30.8  48899800     30.8
#> # … with 609 more rows

#### Equivalent method using an index vector

# FB stock prices
data(FB)
FB <- as_tbl_time(FB, date)

custom_period <- create_series(
  time_formula = dplyr::first(FB$date) - 1 ~ dplyr::last(FB$date),
  period       = "2 day",
  class        = "Date",
  as_vector    = TRUE)

FB %>%
  as_tbl_time(date) %>%
  as_period(period = custom_period)
#> # A time tibble: 619 × 8
#> # Index:         date
#>    symbol date        open  high   low close    volume adjusted
#>    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
#>  1 FB     2013-01-02  27.4  28.2  27.4  28    69846400     28  
#>  2 FB     2013-01-03  27.9  28.5  27.6  27.8  63140600     27.8
#>  3 FB     2013-01-07  28.7  29.8  28.6  29.4  83781800     29.4
#>  4 FB     2013-01-09  29.7  30.6  29.5  30.6 104787700     30.6
#>  5 FB     2013-01-11  31.3  32.0  31.1  31.7  89598000     31.7
#>  6 FB     2013-01-14  32.1  32.2  30.6  31.0  98892800     31.0
#>  7 FB     2013-01-15  30.6  31.7  29.9  30.1 173242600     30.1
#>  8 FB     2013-01-17  30.1  30.4  30.0  30.1  40256700     30.1
#>  9 FB     2013-01-22  29.8  30.9  29.7  30.7  55243300     30.7
#> 10 FB     2013-01-23  31.1  31.5  30.8  30.8  48899800     30.8
#> # … with 609 more rows

# Manually calculating returns at different periods -------------------------

data(FB)

# Annual Returns
# Convert to end of year periodicity, but include the endpoints to use as
# a reference for the first return calculation. Then calculate returns.
FB %>%
  as_tbl_time(date) %>%
  as_period("1 y", side = "end", include_endpoints = TRUE) %>%
  dplyr::mutate(yearly_return = adjusted / dplyr::lag(adjusted) - 1)
#> # A time tibble: 5 × 9
#> # Index:         date
#>   symbol date        open  high   low close   volume adjusted yearly_return
#>   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>         <dbl>
#> 1 FB     2013-01-02  27.4  28.2  27.4  28   69846400     28         NA     
#> 2 FB     2013-12-31  54.1  54.9  53.9  54.7 43076200     54.7        0.952 
#> 3 FB     2014-12-31  79.5  79.8  77.9  78.0 19935400     78.0        0.428 
#> 4 FB     2015-12-31 106   106.  105.  105.  18298700    105.         0.341 
#> 5 FB     2016-12-30 117.  117.  115.  115.  18600100    115.         0.0993