Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
^.*\.Rproj$
^\.Rproj\.user$
^\.github$
^\.vscode$
43 changes: 43 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## Description

<!-- Briefly describe the changes in this PR -->

## Type of Change

<!-- Mark the relevant option with an "x" -->

- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Documentation update
- [ ] Code refactoring (no functional changes)

## Related Issues

<!-- Link any related issues here using "Fixes #123" or "Closes #123" -->

## Checklist

<!-- Mark completed items with an "x" -->

### Code Quality
- [ ] My code follows the tidyverse style guide
- [ ] I have commented my code where necessary
- [ ] I have made corresponding changes to the documentation

### Documentation
- [ ] I have added/updated roxygen2 documentation for any new/changed functions
- [ ] I have added `@examples` for new exported functions
- [ ] I have updated the README if needed
- [ ] I have added a bullet to NEWS.md describing the changes

### Testing
- [ ] I have added tests that prove my fix/feature works
- [ ] New and existing tests pass locally with my changes

### R CMD check
- [ ] `devtools::check()` passes with 0 errors, 0 warnings, and 0 notes

## Additional Notes

<!-- Any additional information that reviewers should know -->
1 change: 1 addition & 0 deletions .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-r@v2
- uses: r-lib/actions/setup-pandoc@v2
- name: Install dependencies
run: |
install.packages(c("remotes", "rcmdcheck"))
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/pkgdown.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
release:
types: [published]
workflow_dispatch:

name: pkgdown

jobs:
pkgdown:
runs-on: ubuntu-latest
# Only restrict concurrency for non-PR jobs
concurrency:
group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
steps:
- uses: actions/checkout@v3

- uses: r-lib/actions/setup-pandoc@v2

- uses: r-lib/actions/setup-r@v2
with:
use-public-rspm: true

- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::pkgdown, local::.
needs: website

- name: Build site
run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
shell: Rscript {0}

