{"id":21182759,"url":"https://github.com/jszitas/soothsayer","last_synced_at":"2025-10-17T08:20:17.177Z","repository":{"id":62828201,"uuid":"420237776","full_name":"JSzitas/soothsayer","owner":"JSzitas","description":"Automatic Time Series Forecasting and Ensembling via Meta-learning","archived":false,"fork":false,"pushed_at":"2023-04-11T16:41:42.000Z","size":51320,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-21T14:45:42.570Z","etag":null,"topics":["forecasting","forecasting-models","machine-learning","meta-learning","model-selection","r","time-series"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JSzitas.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-10-22T20:48:01.000Z","updated_at":"2023-04-11T18:14:34.000Z","dependencies_parsed_at":"2023-09-22T03:04:30.203Z","dependency_job_id":null,"html_url":"https://github.com/JSzitas/soothsayer","commit_stats":{"total_commits":114,"total_committers":1,"mean_commits":114.0,"dds":0.0,"last_synced_commit":"98f46bded18e401650940c763e6e47536e66b49f"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSzitas%2Fsoothsayer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSzitas%2Fsoothsayer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSzitas%2Fsoothsayer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JSzitas%2Fsoothsayer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JSzitas","download_url":"https://codeload.github.com/JSzitas/soothsayer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243652707,"owners_count":20325611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["forecasting","forecasting-models","machine-learning","meta-learning","model-selection","r","time-series"],"created_at":"2024-11-20T17:57:53.072Z","updated_at":"2025-10-17T08:20:12.130Z","avatar_url":"https://github.com/JSzitas.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\nalways_allow_html: true\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n```\n\n# soothsayer\n\n\u003c!-- badges: start --\u003e\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)\n[![R-CMD-check](https://github.com/JSzitas/soothsayer/workflows/R-CMD-check/badge.svg)](https://github.com/JSzitas/soothsayer/actions)\n[![Codecov test coverage](https://codecov.io/gh/JSzitas/soothsayer/branch/main/graph/badge.svg)](https://codecov.io/gh/JSzitas/soothsayer?branch=main)\n[![CRAN status](https://www.r-pkg.org/badges/version/soothsayer)](https://CRAN.R-project.org/package=soothsayer)\n\u003c!-- badges: end --\u003e\n\n\n**soothsayer** provides tools for automation of time series model selection.\n\nThis is achieved by fitting your own version of Feature-based Forecast Model Selection (FFORMS), as described in . \nThe package does this in a way that tries to leverage the **tidy** framework.\n\n## Workflow \n\n![Intended workflow for soothsayer](workflow.png)\n\n* compute time series features (e.g. Box-Pierce statistic, time series entropy, ...)\n* run a **set of rules**, or an **oracle** model for fitting models \n* generate forecast combinations \n\nThe forecast rules are implemented directly in the model, i.e. the following is perfectly valid and runnable code: \n\n```{r}\nlibrary(fabletools)\nlibrary(soothsayer)\n\nex_data \u003c- tsibbledata::aus_livestock %\u003e%\n  as.data.frame() %\u003e%\n  dplyr::group_by(Month, State) %\u003e%\n  dplyr::summarise(count = sum(Count)) %\u003e%\n  dplyr::ungroup() %\u003e%\n  tsibble::as_tsibble(index = \"Month\", key= \"State\")\n\ntrain \u003c- dplyr::filter(ex_data, Month \u003c= tsibble::yearmonth(\"2017 Jan\"))\ntest \u003c- dplyr::filter( ex_data, Month \u003e tsibble::yearmonth(\"2017 Jan\") )\n\nmdls \u003c- fabletools::model(\n  train,\n  ar = fable::ARIMA( count ),\n  arima = fable::ARIMA(count),\n  soothsayer = soothsayer(count ~ \n                            # only fit arima if there is over 12 observations\n                            rules(arima ~ .length \u003e 12,\n                                  # always fit an AR model \n                                  ar ~ TRUE,\n                                  # only fit ets if length is over 15\n                                  ets ~ .length \u003e 15))\n)\n```\n\nNote that this works seamlessly with fitting any model in the **fable** package \nand models which work in the **fabletools** framework. This includes, among others \n[fable.tbats](https://github.com/JSzitas/fable.tbats), the wrapper for the TBATS\nmodel. \n\nThis then works just like any other model in **fable**, and generating forecasts\nis seamless: \n\n```{r}\nforecast(mdls, test) %\u003e% \n  # only a subset of forecasts plotted for visibility\n  dplyr::filter(State == \"Western Australia\") %\u003e% \n  ggplot2::autoplot(test)\n```\n\n# Combinations\n\n**soothsayer** also supports forecast combinations. Following the example above, \nby default, soothsayer creates an equally weighed combination of all models\nwhich are matched:\n\n```{r}\n# this is identical to the above \nmdls \u003c- fabletools::model(\n  train,\n  ar = fable::ARIMA( count ),\n  arima = fable::ARIMA(count),\n  soothsayer = soothsayer(count ~ \n                            rules(arima ~ .length \u003e 12,\n                                  ar ~ TRUE,\n                                  ets ~ .length \u003e 15) + \n                            # note the explicit combiner, though\n                            combiner(combiner_equal))\n)\n```\n\nHowever, multiple combiners are implemented within the package - \na good example being the **'greedy stacking'** one (See [1]): \n\n```{r}\n# this is identical to the above \nmdls \u003c- fabletools::model(\n  train,\n  ar = fable::ARIMA( count ),\n  arima = fable::ARIMA(count),\n  soothsayer = soothsayer(count ~ \n                            rules(arima ~ .length \u003e 12,\n                                  ar ~ TRUE,\n                                  ets ~ .length \u003e 15) + \n                            # note the explicit combiner, though\n                            combiner(combiner_greedy_stacking))\n)\n```\n\nThese allow you to implement specific types of weighed combinations, including \npreset weights (**combiner_custom**). Further, note that the combiner argument \ntakes a function - any function with the following signature:\n\n```{r}\nnew_combiner \u003c- function(.models, ...) {\n  # your code goes here\n}\n```\n\nthis is expected to return a vector of weights in the same order as **.models**,\nwhere **.models** is the fitted model *mable** object.  \n\n# Adding soothsayers to existing mables\n\nTODO: Document \n\n# References\n\n+ [1] Kurz, Maier \u0026 Rink; 'A greedy stacking algorithm for model ensembling and domain weighting',\nBMC Research Notes volume 13, Article number: 70 (2020)\n(See full text at https://bmcresnotes.biomedcentral.com/articles/10.1186/s13104-020-4931-7)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjszitas%2Fsoothsayer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjszitas%2Fsoothsayer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjszitas%2Fsoothsayer/lists"}