- name: Deploy to GitHub pages 🚀
if: github.event_name != 'pull_request'
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
clean: false
branch: gh-pages
folder: docs
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ vignettes/*.pdf
# Shiny token, see https://shiny.rstudio.com/articles/shinyapps.html
rsconnect/
.Rproj.user
.vscode/settings.json
46 changes: 34 additions & 12 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
Package: tstoolbox
Type: Package
Title: Useful tools for time series analysis
Version: 0.1.0
Author: Martin Chan
Maintainer: Martin Chan <martinchan53@gmail.com>
Description: Useful tools for time series analysis.
License: What license is it under?
Encoding: UTF-8
LazyData: true
Imports: base, dplyr, ggplot2, ggthemes, stats, rlang, lubridate, Rfast, magrittr
RoxygenNote: 7.1.0
Package: tstoolbox
Type: Package
Title: Tools for Time Series Analysis and Diagnostics
Version: 0.1.0
Authors@R:
person("Martin", "Chan", , "martinchan53@gmail.com", role = c("aut", "cre"))
Description: Provides utility functions for time series analysis including
direction analysis (measuring co-movement between series), cross-correlation
analysis with visualization, adstock transformation and reversal, and various
helper functions for time series diagnostics and exploration.
License: MIT + file LICENSE
Encoding: UTF-8
URL: https://github.com/martinctc/tstoolbox
BugReports: https://github.com/martinctc/tstoolbox/issues
Imports:
dplyr,
ggplot2,
ggthemes,
glue,
lubridate,
magrittr,
Rfast,
rlang,
scales,
stats,
tibble,
tidyr
Suggests:
knitr,
rmarkdown,
testthat (>= 3.0.0)
Config/testthat/edition: 3
VignetteBuilder: knitr
RoxygenNote: 7.3.2
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2026
COPYRIGHT HOLDER: Martin Chan
42 changes: 42 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
# Generated by roxygen2: do not edit by hand

S3method(plot,direction_leadlag)
S3method(print,asymmetric_direction)
S3method(print,concordance)
S3method(print,direction_leadlag)
S3method(print,direction_test)
export("%>%")
export(adstock)
export(analyse_direction)
export(asymmetric_direction)
export(concordance)
export(direction)
export(direction_leadlag)
export(direction_test)
export(pc_change)
export(plot_rolling_direction)
export(plot_xcf)
export(return_k_date)
export(reverse_adstock)
export(rolling_direction)
export(stend_line)
export(sumlagdiff)
export(ts_summarise)
export(xcf)
import(lubridate)
importFrom(Rfast,nth)
importFrom(dplyr,group_by)
importFrom(dplyr,lag)
importFrom(dplyr,mutate)
importFrom(dplyr,mutate_at)
importFrom(dplyr,summarise)
importFrom(dplyr,summarise_at)
importFrom(dplyr,vars)
importFrom(ggplot2,aes)
importFrom(ggplot2,annotate)
importFrom(ggplot2,element_text)
importFrom(ggplot2,geom_bar)
importFrom(ggplot2,geom_col)
importFrom(ggplot2,geom_hline)
importFrom(ggplot2,geom_line)
importFrom(ggplot2,geom_ribbon)
importFrom(ggplot2,geom_vline)
importFrom(ggplot2,ggplot)
importFrom(ggplot2,ggtitle)
importFrom(ggplot2,labs)
importFrom(ggplot2,scale_fill_gradient2)
importFrom(ggplot2,scale_fill_manual)
importFrom(ggplot2,scale_y_continuous)
importFrom(ggplot2,theme)
importFrom(ggplot2,theme_minimal)
importFrom(ggplot2,ylab)
importFrom(lubridate,floor_date)
importFrom(magrittr,"%>%")
importFrom(rlang,`:=`)
importFrom(rlang,enquo)
importFrom(rlang,sym)
importFrom(stats,ccf)
importFrom(tibble,as_tibble)
30 changes: 30 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# tstoolbox 0.1.0

* Initial CRAN submission

## Co-movement Analysis (New)
* `rolling_direction()` - Calculate co-movement proportion over rolling windows
* `direction_test()` - Statistical significance testing for co-movement (binomial, permutation, bootstrap)
* `plot_rolling_direction()` - Visualize rolling co-movement over time
* `direction_leadlag()` - Detect lead-lag relationships in directional co-movement
* `concordance()` - Harding-Pagan concordance index for formal co-movement measurement
* `asymmetric_direction()` - Analyse if co-movement differs during upturns vs downturns

## Direction Analysis
* `analyse_direction()` - Analyse co-movement between two numeric variables
* `direction()` - Return direction of change relative to previous value

## Cross-correlation
* `xcf()` - Create cross-correlation table
* `plot_xcf()` - Create pretty cross-correlation plot

## Adstock Transformations
* `adstock()` - Calculate adstock (decay) transformation
* `reverse_adstock()` - Convert adstocked values back to original

## Time Series Utilities
* `ts_summarise()` - Group-summarise a time series by time interval
* `return_k_date()` - Return k-th most recent or oldest date from a vector
* `pc_change()` - Calculate percentage change relative to lag k
* `stend_line()` - Generate linear vector between start and end values
* `sumlagdiff()` - Sum of absolute differences (fluctuation score)
13 changes: 12 additions & 1 deletion R/adstock.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
#' Calculate adstock (decay)
#'
#' Applies an adstock (decay) transformation to a numeric vector using
#' a recursive filter.
#'
#' @param x Numeric vector to be passed through.
#' @param rate Decay rate to be applied to `x`
#' @param rate Decay rate to be applied to `x`. Must be between 0 and 1.
#'
#' @return A numeric vector of the same length as `x` with the adstock
#' transformation applied.
#'
#' @examples
#' # Apply 20% decay rate
#' adstock(c(100, 200, 300, 150, 200), rate = 0.2)
#'
#' @export
adstock <- function(x, rate = 0){
x %>%
Expand Down
33 changes: 26 additions & 7 deletions R/analyse_direction.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
#' Analyse co-movement between two numeric variables.
#' Analyse co-movement between two numeric variables
#'
#' This returns the total number and proportion of pairwise co-movement in two time series variables.
#' An explanatory note is printed as a message in the console.
#' This returns the total number and proportion of pairwise co-movement in two
#' time series variables. An explanatory note is printed as a message in the console.
#'
#'@export
#' @param x A data frame containing the time series variables.
#' @param var1 Unquoted name of the first numeric variable.
#' @param var2 Unquoted name of the second numeric variable.
#'
#' @return A tibble with three columns: `n` (number of matching directions),
#' `base` (total number of observations), and `prop` (proportion of matches).
#'
#' @importFrom rlang enquo `:=`
#' @importFrom dplyr vars mutate_at mutate summarise
#' @importFrom glue glue
#' @importFrom tidyr drop_na
#'
#' @examples
#' df <- data.frame(
#' series1 = c(1, 3, 2, 5, 4),
#' series2 = c(2, 4, 3, 6, 5)
#' )
#' analyse_direction(df, series1, series2)
#'
#' @export
analyse_direction <- function(x,var1,var2){
var1 <- enquo(var1)
var2 <- enquo(var2)
var1 <- rlang::enquo(var1)
var2 <- rlang::enquo(var2)

x %>%
dplyr::mutate_at(vars(!!var1,!!var2),~direction(.)) %>%
dplyr::mutate_at(dplyr::vars(!!var1,!!var2),~direction(.)) %>%
tidyr::drop_na() %>%
dplyr::mutate(match:=(!!var1)==(!!var2)) %>%
dplyr::summarise(n=sum(match),
Expand Down
Loading
Loading