Full Code of facebook/prophet for AI

main 181f4479878b cached
277 files
21.1 MB
2.4M tokens
233 symbols
1 requests
Download .txt
Showing preview only (9,561K chars total). Download the full file or copy to clipboard to get everything.
Repository: facebook/prophet
Branch: main
Commit: 181f4479878b
Files: 277
Total size: 21.1 MB

Directory structure:
gitextract_w0ay2q3a/

├── .deepsource.toml
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build-and-test.yml
│       └── wheel.yml
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── Makefile
├── R/
│   ├── .Rbuildignore
│   ├── .gitignore
│   ├── DESCRIPTION
│   ├── LICENSE
│   ├── NAMESPACE
│   ├── R/
│   │   ├── data.R
│   │   ├── diagnostics.R
│   │   ├── make_holidays.R
│   │   ├── plot.R
│   │   ├── prophet.R
│   │   ├── stan_backends.R
│   │   ├── stanmodels.R
│   │   ├── sysdata.rda
│   │   ├── utilities.R
│   │   └── zzz.R
│   ├── configure
│   ├── configure.win
│   ├── data-raw/
│   │   ├── generated_holidays.R
│   │   └── generated_holidays.csv
│   ├── inst/
│   │   ├── include/
│   │   │   └── stan_meta_header.hpp
│   │   └── stan/
│   │       └── prophet.stan
│   ├── man/
│   │   ├── add_changepoints_to_plot.Rd
│   │   ├── add_country_holidays.Rd
│   │   ├── add_group_component.Rd
│   │   ├── add_regressor.Rd
│   │   ├── add_seasonality.Rd
│   │   ├── check_cmdstanr.Rd
│   │   ├── construct_holiday_dataframe.Rd
│   │   ├── coverage.Rd
│   │   ├── cross_validation.Rd
│   │   ├── df_for_plotting.Rd
│   │   ├── dot-fit.Rd
│   │   ├── dot-load_model.Rd
│   │   ├── dot-sampling.Rd
│   │   ├── dot-stan_args.Rd
│   │   ├── dyplot.prophet.Rd
│   │   ├── fit.prophet.Rd
│   │   ├── flat_growth_init.Rd
│   │   ├── flat_trend.Rd
│   │   ├── fourier_series.Rd
│   │   ├── generate_cutoffs.Rd
│   │   ├── generated_holidays.Rd
│   │   ├── get_holiday_names.Rd
│   │   ├── get_stan_backend.Rd
│   │   ├── initialize_scales_fn.Rd
│   │   ├── linear_growth_init.Rd
│   │   ├── logistic_growth_init.Rd
│   │   ├── mae.Rd
│   │   ├── make_all_seasonality_features.Rd
│   │   ├── make_future_dataframe.Rd
│   │   ├── make_holiday_features.Rd
│   │   ├── make_holidays_df.Rd
│   │   ├── make_seasonality_features.Rd
│   │   ├── mape.Rd
│   │   ├── mdape.Rd
│   │   ├── mse.Rd
│   │   ├── parse_seasonality_args.Rd
│   │   ├── performance_metrics.Rd
│   │   ├── piecewise_linear.Rd
│   │   ├── piecewise_logistic.Rd
│   │   ├── plot.prophet.Rd
│   │   ├── plot_cross_validation_metric.Rd
│   │   ├── plot_forecast_component.Rd
│   │   ├── plot_seasonality.Rd
│   │   ├── plot_weekly.Rd
│   │   ├── plot_yearly.Rd
│   │   ├── predict.prophet.Rd
│   │   ├── predict_seasonal_components.Rd
│   │   ├── predict_trend.Rd
│   │   ├── predict_uncertainty.Rd
│   │   ├── predictive_samples.Rd
│   │   ├── prophet.Rd
│   │   ├── prophet_copy.Rd
│   │   ├── prophet_plot_components.Rd
│   │   ├── regressor_coefficients.Rd
│   │   ├── regressor_column_matrix.Rd
│   │   ├── rmse.Rd
│   │   ├── rolling_mean_by_h.Rd
│   │   ├── rolling_median_by_h.Rd
│   │   ├── sample_model.Rd
│   │   ├── sample_posterior_predictive.Rd
│   │   ├── sample_predictive_trend.Rd
│   │   ├── seasonality_plot_df.Rd
│   │   ├── set_auto_seasonalities.Rd
│   │   ├── set_changepoints.Rd
│   │   ├── set_date.Rd
│   │   ├── setup_dataframe.Rd
│   │   ├── single_cutoff_forecast.Rd
│   │   ├── smape.Rd
│   │   ├── time_diff.Rd
│   │   ├── validate_column_name.Rd
│   │   └── validate_inputs.Rd
│   ├── prophet.Rproj
│   ├── src/
│   │   ├── Makevars
│   │   └── Makevars.win
│   ├── tests/
│   │   ├── testthat/
│   │   │   ├── data.csv
│   │   │   ├── data2.csv
│   │   │   ├── test_diagnostics.R
│   │   │   ├── test_prophet.R
│   │   │   ├── test_stan_functions.R
│   │   │   └── test_utilities.R
│   │   └── testthat.R
│   └── vignettes/
│       └── quick_start.Rmd
├── README.md
├── docker-compose.yml
├── docs/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── Gemfile
│   ├── LICENSE
│   ├── Makefile
│   ├── README.md
│   ├── _config.yml
│   ├── _data/
│   │   ├── authors.yml
│   │   ├── features.yml
│   │   ├── nav.yml
│   │   ├── nav_docs.yml
│   │   ├── powered_by.yml
│   │   ├── powered_by_highlight.yml
│   │   └── promo.yml
│   ├── _docs/
│   │   ├── additional_topics.md
│   │   ├── contributing.md
│   │   ├── diagnostics.md
│   │   ├── handling_shocks.md
│   │   ├── holiday_effects.md
│   │   ├── installation.md
│   │   ├── multiplicative_seasonality.md
│   │   ├── non-daily_data.md
│   │   ├── outliers.md
│   │   ├── quick_start.md
│   │   ├── saturating_forecasts.md
│   │   ├── seasonality,_holiday_effects,_and_regressors.md
│   │   ├── trend_changepoints.md
│   │   └── uncertainty_intervals.md
│   ├── _includes/
│   │   ├── blog_pagination.html
│   │   ├── content/
│   │   │   ├── gridblocks.html
│   │   │   └── items/
│   │   │       └── gridblock.html
│   │   ├── doc.html
│   │   ├── doc_paging.html
│   │   ├── footer.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── hero.html
│   │   ├── home_header.html
│   │   ├── katex_import.html
│   │   ├── katex_render.html
│   │   ├── nav/
│   │   │   ├── collection_nav.html
│   │   │   ├── collection_nav_group.html
│   │   │   ├── collection_nav_group_item.html
│   │   │   └── header_nav.html
│   │   ├── nav.html
│   │   ├── nav_search.html
│   │   ├── plugins/
│   │   │   ├── all_share.html
│   │   │   ├── ascii_cinema.html
│   │   │   ├── button.html
│   │   │   ├── github_star.html
│   │   │   ├── github_watch.html
│   │   │   ├── google_share.html
│   │   │   ├── iframe.html
│   │   │   ├── like_button.html
│   │   │   ├── plugin_row.html
│   │   │   ├── post_social_plugins.html
│   │   │   ├── slideshow.html
│   │   │   ├── twitter_follow.html
│   │   │   └── twitter_share.html
│   │   ├── post.html
│   │   ├── powered_by.html
│   │   ├── social_plugins.html
│   │   └── ui/
│   │       └── button.html
│   ├── _layouts/
│   │   ├── basic.html
│   │   ├── blog.html
│   │   ├── blog_default.html
│   │   ├── default.html
│   │   ├── doc_default.html
│   │   ├── doc_page.html
│   │   ├── docs.html
│   │   ├── home.html
│   │   ├── page.html
│   │   ├── plain.html
│   │   ├── post.html
│   │   ├── redirect.html
│   │   └── top-level.html
│   ├── _sass/
│   │   ├── _base.scss
│   │   ├── _blog.scss
│   │   ├── _buttons.scss
│   │   ├── _footer.scss
│   │   ├── _gridBlock.scss
│   │   ├── _header.scss
│   │   ├── _poweredby.scss
│   │   ├── _promo.scss
│   │   ├── _react_docs_nav.scss
│   │   ├── _react_header_nav.scss
│   │   ├── _reset.scss
│   │   ├── _search.scss
│   │   ├── _slideshow.scss
│   │   ├── _syntax-highlighting.scss
│   │   └── _tables.scss
│   ├── blog/
│   │   ├── all.html
│   │   └── index.html
│   ├── css/
│   │   └── main.scss
│   ├── docs/
│   │   └── index.html
│   ├── feed.xml
│   ├── index.md
│   └── nbconvert_template.tpl
├── examples/
│   ├── example_air_passengers.csv
│   ├── example_pedestrians_covid.csv
│   ├── example_pedestrians_multivariate.csv
│   ├── example_retail_sales.csv
│   ├── example_wp_log_R.csv
│   ├── example_wp_log_R_outliers1.csv
│   ├── example_wp_log_R_outliers2.csv
│   ├── example_wp_log_peyton_manning.csv
│   └── example_yosemite_temps.csv
├── notebooks/
│   ├── additional_topics.ipynb
│   ├── diagnostics.ipynb
│   ├── handling_shocks.ipynb
│   ├── multiplicative_seasonality.ipynb
│   ├── non-daily_data.ipynb
│   ├── outliers.ipynb
│   ├── quick_start.ipynb
│   ├── saturating_forecasts.ipynb
│   ├── seasonality,_holiday_effects,_and_regressors.ipynb
│   ├── trend_changepoints.ipynb
│   └── uncertainty_intervals.ipynb
├── python/
│   ├── LICENSE
│   ├── MANIFEST.in
│   ├── README.md
│   ├── prophet/
│   │   ├── __init__.py
│   │   ├── __version__.py
│   │   ├── diagnostics.py
│   │   ├── forecaster.py
│   │   ├── make_holidays.py
│   │   ├── models.py
│   │   ├── plot.py
│   │   ├── py.typed
│   │   ├── serialize.py
│   │   ├── tests/
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── data.csv
│   │   │   ├── data2.csv
│   │   │   ├── data3.csv
│   │   │   ├── serialized_model_v0.6.1.dev0.json
│   │   │   ├── serialized_model_v0.7.1.json
│   │   │   ├── serialized_model_v1.0.1.json
│   │   │   ├── test_diagnostics.py
│   │   │   ├── test_prophet.py
│   │   │   ├── test_serialize.py
│   │   │   └── test_utilities.py
│   │   └── utilities.py
│   ├── pyproject.toml
│   ├── scripts/
│   │   └── generate_holidays_file.py
│   ├── setup.py
│   └── stan/
│       └── prophet.stan
└── python_shim/
    ├── LICENSE
    ├── MANIFEST.in
    ├── README.md
    ├── fbprophet/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── forecaster.py
    │   ├── make_holidays.py
    │   ├── models.py
    │   ├── plot.py
    │   ├── serialize.py
    │   └── tests/
    │       ├── __init__.py
    │       ├── data.csv
    │       └── test_package.py
    ├── requirements.txt
    └── setup.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .deepsource.toml
================================================
version = 1

test_patterns = ["python/prophet/tests/**"]
exclude_patterns = ["R/**", "notebooks/**", "docs/**", "examples/**"]

[[analyzers]]
name = "python"
enabled = true

  [analyzers.meta]
  runtime_version = "3.x.x"


================================================
FILE: .gitattributes
================================================
docs/* linguist-documentation
examples/* linguist-documentation
notebooks/* linguist-documentation


================================================
FILE: .github/workflows/build-and-test.yml
================================================
name: Build

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-test-python:

    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        python-version: ["3.12"]
        os:
          - macos-14-large # Intel
          - macos-14-xlarge # ARM64
          - ubuntu-24.04 # Intel
          - ubuntu-24.04-arm # ARM64
          - windows-latest
      fail-fast: false

    steps:
    - name: "Set environment variables (Windows)"
      if: startsWith(runner.os, 'Windows')
      shell: pwsh
      run: |
        (Get-ItemProperty "HKLM:System\CurrentControlSet\Control\FileSystem").LongPathsEnabled
        $os_version = (Get-CimInstance Win32_OperatingSystem).version
        Echo "OS_VERSION=$os_version" >> $env:GITHUB_ENV
    - uses: actions/checkout@v4
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}
        cache: pip
        cache-dependency-path: "**/python/pyproject.toml"
    - name: "Restore RTools40"
      if: startsWith(runner.os, 'Windows')
      id: cache-rtools
      uses: actions/cache@v4
      with:
        path: C:/rtools40
        key: ${{ runner.os }}-${{ env.OS_VERSION }}-rtools-v1
    - name: Install and test
      run: |
        cd python
        python -m pip install -U --editable ".[dev,parallel]"
        python -m pytest prophet/tests/

  typecheck-python:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: astral-sh/setup-uv@v7
        with:
          activate-environment: true

      - name: Install
        run: cd python && uv pip install ".[dev,parallel]"

      - name: Typecheck with pyrefly
        run: cd python && pyrefly check --output-format=github

  build-and-test-r:

    runs-on: ${{ matrix.config.os }}
    name: R ${{ matrix.config.os }} (${{ matrix.config.r }})
    strategy:
      matrix:
        config:
          - {os: ubuntu-22.04, r: 'release'}
      fail-fast: false

    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
      R_KEEP_PKG_SOURCE: yes
      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
      PKGDIR: "R/"

    steps:
      - uses: actions/checkout@v4

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

      - uses: r-lib/actions/setup-r@v2
        with:
          r-version: ${{ matrix.config.r }}
          use-public-rspm: true

      # Install dependencies - separating the steps to fix dependency conflicts
      - name: Install dependencies
        run: |
          install.packages('remotes')
          remotes::install_deps(dependencies = TRUE)
          remotes::install_cran(c("rcmdcheck", "knitr", "testthat", "readr", "rmarkdown"))
        shell: Rscript {0}
        working-directory: ${{ env.PKGDIR }}

      # Install Stan packages separately if needed
      - name: Install Stan packages
        run: |
          install.packages(c("cmdstanr", "posterior"), repos = c("https://stan-dev.r-universe.dev", getOption("repos")))
        shell: Rscript {0}

      - name: Check
        uses: r-lib/actions/check-r-package@v2
        with:
          upload-snapshots: true
          build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
          working-directory: ${{ env.PKGDIR }}

      - name: Upload package source
        if: always() # Upload even if the check step fails
        uses: actions/upload-artifact@v4
        with:
          name: r-source-package
          path: "**/*.tar.gz"


================================================
FILE: .github/workflows/wheel.yml
================================================
name: "Create Python distributions and upload to PyPI"

on:
  release:
    types: [ published ]
  workflow_dispatch: {}


env:
  STAN_BACKEND: "CMDSTANPY"

jobs:
  make-wheels:
    name: Make ${{ matrix.os }} ${{ matrix.cibw_arch }} wheels
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os:
          - macos-14-large # Intel
          - macos-14-xlarge # ARM64
          - ubuntu-24.04 # Intel
          - ubuntu-24.04-arm # ARM64
          - windows-latest
        cibw_arch: ["native"]
        # Build one wheel (ABI = none) using first build spec, then test on all python versions.
        cibw_build: ["cp310-* cp311-* cp312-*"]
      fail-fast: false

    steps:
      - name: "Set environment variables (Windows)"
        shell: pwsh
        if: startsWith(runner.os, 'Windows')
        run: |
          (Get-ItemProperty "HKLM:System\CurrentControlSet\Control\FileSystem").LongPathsEnabled
          $os_version = (Get-CimInstance Win32_OperatingSystem).version
          Echo "OS_VERSION=$os_version" >> $env:GITHUB_ENV

      - name: "Checkout repo"
        uses: actions/checkout@v5

      - name: "Restore RTools40"
        if: startsWith(runner.os, 'Windows')
        id: cache-rtools
        uses: actions/cache@v4
        with:
          path: C:/rtools40
          key: ${{ runner.os }}-${{ env.OS_VERSION }}-rtools-v1

      - name: "Build wheels"
        uses: pypa/cibuildwheel@v3.2.1
        with:
          package-dir: python
        env:
          CIBW_ENVIRONMENT: >
            STAN_BACKEND="${{ env.STAN_BACKEND }}"
            MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-14-large' && 10.11 || 11.0 }}"
          CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 # distributed cmdstan binary is broken with manylinux_2_28
          CIBW_BUILD: ${{ matrix.cibw_build }}
          CIBW_SKIP: "*musllinux*"
          CIBW_ARCHS: ${{ matrix.cibw_arch }}
          CIBW_BUILD_FRONTEND: build
          CIBW_TEST_REQUIRES: pytest
          CIBW_TEST_COMMAND: pytest --pyargs prophet

      - name: "Upload wheel as artifact"
        uses: actions/upload-artifact@v4
        with:
          name: artifact-${{ matrix.os }}-${{ matrix.cibw_arch }}-wheel
          path: "./**/*.whl"

  make-sdist:
    name: Make source distribution
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - run: pipx run build --sdist
      working-directory: python

    - uses: actions/upload-artifact@v4
      with:
        name: artifact-source-dist
        path: "./**/dist/*.tar.gz"

  upload:
    name: Upload to PyPI
    needs: [make-wheels, make-sdist]
    runs-on: ubuntu-latest
    if: github.event_name == 'release' && github.event.action == 'published'
    environment: release
    permissions:
      id-token: write
    steps:
    - name: Download all artifacts
      uses: actions/download-artifact@v4

    - name: Copy artifacts to dist/ folder
      run: |
        find . -name 'artifact-*' -exec unzip '{}' \;
        mkdir -p dist/
        find . -name '*.tar.gz' -exec mv '{}' dist/ \;
        find . -name '*.whl' -exec mv '{}' dist/ \;

    - name: Upload
      uses: pypa/gh-action-pypi-publish@v1.13.0


================================================
FILE: .gitignore
================================================
# Compiled python modules.
*.pyc

# Persisted models.
*.pkl

# Setuptools distribution folder.
python/dist/
python_shim/dist/

# test cache
.pytest_cache
python/prophet/tests/dask-worker-space

# Python cache
__pycache__

# Python egg metadata, regenerated from source files by setuptools.
python/*.egg-info
python/build/
python_shim/*.egg-info
python_shim/build/

# Notebook checkpoints
.ipynb_checkpoints

*.*~

*.idea
*.vscode
*.DS_Store
*.envrc

# Development with Python
python/**/bin/
python/**/etc/
python/**/lib/
python/**/lib64
python/**/pyvenv.cfg
python/**/share/
python/**/stan_model/
.Rproj.user


================================================
FILE: .travis.yml
================================================
dist: xenial
addons:
  apt:
    packages:
      - libv8-dev
language: python

jobs:
  include:
    - language: python
      python:
        - "3.7"
      cache: pip
      install:
        - pip install --upgrade pip
        - pip install -U -r python/requirements.txt dask[dataframe] distributed
      script:
        - cd python && python setup.py develop test
        - python setup.py clean
        - rm -rf prophet/stan_model
        - wget https://github.com/stan-dev/cmdstan/releases/download/v2.22.1/cmdstan-2.22.1.tar.gz -O /tmp/cmdstan.tar.gz > /dev/null
        - tar -xvf /tmp/cmdstan.tar.gz -C /tmp > /dev/null
        - make -C /tmp/cmdstan-2.22.1/ build > /dev/null
        - CMDSTAN=/tmp/cmdstan-2.22.1 STAN_BACKEND=CMDSTANPY python setup.py develop test

    - language: r
      r:
        - devel
      cache: packages
      install:
        - R -e 'install.packages("devtools")'
        - R -e 'devtools::install_deps("R", dependencies = TRUE)'
        - cd R
        - R CMD build .
        - R CMD INSTALL *tar.gz
      script:
        - R -e 'library(prophet); library(devtools); devtools::test()'



================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct
Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated.

================================================
FILE: Dockerfile
================================================
FROM python:3.7-stretch

RUN apt-get -y install libc-dev

RUN pip install --upgrade pip

COPY . .

WORKDIR python

RUN python -m pip install -e ".[dev, parallel]"

WORKDIR /


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) Facebook, Inc. and its affiliates.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
build:
	docker-compose build

py-shell:
	docker-compose run package ipython

shell:
	docker-compose run package bash


================================================
FILE: R/.Rbuildignore
================================================
^renv$
^renv\.lock$
^data-raw$
^libs$
^doc$
^Meta$
^.*\.Rproj$
^\.Rproj\.user$


================================================
FILE: R/.gitignore
================================================
.DS_Store

# History files
.Rhistory
.Rapp.history

# Session Data files
.RData

# User-specific files
.Ruserdata

# Example code in package build process
*-Ex.R

# Output files from R CMD build
/*.tar.gz

# Output files from R CMD check
/*.Rcheck/

# RStudio files
.Rproj.user/

# produced vignettes
vignettes/*.html
vignettes/*.pdf

# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
.httr-oauth

# knitr and R markdown default cache directories
*_cache/
/cache/

# Temporary files created by R markdown
*.utf8.md
*.knit.md

# R Environment Variables
.Renviron
inst/doc

# Stan
exec/*.rda
src/*.o
src/*.h
src/*.cc
src/*.cpp
src/*.hpp
src/prophet.so
src/prophet.dll
src/init.o

# Development
.Rprofile
renv.lock
renv/


================================================
FILE: R/DESCRIPTION
================================================
Package: prophet
Title: Automatic Forecasting Procedure
Version: 1.2.2
Date: 2026-01-25
Authors@R: c(
  person("Cuong", "Duong", email = "cuong.duong242@gmail.com", role = c("cre", "aut")),
  person("Sean", "Taylor", email = "sjtz@pm.me", role = "aut"),
  person("Ben", "Letham", email = "bletham@fb.com", role = "aut")
  )
Description: Implements a procedure for forecasting time series data based on
    an additive model where non-linear trends are fit with yearly, weekly, and
    daily seasonality, plus holiday effects. It works best with time series
    that have strong seasonal effects and several seasons of historical data.
    Prophet is robust to missing data and shifts in the trend, and typically
    handles outliers well.
URL: https://github.com/facebook/prophet
BugReports: https://github.com/facebook/prophet/issues
Depends:
    R (>= 3.4.0),
    Rcpp (>= 0.12.0),
    rlang (>= 0.3.0.1)
Imports:
    dplyr (>= 0.7.7),
    dygraphs (>= 1.1.1.4),
    extraDistr,
    ggplot2,
    grid,
    lubridate,
    methods,
    RcppParallel (>= 5.0.1),
    rstan (>= 2.18.1),
    rstantools (>= 2.0.0),
    scales,
    StanHeaders,
    stats,
    tidyr (>= 0.6.1),
    xts
Suggests:
    cmdstanr,
    posterior,
    knitr,
    testthat,
    readr,
    rmarkdown
Additional_repositories: https://stan-dev.r-universe.dev
SystemRequirements: GNU make, C++17
Biarch: true
License: MIT + file LICENSE
LinkingTo:
    BH (>= 1.66.0),
    Rcpp (>= 0.12.0),
    RcppParallel (>= 5.0.1),
    RcppEigen (>= 0.3.3.3.0),
    rstan (>= 2.18.1),
    StanHeaders (>= 2.18.0)
LazyData: true
VignetteBuilder: knitr
Encoding: UTF-8
RoxygenNote: 7.2.0


================================================
FILE: R/LICENSE
================================================
YEAR: 2017-present
COPYRIGHT HOLDER: Facebook, Inc.


================================================
FILE: R/NAMESPACE
================================================
# Generated by roxygen2: do not edit by hand

S3method(plot,prophet)
S3method(predict,prophet)
export(add_changepoints_to_plot)
export(add_country_holidays)
export(add_regressor)
export(add_seasonality)
export(cross_validation)
export(dyplot.prophet)
export(fit.prophet)
export(generated_holidays)
export(make_future_dataframe)
export(performance_metrics)
export(plot_cross_validation_metric)
export(plot_forecast_component)
export(predictive_samples)
export(prophet)
export(prophet_plot_components)
export(regressor_coefficients)
import(Rcpp)
import(RcppParallel, except = LdFlags)
import(rlang)
importFrom(dplyr,"%>%")
useDynLib(prophet, .registration = TRUE)


================================================
FILE: R/R/data.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.


#' Generated table of holiday dates at the country level from 1995 to 2045
#'
#' The data is primarily based on the Python package [holidays](https://pypi.org/project/holidays/)
#'
#' @format A data frame with four variables: ds, holiday, country, year
#' @source \url{https://github.com/facebook/prophet/blob/main/python/scripts/generate_holidays_file.py}
#' @export
"generated_holidays"


================================================
FILE: R/R/diagnostics.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

## Makes R CMD CHECK happy due to dplyr syntax below
globalVariables(c(
  "ds", "y", "cap", "yhat", "yhat_lower", "yhat_upper", "size"))

#' Generate cutoff dates
#'
#' @param df Dataframe with historical data.
#' @param horizon timediff forecast horizon.
#' @param initial timediff initial window.
#' @param period timediff Simulated forecasts are done with this period.
#'
#' @return Array of datetimes.
#'
#' @keywords internal
generate_cutoffs <- function(df, horizon, initial, period) {
  # Last cutoff is (latest date in data) - (horizon).
  cutoff <- max(df$ds) - horizon
  tzone <- attr(cutoff, "tzone")  # Timezone is wiped by putting in array
  result <- c(cutoff)
  while (result[length(result)] >= min(df$ds) + initial) {
    cutoff <- cutoff - period
    # If data does not exist in data range (cutoff, cutoff + horizon]
    if (!any((df$ds > cutoff) & (df$ds <= cutoff + horizon))) {
        # Next cutoff point is 'closest date before cutoff in data - horizon'
        if (cutoff > min(df$ds)) {
          closest.date <- max(df$ds[df$ds <= cutoff])
          cutoff <- closest.date - horizon
        }
        # else no data left, leave cutoff as is, it will be dropped.
    }
    result <- c(result, cutoff)
  }
  result <- utils::head(result, -1)
  if (length(result) == 0) {
    stop(paste(
      'Less data than horizon after initial window.',
      'Make horizon or initial shorter.'
    ))
  }
  # Reset timezones
  attr(result, "tzone") <- tzone
  message(paste(
    'Making', length(result), 'forecasts with cutoffs between',
    result[length(result)], 'and', result[1]
  ))
  return(rev(result))
}

#' Cross-validation for time series.
#'
#' Computes forecasts from historical cutoff points which user can input.If
#' not provided, these are computed beginning from (end - horizon), and working
#' backwards making cutoffs with a spacing of period until initial is reached.
#'
#' When period is equal to the time interval of the data, this is the
#' technique described in https://robjhyndman.com/hyndsight/tscv/ .
#'
#' @param model Fitted Prophet model.
#' @param horizon Integer size of the horizon
#' @param units String unit of the horizon, e.g., "days", "secs".
#' @param period Integer amount of time between cutoff dates. Same units as
#'  horizon. If not provided, 0.5 * horizon is used.
#' @param initial Integer size of the first training period. If not provided,
#'  3 * horizon is used. Same units as horizon.
#' @param cutoffs Vector of cutoff dates to be used during
#'  cross-validtation. If not provided works beginning from (end - horizon),
#'  works backwards making cutoffs with a spacing of period until initial is
#'  reached.
#'
#' @return A dataframe with the forecast, actual value, and cutoff date.
#'
#' @export
cross_validation <- function(
    model, horizon, units, period = NULL, initial = NULL, cutoffs=NULL) {
  df <- model$history
  horizon.dt <- as.difftime(horizon, units = units)

  predict_columns <- c('ds', 'yhat')
  if (model$uncertainty.samples){
    predict_columns <- append(predict_columns, c('yhat_lower', 'yhat_upper'))
  }
  # Identify largest seasonality period
  period.max <- 0
  for (s in model$seasonalities) {
    period.max <- max(period.max, s$period)
  }
  seasonality.dt <- as.difftime(period.max, units = 'days')

  if (is.null(cutoffs)){

    # Set period
    if (is.null(period)) {
      period <- 0.5 * horizon
    }
    period.dt <- as.difftime(period, units = units)
    # Set initial
    if (is.null(initial)) {
      initial.dt <- max(
        as.difftime(3 * horizon, units = units),
        seasonality.dt
      )
    }else {
      initial.dt <- as.difftime(initial, units = units)
    }
    cutoffs <- generate_cutoffs(df, horizon.dt, initial.dt, period.dt)
  }else{
    cutoffs <- set_date(ds=cutoffs)
    # Validation
    if (min(cutoffs) <= min(df$ds)) {
      stop('Minimum cutoff value is not strictly greater than min date in history')
    }
    end_date_minus_horizon <- max(df$ds) - horizon.dt
    if (max(cutoffs) > end_date_minus_horizon) {
      stop('Maximum cutoff value is greater than end date minus horizon')
    }
    initial.dt <- cutoffs[1] - min(df$ds)
  }

  # Check if the initial window  (that is, the amount of time between the
  # start of the history and the first cutoff) is less than the
  # maximum seasonality period
  if (initial.dt < seasonality.dt) {
    warning(paste0('Seasonality has period of ', period.max, ' days which ',
      'is larger than initial window. Consider increasing initial.'))
  }

  predicts <- data.frame()
  for (i in 1:length(cutoffs)) {
    df.c <- single_cutoff_forecast(df, model, cutoffs[i], horizon.dt, predict_columns)
    predicts <- rbind(predicts, df.c)
  }
  return(predicts)
}

#' Forecast for a single cutoff.

#' Used in cross_validation function when evaluating for multiple cutoffs.
#'
#' @param df Dataframe with history for cutoff.
#' @param model Prophet model object.
#' @param cutoff Datetime of cutoff.
#' @param horizon.dt timediff forecast horizon.
#' @param predict_columns Array of names of columns to be returned in output.
#'
#' @return Dataframe with forecast, actual value, and cutoff.
#'
#' @keywords internal
single_cutoff_forecast <- function(df, model, cutoff, horizon.dt, predict_columns){
  m <- prophet_copy(model, cutoff)
  # Train model
  history.c <- dplyr::filter(df, ds <= cutoff)
  if (nrow(history.c) < 2) {
    stop('Less than two datapoints before cutoff. Increase initial window.')
  }
  fit.args <- c(list(m=m, df=history.c), model$fit.kwargs)
  m <- do.call(fit.prophet, fit.args)
  # Calculate yhat
  df.predict <- dplyr::filter(df, ds > cutoff, ds <= cutoff + horizon.dt)
  # Get the columns for the future dataframe
  columns <- 'ds'
  if (m$growth == 'logistic') {
    columns <- c(columns, 'cap')
    if (m$logistic.floor) {
      columns <- c(columns, 'floor')
    }
  }
  columns <- c(columns, names(m$extra_regressors))
  for (name in names(m$seasonalities)) {
    condition.name = m$seasonalities[[name]]$condition.name
    if (!is.null(condition.name)) {
      columns <- c(columns, condition.name)
    }
  }
  future <- df.predict[columns]
  yhat <- stats::predict(m, future)
  # Merge yhat, y, and cutoff.
  df.c <- dplyr::inner_join(df.predict, yhat[predict_columns], by = "ds")
  df.c <- df.c[c(predict_columns, "y")]
  df.c <- dplyr::select(df.c, y, predict_columns)
  df.c$cutoff <- cutoff
  return(df.c)
}

#' Copy Prophet object.
#'
#' @param m Prophet model object.
#' @param cutoff Date, possibly as string. Changepoints are only retained if
#'  changepoints <= cutoff.
#'
#' @return An unfitted Prophet model object with the same parameters as the
#'  input model.
#'
#' @keywords internal
prophet_copy <- function(m, cutoff = NULL) {
  if (is.null(m$history)) {
    stop("This is for copying a fitted Prophet object.")
  }

  if (m$specified.changepoints) {
    changepoints <- m$changepoints
    if (!is.null(cutoff)) {
      cutoff <- set_date(cutoff)
      last_history_date <- max(m$history$ds[m$history$ds <= cutoff])
      changepoints <- changepoints[changepoints < last_history_date]
    }
  } else {
    changepoints <- NULL
  }
  # Auto seasonalities are set to FALSE because they are already set in
  # m$seasonalities.
  m2 <- prophet(
    growth = m$growth,
    changepoints = changepoints,
    n.changepoints = m$n.changepoints,
    changepoint.range = m$changepoint.range,
    yearly.seasonality = FALSE,
    weekly.seasonality = FALSE,
    daily.seasonality = FALSE,
    holidays = m$holidays,
    seasonality.mode = m$seasonality.mode,
    seasonality.prior.scale = m$seasonality.prior.scale,
    changepoint.prior.scale = m$changepoint.prior.scale,
    holidays.prior.scale = m$holidays.prior.scale,
    mcmc.samples = m$mcmc.samples,
    interval.width = m$interval.width,
    uncertainty.samples = m$uncertainty.samples,
    fit = FALSE
  )
  m2$extra_regressors <- m$extra_regressors
  m2$seasonalities <- m$seasonalities
  m2$country_holidays <- m$country_holidays
  return(m2)
}

#' Compute performance metrics from cross-validation results.
#'
#' Computes a suite of performance metrics on the output of cross-validation.
#' By default the following metrics are included:
#' 'mse': mean squared error,
#' 'rmse': root mean squared error,
#' 'mae': mean absolute error,
#' 'mape': mean percent error,
#' 'mdape': median percent error,
#' 'smape': symmetric mean absolute percentage error,
#' 'coverage': coverage of the upper and lower intervals
#'
#' A subset of these can be specified by passing a list of names as the
#' `metrics` argument.
#'
#' Metrics are calculated over a rolling window of cross validation
#' predictions, after sorting by horizon. Averaging is first done within each
#' value of the horizon, and then across horizons as needed to reach the
#' window size. The size of that window (number of simulated forecast points)
#' is determined by the rolling_window argument, which specifies a proportion
#' of simulated forecast points to include in each window. rolling_window=0
#' will compute it separately for each horizon. The default of
#' rolling_window=0.1 will use 10% of the rows in df in each window.
#' rolling_window=1 will compute the metric across all simulated forecast
#' points. The results are set to the right edge of the window.
#'
#' If rolling_window < 0, then metrics are computed at each datapoint with no
#' averaging (i.e., 'mse' will actually be squared error with no mean).
#'
#' The output is a dataframe containing column 'horizon' along with columns
#' for each of the metrics computed.
#'
#' @param df The dataframe returned by cross_validation.
#' @param metrics An array of performance metrics to compute. If not provided,
#'  will use c('mse', 'rmse', 'mae', 'mape', 'mdape', 'smape', 'coverage').
#' @param rolling_window Proportion of data to use in each rolling window for
#'  computing the metrics. Should be in [0, 1] to average.
#'
#' @return A dataframe with a column for each metric, and column 'horizon'.
#'
#' @export
performance_metrics <- function(df, metrics = NULL, rolling_window = 0.1) {
  valid_metrics <- c('mse', 'rmse', 'mae', 'mape', 'mdape', 'smape', 'coverage')
  if (is.null(metrics)) {
    metrics <- valid_metrics
  }
  if ((!('yhat_lower' %in% colnames(df)) | !('yhat_upper' %in% colnames(df))) & ('coverage' %in% metrics)){
    metrics <- metrics[metrics != 'coverage']
  }

  if (length(metrics) != length(unique(metrics))) {
    stop('Input metrics must be an array of unique values.')
  }
  if (!all(metrics %in% valid_metrics)) {
    stop(
      paste('Valid values for metrics are:', paste(valid_metrics, collapse = ", "))
    )
  }
  df_m <- df
  df_m$horizon <- df_m$ds - df_m$cutoff
  df_m <- df_m[order(df_m$horizon),]
  if (('mape' %in% metrics) & (min(abs(df_m$y)) < 1e-8)) {
    message('Skipping MAPE because y close to 0')
    metrics <- metrics[metrics != 'mape']
  }
  if (('mdape' %in% metrics) & (min(abs(df_m$y)) < 1e-8)) {
    message('Skipping MDAPE because y close to 0')
    metrics <- metrics[metrics != 'mdape']
  }
  if (length(metrics) == 0) {
    return(NULL)
  }
  w <- as.integer(rolling_window * nrow(df_m))
  if (w >= 0) {
    w <- max(w, 1)
    w <- min(w, nrow(df_m))
  }
  # Compute all metrics
  dfs = list()
  for (metric in metrics) {
    dfs[[metric]] <- get(metric)(df_m, w)
  }
  res <- dfs[[metrics[1]]]
  for (i in 2:length(metrics)) {
    res_m <- dfs[[metrics[i]]]
    stopifnot(res$horizon == res_m$horizon)
    res[[metrics[i]]] = res_m[[metrics[i]]]
  }
  return(res)
}

#' Compute a rolling mean of x, after first aggregating by h
#'
#' Right-aligned. Computes a single mean for each unique value of h. Each mean
#' is over at least w samples.
#'
#' @param x Array.
#' @param h Array of horizon for each value in x.
#' @param w Integer window size (number of elements).
#' @param name String name for metric in result dataframe.
#'
#' @return Dataframe with columns horizon and name, the rolling mean of x.
#'
#' @importFrom dplyr "%>%"
#' @keywords internal
rolling_mean_by_h <- function(x, h, w, name) {
  # Aggregate over h
  df <- data.frame(x=x, h=h)
  df2 <- df %>%
    dplyr::group_by(h) %>%
    dplyr::summarise(sum = sum(x), n = dplyr::n())

  xs <- df2$sum
  ns <- df2$n
  hs <- df2$h
  
  trailing_i <- length(hs)
  x_sum <- 0
  n_sum <- 0
  # We don't know output size but it is bounded by length(hs)
  res_x <- vector("double", length=length(hs))
  
  # Start from the right and work backwards
  for(i in length(hs):1) {
    x_sum <- x_sum + xs[i]
    n_sum <- n_sum + ns[i]
    while (n_sum >= w) {
      # Include points from the previous horizon. All of them if still
      # less than w, otherwise weight the mean by the difference
      excess_n <- n_sum - w
      excess_x <- excess_n * xs[i]/ ns[i]
      res_x[trailing_i] <- (x_sum - excess_x) / w
      x_sum <- x_sum - xs[trailing_i]
      n_sum <- n_sum - ns[trailing_i]
      trailing_i <- trailing_i - 1
    }
  }

  # R handles subsetting weirdly
  if(trailing_i == 0) {
    res_h <- hs
  } else {
    res_h <- hs[-(1:trailing_i)]
    res_x <- res_x[-(1:trailing_i)]  
  }
  
  res <- data.frame(horizon=res_h)
  res[[name]] <- res_x

  return(res)
}


#' Compute a rolling median of x, after first aggregating by h
#'
#' Right-aligned. Computes a single median for each unique value of h. Each median
#' is over at least w samples.
#'
#' For each h where there are fewer than w samples, we take samples from the previous h,
#  moving backwards. (In other words, we ~ assume that the x's are shuffled within each h.)
#'
#' @param x Array.
#' @param h Array of horizon for each value in x.
#' @param w Integer window size (number of elements).
#' @param name String name for metric in result dataframe.
#'
#' @return Dataframe with columns horizon and name, the rolling median of x.
#'
#' @importFrom dplyr "%>%"
rolling_median_by_h <- function(x, h, w, name) {
  # Aggregate over h
  df <- data.frame(x=x, h=h)
  grouped <- df %>% dplyr::group_by(h)
  df2 <- grouped %>%
    dplyr::summarise(size=dplyr::n()) %>%
    dplyr::arrange(h) %>%
    dplyr::select(h, size)

  hs <- df2$h
  res <- data.frame(horizon=c())
  res[[name]] <- c()

  # Start from the right and work backwards
  i <- length(hs)
  while (i > 0) {
    h_i <- hs[i]
    xs <- grouped  %>%
      dplyr::filter(h==h_i)
    xs <- xs$x

    next_idx_to_add = which.max(h==h_i) - 1

    while ((length(xs) < w) & (next_idx_to_add > 0)) {
      # Include points from the previous horizon. All of them if still less
      # than w, otherwise just enough to get to w.
      xs <- c(x[next_idx_to_add], xs)
      next_idx_to_add = next_idx_to_add - 1
    }
    if (length(xs) < w) {
      # Ran out of horizons before enough points.
      break
    }
    res.i <- data.frame(horizon=hs[i])
    res.i[[name]] <- stats::median(xs)
    res <- rbind(res.i, res)
    i <- i - 1
  }
  return(res)
}

# The functions below specify performance metrics for cross-validation results.
# Each takes as input the output of cross_validation, and returns the statistic
# as a dataframe, given a window size for rolling aggregation.

#' Mean squared error
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of mean squared errors.
#'
#' @keywords internal
mse <- function(df, w) {
  se <- (df$y - df$yhat) ** 2
  if (w < 0) {
    return(data.frame(horizon = df$horizon, mse = se))
  }
  return(rolling_mean_by_h(x = se, h = df$horizon, w = w, name = 'mse'))
}

#' Root mean squared error
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of root mean squared errors.
#'
#' @keywords internal
rmse <- function(df, w) {
  res <- mse(df, w)
  res$mse <- sqrt(res$mse)
  names(res)[names(res) == 'mse'] <- 'rmse'
  return(res)
}

#' Mean absolute error
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of mean absolute errors.
#'
#' @keywords internal
mae <- function(df, w) {
  ae <- abs(df$y - df$yhat)
  if (w < 0) {
    return(data.frame(horizon = df$horizon, mae = ae))
  }
  return(rolling_mean_by_h(x = ae, h = df$horizon, w = w, name = 'mae'))
}

#' Mean absolute percent error
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of mean absolute percent errors.
#'
#' @keywords internal
mape <- function(df, w) {
  ape <- abs((df$y - df$yhat) / df$y)
  if (w < 0) {
    return(data.frame(horizon = df$horizon, mape = ape))
  }
  return(rolling_mean_by_h(x = ape, h = df$horizon, w = w, name = 'mape'))
}


#' Median absolute percent error
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of median absolute percent errors.
#'
#' @keywords internal
mdape <- function(df, w) {
  ape <- abs((df$y - df$yhat) / df$y)
  if (w < 0) {
    return(data.frame(horizon = df$horizon, mdape = ape))
  }
  return(rolling_median_by_h(x = ape, h = df$horizon, w = w, name = 'mdape'))
}


#' Symmetric mean absolute percentage error
#' based on Chen and Yang (2004) formula
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of symmetric mean absolute percent errors.
#'
#' @keywords internal
smape <- function(df, w) {
  sape <- abs(df$y - df$yhat) / ((abs(df$y) + abs(df$yhat)) / 2)
  if (w < 0) {
    return(data.frame(horizon = df$horizon, smape = sape))
  }
  return(rolling_mean_by_h(x = sape, h = df$horizon, w = w, name = 'smape'))
}


#' Coverage
#'
#' @param df Cross-validation results dataframe.
#' @param w Aggregation window size.
#'
#' @return Array of coverages
#'
#' @keywords internal
coverage <- function(df, w) {
  is_covered <- (df$y >= df$yhat_lower) & (df$y <= df$yhat_upper)
  if (w < 0) {
    return(data.frame(horizon = df$horizon, coverage = is_covered))
  }
  return(
    rolling_mean_by_h(x = is_covered, h = df$horizon, w = w, name = 'coverage')
  )
}


================================================
FILE: R/R/make_holidays.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.


#' Return all possible holiday names of given country
#'
#' @param country.name Country name (character).
#'
#' @return A vector of all possible holiday names (unique) of given country.
#' @keywords internal
get_holiday_names <- function(country.name){
    holidays <- generated_holidays %>% 
      dplyr::filter(country == country.name) %>%
      dplyr::select(holiday) %>%
      unique()
  return(holidays$holiday)
}


#' Make dataframe of holidays for given years and countries
#'
#' @param years List of years for which to include holiday dates.
#' @param country.name Country name (character).
#'
#' @return Dataframe with 'ds' and 'holiday', which can directly feed
#'  to 'holidays' params in Prophet
#' @keywords internal
make_holidays_df <- function(years, country.name){
  country.holidays = generated_holidays %>%
    dplyr::filter(country == country.name)
  max.year <- max(country.holidays$year)
  min.year <- min(country.holidays$year)
  if (max(years) > max.year ||  min(years) < min.year){
    warning.msg = paste("Holidays for", country.name, "are only supported from", min.year, 
                        "to", max.year)
    warning(warning.msg)
  }
  holidays.df <- country.holidays %>%
    dplyr::filter(year %in% years) %>%
    dplyr::select(ds, holiday) %>%
    dplyr::mutate(ds = as.Date(ds)) %>%
    data.frame
  return(holidays.df)
}


================================================
FILE: R/R/plot.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

#' Merge history and forecast for plotting.
#'
#' @param m Prophet object.
#' @param fcst Data frame returned by prophet predict.
#'
#' @importFrom dplyr "%>%"
#' @keywords internal
df_for_plotting <- function(m, fcst) {
  # Make sure there is no y in fcst
  fcst$y <- NULL
  df <- m$history %>%
    dplyr::select(ds, y) %>%
    dplyr::full_join(fcst, by = "ds") %>%
    dplyr::arrange(ds)
  return(df)
}

#' Plot the prophet forecast.
#'
#' @param x Prophet object.
#' @param fcst Data frame returned by predict(m, df).
#' @param uncertainty Optional boolean indicating if the uncertainty interval for yhat
#'  should be plotted, which will only be done if x$uncertainty.samples > 0.
#'  Must be present in fcst as yhat_lower and yhat_upper.
#' @param plot_cap Boolean indicating if the capacity should be shown in the
#'  figure, if available.
#' @param xlabel Optional label for x-axis
#' @param ylabel Optional label for y-axis
#' @param ... additional arguments
#'
#' @return A ggplot2 plot.
#'
#' @examples
#' \dontrun{
#' history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
#'                       y = sin(1:366/200) + rnorm(366)/10)
#' m <- prophet(history)
#' future <- make_future_dataframe(m, periods = 365)
#' forecast <- predict(m, future)
#' plot(m, forecast)
#' }
#'
#' @export
plot.prophet <- function(x, fcst, uncertainty = TRUE, plot_cap = TRUE,
                         xlabel = 'ds', ylabel = 'y', ...) {
  df <- df_for_plotting(x, fcst)
  gg <- ggplot2::ggplot(df, ggplot2::aes(x = ds, y = y)) +
    ggplot2::labs(x = xlabel, y = ylabel)
  if (exists('cap', where = df) && plot_cap) {
    gg <- gg + ggplot2::geom_line(
      ggplot2::aes(y = cap), linetype = 'dashed', na.rm = TRUE)
  }
  if (x$logistic.floor && exists('floor', where = df) && plot_cap) {
    gg <- gg + ggplot2::geom_line(
      ggplot2::aes(y = floor), linetype = 'dashed', na.rm = TRUE)
  }
  if (uncertainty && x$uncertainty.samples && exists('yhat_lower', where = df)) {
    gg <- gg +
      ggplot2::geom_ribbon(ggplot2::aes(ymin = yhat_lower, ymax = yhat_upper),
                           alpha = 0.2,
                           fill = "#0072B2",
                           na.rm = TRUE)
  }
  gg <- gg +
    ggplot2::geom_point(na.rm=TRUE) +
    ggplot2::geom_line(ggplot2::aes(y = yhat), color = "#0072B2",
                       na.rm = TRUE) +
    ggplot2::theme(aspect.ratio = 3 / 5)
  return(gg)
}

#' Plot the components of a prophet forecast.
#' Prints a ggplot2 with whichever are available of: trend, holidays, weekly
#' seasonality, yearly seasonality, and additive and multiplicative extra
#' regressors.
#'
#' @param m Prophet object.
#' @param fcst Data frame returned by predict(m, df).
#' @param uncertainty Optional boolean indicating if the uncertainty interval should be
#'  plotted for the trend, from fcst columns trend_lower and trend_upper.This will
#'  only be done if m$uncertainty.samples > 0.
#' @param plot_cap Boolean indicating if the capacity should be shown in the
#'  figure, if available.
#' @param weekly_start Integer specifying the start day of the weekly
#'  seasonality plot. 0 (default) starts the week on Sunday. 1 shifts by 1 day
#'  to Monday, and so on.
#' @param yearly_start Integer specifying the start day of the yearly
#'  seasonality plot. 0 (default) starts the year on Jan 1. 1 shifts by 1 day
#'  to Jan 2, and so on.
#' @param render_plot Boolean indicating if the plots should be rendered.
#'  Set to FALSE if you want the function to only return the list of panels.
#'
#' @return Invisibly return a list containing the plotted ggplot objects
#'
#' @export
#' @importFrom dplyr "%>%"
prophet_plot_components <- function(
  m, fcst, uncertainty = TRUE, plot_cap = TRUE, weekly_start = 0,
  yearly_start = 0, render_plot = TRUE
) {
  dt <- diff(time_diff(m$history$ds, m$start))
  min.dt <- min(dt[dt > 0])
  # Plot the trend
  panels <- list(
    plot_forecast_component(m, fcst, 'trend', uncertainty, plot_cap))
  # Plot holiday components, if present.
  if (!is.null(m$train.holiday.names) && ('holidays' %in% colnames(fcst))) {
    panels[[length(panels) + 1]] <- plot_forecast_component(
      m, fcst, 'holidays', uncertainty, FALSE)
  }
  # Plot weekly seasonality, if present
  if ("weekly" %in% colnames(fcst)) {
    if (min.dt < 1) {
      panels[[length(panels) + 1]] <- plot_seasonality(m, 'weekly', uncertainty)
    } else {
      panels[[length(panels) + 1]] <- plot_weekly(m, uncertainty, weekly_start)
    }
  }
  # Plot yearly seasonality, if present
  if ("yearly" %in% colnames(fcst)) {
    panels[[length(panels) + 1]] <- plot_yearly(m, uncertainty, yearly_start)
  }
  # Plot other seasonalities
  for (name in sort(names(m$seasonalities))) {
    if (!(name %in% c('weekly', 'yearly')) &&
        (name %in% colnames(fcst))) {
      if (m$seasonalities[[name]]$period == 7) {
        panels[[length(panels) + 1]] <- plot_weekly(m, uncertainty,
                                                    weekly_start, name)
      } else if (m$seasonalities[[name]]$period == 365.25) {
        panels[[length(panels) + 1]] <- plot_yearly(m, uncertainty,
                                                    yearly_start, name)
      } else {
        panels[[length(panels) + 1]] <- plot_seasonality(m, name, uncertainty)
      }
    }
  }
  # Plot extra regressors
  regressors <- list(additive = FALSE, multiplicative = FALSE)
  for (name in names(m$extra_regressors)) {
    regressors[[m$extra_regressors[[name]]$mode]] <- TRUE
  }
  for (mode in c('additive', 'multiplicative')) {
    if ((regressors[[mode]]) &
        (paste0('extra_regressors_', mode) %in% colnames(fcst))
    ) {
      panels[[length(panels) + 1]] <- plot_forecast_component(
        m, fcst, paste0('extra_regressors_', mode), uncertainty, FALSE)
    }
  }

  if (render_plot) {
    # Make the plot.
    grid::grid.newpage()
    grid::pushViewport(grid::viewport(layout = grid::grid.layout(length(panels),
                                                                 1)))
    for (i in seq_along(panels)) {
      print(panels[[i]], vp = grid::viewport(layout.pos.row = i,
                                             layout.pos.col = 1))
    }
  }
  return(invisible(panels))
}

#' Plot a particular component of the forecast.
#'
#' @param m Prophet model
#' @param fcst Dataframe output of `predict`.
#' @param name String name of the component to plot (column of fcst).
#' @param uncertainty Optional boolean to plot uncertainty intervals, which will 
#'  only be done if m$uncertainty.samples > 0.
#' @param plot_cap Boolean indicating if the capacity should be shown in the
#'  figure, if available.
#'
#' @return A ggplot2 plot.
#'
#' @export
plot_forecast_component <- function(
  m, fcst, name, uncertainty = TRUE, plot_cap = FALSE
) {

  wrapped.name <- paste0("`", name, "`")
  
  lower.name <- paste0(name, '_lower')
  lower.name <- paste0("`", lower.name, "`")

  upper.name <- paste0(name, '_upper')
  upper.name <- paste0("`", upper.name, "`")

  gg.comp <- ggplot2::ggplot(
      fcst, ggplot2::aes_string(x = 'ds', y = wrapped.name, group = 1)) +
    ggplot2::geom_line(color = "#0072B2", na.rm = TRUE)
  if (exists('cap', where = fcst) && plot_cap) {
    gg.comp <- gg.comp + ggplot2::geom_line(
      ggplot2::aes(y = cap), linetype = 'dashed', na.rm = TRUE)
  }
  if (exists('floor', where = fcst) && plot_cap) {
    gg.comp <- gg.comp + ggplot2::geom_line(
      ggplot2::aes(y = floor), linetype = 'dashed', na.rm = TRUE)
  }
  if (uncertainty && m$uncertainty.samples) {
    gg.comp <- gg.comp +
      ggplot2::geom_ribbon(
        ggplot2::aes_string(
          ymin = lower.name, ymax = upper.name
        ),
        alpha = 0.2,
        fill = "#0072B2",
        na.rm = TRUE)
  }
  if (name %in% m$component.modes$multiplicative) {
    gg.comp <- gg.comp + ggplot2::scale_y_continuous(labels = scales::percent)
  }
  return(gg.comp)
}

#' Prepare dataframe for plotting seasonal components.
#'
#' @param m Prophet object.
#' @param ds Array of dates for column ds.
#'
#' @return A dataframe with seasonal components on ds.
#'
#' @keywords internal
seasonality_plot_df <- function(m, ds) {
  df_list <- list(ds = ds, cap = 1, floor = 0)
  for (name in names(m$extra_regressors)) {
    df_list[[name]] <- 0
  }
  # Activate all conditional seasonality columns
  for (name in names(m$seasonalities)) {
    condition.name = m$seasonalities[[name]]$condition.name
    if (!is.null(condition.name)) {
      df_list[[condition.name]] <- TRUE
    }
  }
  df <- as.data.frame(df_list)
  df <- setup_dataframe(m, df)$df
  return(df)
}

#' Plot the weekly component of the forecast.
#'
#' @param m Prophet model object
#' @param uncertainty Optional boolean to plot uncertainty intervals, which will
#'  only be done if m$uncertainty.samples > 0.
#' @param weekly_start Integer specifying the start day of the weekly
#'  seasonality plot. 0 (default) starts the week on Sunday. 1 shifts by 1 day
#'  to Monday, and so on.
#' @param name Name of seasonality component if previously changed
#'  from default 'weekly'.
#'
#' @return A ggplot2 plot.
#'
#' @keywords internal
plot_weekly <- function(m, uncertainty = TRUE, weekly_start = 0,
                        name = 'weekly') {
  # Compute weekly seasonality for a Sun-Sat sequence of dates.
  days <- seq(set_date('2017-01-01'), by='d', length.out=7) + as.difftime(
    weekly_start, units = "days")
  df.w <- seasonality_plot_df(m, days)
  seas <- predict_seasonal_components(m, df.w)
  seas$dow <- factor(weekdays(df.w$ds), levels=weekdays(df.w$ds))

  gg.weekly <- ggplot2::ggplot(
      seas, ggplot2::aes_string(x = 'dow', y = name, group = 1)) +
    ggplot2::geom_line(color = "#0072B2", na.rm = TRUE) +
    ggplot2::labs(x = "Day of week")
  if (uncertainty && m$uncertainty.samples) {
    gg.weekly <- gg.weekly +
      ggplot2::geom_ribbon(ggplot2::aes_string(ymin = paste0(name, '_lower'),
                                               ymax = paste0(name, '_upper')),
                           alpha = 0.2,
                           fill = "#0072B2",
                           na.rm = TRUE)
  }
  if (m$seasonalities[[name]]$mode == 'multiplicative') {
    gg.weekly <- (
      gg.weekly + ggplot2::scale_y_continuous(labels = scales::percent)
    )
  }
  return(gg.weekly)
}

#' Plot the yearly component of the forecast.
#'
#' @param m Prophet model object.
#' @param uncertainty Optional boolean to plot uncertainty intervals, which
#'  will only be done if m$uncertainty.samples > 0.
#' @param yearly_start Integer specifying the start day of the yearly
#'  seasonality plot. 0 (default) starts the year on Jan 1. 1 shifts by 1 day
#'  to Jan 2, and so on.
#' @param name Name of seasonality component if previously changed
#'  from default 'yearly'.
#'
#' @return A ggplot2 plot.
#'
#' @keywords internal
plot_yearly <- function(m, uncertainty = TRUE, yearly_start = 0,
                        name = 'yearly') {
  # Compute yearly seasonality for a Jan 1 - Dec 31 sequence of dates.
  days <- seq(set_date('2017-01-01'), by='d', length.out=365) + as.difftime(
    yearly_start, units = "days")
  df.y <- seasonality_plot_df(m, days)
  seas <- predict_seasonal_components(m, df.y)
  seas$ds <- df.y$ds

  gg.yearly <- ggplot2::ggplot(
      seas, ggplot2::aes_string(x = 'ds', y = name, group = 1)) +
    ggplot2::geom_line(color = "#0072B2", na.rm = TRUE) +
    ggplot2::labs(x = "Day of year") +
    ggplot2::scale_x_datetime(labels = scales::date_format('%B %d'))
  if (uncertainty && m$uncertainty.samples) {
    gg.yearly <- gg.yearly +
      ggplot2::geom_ribbon(ggplot2::aes_string(ymin = paste0(name, '_lower'),
                                               ymax = paste0(name, '_upper')),
                           alpha = 0.2,
                           fill = "#0072B2",
                           na.rm = TRUE)
  }
  if (m$seasonalities[[name]]$mode == 'multiplicative') {
    gg.yearly <- (
      gg.yearly + ggplot2::scale_y_continuous(labels = scales::percent)
    )
  }
  return(gg.yearly)
}

#' Plot a custom seasonal component.
#'
#' @param m Prophet model object.
#' @param name String name of the seasonality.
#' @param uncertainty Optional boolean to plot uncertainty intervals, which
#'  will only be done if m$uncertainty.samples > 0.
#'
#' @return A ggplot2 plot.
#'
#' @keywords internal
plot_seasonality <- function(m, name, uncertainty = TRUE) {
  # Compute seasonality from Jan 1 through a single period.
  start <- set_date('2017-01-01')
  period <- m$seasonalities[[name]]$period
  end <- start + period * 24 * 3600
  plot.points <- 200
  days <- seq(from=start, to=end, length.out=plot.points)
  df.y <- seasonality_plot_df(m, days)
  seas <- predict_seasonal_components(m, df.y)
  seas$ds <- df.y$ds
  gg.s <- ggplot2::ggplot(
      seas, ggplot2::aes_string(x = 'ds', y = name, group = 1)) +
    ggplot2::geom_line(color = "#0072B2", na.rm = TRUE)

  date_breaks <- ggplot2::waiver()
  label <- 'ds'
  if (name == 'weekly') {
    fmt.str <- '%a'
    date_breaks <- '1 day'
    label <- 'Day of Week'
  } else if (name == 'daily') {
    fmt.str <- '%T'
    date_breaks <- '4 hours'
    label <- 'Hour of day'
  } else if (period <= 2) {
    fmt.str <- '%T'
    label <- 'Hours'
  } else if (period < 14) {
    fmt.str <- '%m/%d %R'
  } else {
    fmt.str <- '%m/%d'
  }
  gg.s <- gg.s +
    ggplot2::scale_x_datetime(
      labels = scales::date_format(fmt.str), date_breaks = date_breaks
    ) +
    ggplot2::xlab(label)
  if (uncertainty && m$uncertainty.samples) {
    gg.s <- gg.s +
    ggplot2::geom_ribbon(
      ggplot2::aes_string(
        ymin = paste0(name, '_lower'), ymax = paste0(name, '_upper')
      ),
      alpha = 0.2,
      fill = "#0072B2",
      na.rm = TRUE)
  }
  if (m$seasonalities[[name]]$mode == 'multiplicative') {
    gg.s <- gg.s + ggplot2::scale_y_continuous(labels = scales::percent)
  }
  return(gg.s)
}

#' Get layers to overlay significant changepoints on prophet forecast plot.
#'
#' @param m Prophet model object.
#' @param threshold Numeric, changepoints where abs(delta) >= threshold are
#'  significant. (Default 0.01)
#' @param cp_color Character, line color. (Default "red")
#' @param cp_linetype Character or integer, line type. (Default "dashed")
#' @param trend Logical, if FALSE, do not draw trend line. (Default TRUE)
#' @param ... Other arguments passed on to layers.
#'
#' @return A list of ggplot2 layers.
#'
#' @examples
#' \dontrun{
#' plot(m, fcst) + add_changepoints_to_plot(m)
#' }
#'
#' @export
add_changepoints_to_plot <- function(m, threshold = 0.01, cp_color = "red",
                               cp_linetype = "dashed", trend = TRUE, ...) {
  layers <- list()
  if (trend) {
    trend_layer <- ggplot2::geom_line(
      ggplot2::aes_string("ds", "trend"), color = cp_color, ...)
    layers <- append(layers, trend_layer)
  }
  signif_changepoints <- m$changepoints[abs(m$params$delta) >= threshold]
  cp_layer <- ggplot2::geom_vline(
    xintercept = as.integer(signif_changepoints), color = cp_color,
    linetype = cp_linetype, ...)
  layers <- append(layers, cp_layer)
  return(layers)
}

#' Plot the prophet forecast.
#'
#' @param x Prophet object.
#' @param fcst Data frame returned by predict(m, df).
#' @param uncertainty Optional boolean indicating if the uncertainty interval for yhat
#'  should be plotted, which will only be done if x$uncertainty.samples > 0. Must be
#'  present in fcst as yhat_lower and yhat_upper.
#' @param ... additional arguments passed to dygraphs::dygraph
#' @importFrom dplyr "%>%"
#' @return A dygraph plot.
#'
#' @examples
#' \dontrun{
#' history <- data.frame(
#'  ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
#'  y = sin(1:366/200) + rnorm(366)/10)
#' m <- prophet(history)
#' future <- make_future_dataframe(m, periods = 365)
#' forecast <- predict(m, future)
#' dyplot.prophet(m, forecast)
#' }
#'
#' @export
dyplot.prophet <- function(x, fcst, uncertainty=TRUE,
                           ...)
{
  forecast.label='Predicted'
  actual.label='Actual'
  # create data.frame for plotting
  df <- df_for_plotting(x, fcst)

  # build variables to include, or not, the uncertainty data
  if(uncertainty && x$uncertainty.samples && exists("yhat_lower", where = df))
  {
    colsToKeep <- c('y', 'yhat', 'yhat_lower', 'yhat_upper')
    forecastCols <- c('yhat_lower', 'yhat', 'yhat_upper')
  } else
  {
    colsToKeep <- c('y', 'yhat')
    forecastCols <- c('yhat')
  }
  # convert to xts for easier date handling by dygraph
  dfTS <- xts::xts(df %>% dplyr::select(.dots=colsToKeep), order.by = df$ds)

  # base plot
  dyBase <- dygraphs::dygraph(dfTS, ...)

  presAnnotation <- function(dygraph, x, text) {
    dygraph %>%
      dygraphs::dyAnnotation(x, text, text, attachAtBottom = TRUE)
  }

  dyBase <- dyBase %>%
    # plot actual values
    dygraphs::dySeries(
      'y', label=actual.label, color='black', drawPoints=TRUE, strokeWidth=0
    ) %>%
    # plot forecast and ribbon
    dygraphs::dySeries(forecastCols, label=forecast.label, color='blue') %>%
    # allow zooming
    dygraphs::dyRangeSelector() %>%
    # make unzoom button
    dygraphs::dyUnzoom()
  if (!is.null(x$holidays)) {
    for (i in 1:nrow(x$holidays)) {
      # make a gray line
      dyBase <- dyBase %>% dygraphs::dyEvent(
        x$holidays$ds[i],color = "rgb(200,200,200)", strokePattern = "solid")
      dyBase <- dyBase %>% dygraphs::dyAnnotation(
        x$holidays$ds[i], x$holidays$holiday[i], x$holidays$holiday[i],
        attachAtBottom = TRUE)
    }
  }
  return(dyBase)
}

#' Plot a performance metric vs. forecast horizon from cross validation.

#' Cross validation produces a collection of out-of-sample model predictions
#' that can be compared to actual values, at a range of different horizons
#' (distance from the cutoff). This computes a specified performance metric
#' for each prediction, and aggregated over a rolling window with horizon.
#'
#' This uses fbprophet.diagnostics.performance_metrics to compute the metrics.
#' Valid values of metric are 'mse', 'rmse', 'mae', 'mape', and 'coverage'.
#'
#' rolling_window is the proportion of data included in the rolling window of
#' aggregation. The default value of 0.1 means 10% of data are included in the
#' aggregation for computing the metric.
#'
#' As a concrete example, if metric='mse', then this plot will show the
#' squared error for each cross validation prediction, along with the MSE
#' averaged over rolling windows of 10% of the data.
#'
#' @param df_cv The output from fbprophet.diagnostics.cross_validation.
#' @param metric Metric name, one of 'mse', 'rmse', 'mae', 'mape', 'coverage'.
#' @param rolling_window Proportion of data to use for rolling average of
#'  metric. In [0, 1]. Defaults to 0.1.
#'
#' @return A ggplot2 plot.
#'
#' @export
plot_cross_validation_metric <- function(df_cv, metric, rolling_window=0.1) {
  df_none <- performance_metrics(df_cv, metrics = metric, rolling_window = -1)
  df_h <- performance_metrics(
    df_cv, metrics = metric, rolling_window = rolling_window
  )

  # Better plotting of difftime
  # Target ~10 ticks
  tick_w <- max(as.double(df_none$horizon, units = 'secs')) / 10.
  # Find the largest time resolution that has <1 unit per bin
  dts <- c('days', 'hours', 'mins', 'secs')
  dt_conversions <- c(
    24 * 60 * 60,
    60 * 60,
    60,
    1
  )
  for (i in seq_along(dts)) {
    if (as.difftime(1, units = dts[i]) < as.difftime(tick_w, units = 'secs')) {
      break
    }
  }
  df_none$x_plt <- (
    as.double(df_none$horizon, units = 'secs') / dt_conversions[i]
  )
  df_h$x_plt <- as.double(df_h$horizon, units = 'secs') / dt_conversions[i]

  gg <- (
    ggplot2::ggplot(df_none, ggplot2::aes_string(x = 'x_plt', y = metric)) +
    ggplot2::labs(x = paste0('Horizon (', dts[i], ')'), y = metric) +
    ggplot2::geom_point(color = 'gray') +
    ggplot2::geom_line(
      data = df_h, ggplot2::aes_string(x = 'x_plt', y = metric), color = 'blue'
    ) +
    ggplot2::theme(aspect.ratio = 3 / 5)
  )

  return(gg)
}


================================================
FILE: R/R/prophet.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

## Makes R CMD CHECK happy due to dplyr syntax below
globalVariables(c(
  "ds", "y", "cap", ".",
  "component", "dow", "doy", "holiday", "holidays", "holidays_lower", "generated_holidays",
  "holidays_upper", "ix", "lower", "n", "stat", "trend", "row_number", "extra_regressors", "col",
  "trend_lower", "trend_upper", "upper", "value", "weekly", "weekly_lower", "weekly_upper",
  "x", "yearly", "yearly_lower", "yearly_upper", "yhat", "yhat_lower", "yhat_upper",
  "country", "year"
))

#' Prophet forecaster.
#'
#' @param df (optional) Dataframe containing the history. Must have columns ds
#'   (date type) and y, the time series. If growth is logistic, then df must
#'   also have a column cap that specifies the capacity at each ds. If not
#'   provided, then the model object will be instantiated but not fit; use
#'   fit.prophet(m, df) to fit the model.
#' @param growth String 'linear', 'logistic', or 'flat' to specify a linear,
#'   logistic or flat trend.
#' @param changepoints Vector of dates at which to include potential
#'   changepoints. If not specified, potential changepoints are selected
#'   automatically.
#' @param n.changepoints Number of potential changepoints to include. Not used
#'   if input `changepoints` is supplied. If `changepoints` is not supplied,
#'   then n.changepoints potential changepoints are selected uniformly from the
#'   first `changepoint.range` proportion of df$ds.
#' @param changepoint.range Proportion of history in which trend changepoints
#'   will be estimated. Defaults to 0.8 for the first 80%. Not used if
#'   `changepoints` is specified.
#' @param yearly.seasonality Fit yearly seasonality. Can be 'auto', TRUE, FALSE,
#'   or a number of Fourier terms to generate.
#' @param weekly.seasonality Fit weekly seasonality. Can be 'auto', TRUE, FALSE,
#'   or a number of Fourier terms to generate.
#' @param daily.seasonality Fit daily seasonality. Can be 'auto', TRUE, FALSE,
#'   or a number of Fourier terms to generate.
#' @param holidays data frame with columns holiday (character) and ds (date
#'   type)and optionally columns lower_window and upper_window which specify a
#'   range of days around the date to be included as holidays. lower_window=-2
#'   will include 2 days prior to the date as holidays. Also optionally can have
#'   a column prior_scale specifying the prior scale for each holiday.
#' @param seasonality.mode 'additive' (default) or 'multiplicative'.
#' @param seasonality.prior.scale Parameter modulating the strength of the
#'   seasonality model. Larger values allow the model to fit larger seasonal
#'   fluctuations, smaller values dampen the seasonality. Can be specified for
#'   individual seasonalities using add_seasonality.
#' @param holidays.prior.scale Parameter modulating the strength of the holiday
#'   components model, unless overridden in the holidays input.
#' @param changepoint.prior.scale Parameter modulating the flexibility of the
#'   automatic changepoint selection. Large values will allow many changepoints,
#'   small values will allow few changepoints.
#' @param mcmc.samples Integer, if greater than 0, will do full Bayesian
#'   inference with the specified number of MCMC samples. If 0, will do MAP
#'   estimation.
#' @param interval.width Numeric, width of the uncertainty intervals provided
#'   for the forecast. If mcmc.samples=0, this will be only the uncertainty in
#'   the trend using the MAP estimate of the extrapolated generative model. If
#'   mcmc.samples>0, this will be integrated over all model parameters, which
#'   will include uncertainty in seasonality.
#' @param uncertainty.samples Number of simulated draws used to estimate
#'   uncertainty intervals. Settings this value to 0 or False will disable
#'   uncertainty estimation and speed up the calculation.
#' @param backend Whether to use the "rstan" or "cmdstanr" backend to fit the
#'   model. If not provided, uses the R_STAN_BACKEND environment variable.
#' @param fit Boolean, if FALSE the model is initialized but not fit.
#' @param ... Additional arguments, passed to \code{\link{fit.prophet}}
#'
#' @return A prophet model.
#'
#' @examples
#' \dontrun{
#' history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
#'                       y = sin(1:366/200) + rnorm(366)/10)
#' m <- prophet(history)
#' }
#'
#' @export
#' @importFrom dplyr "%>%"
#' @import Rcpp
#' @rawNamespace import(RcppParallel, except = LdFlags)
#' @import rlang
#' @useDynLib prophet, .registration = TRUE
prophet <- function(df = NULL,
                    growth = 'linear',
                    changepoints = NULL,
                    n.changepoints = 25,
                    changepoint.range = 0.8,
                    yearly.seasonality = 'auto',
                    weekly.seasonality = 'auto',
                    daily.seasonality = 'auto',
                    holidays = NULL,
                    seasonality.mode = 'additive',
                    seasonality.prior.scale = 10,
                    holidays.prior.scale = 10,
                    changepoint.prior.scale = 0.05,
                    mcmc.samples = 0,
                    interval.width = 0.80,
                    uncertainty.samples = 1000,
                    fit = TRUE,
                    backend = NULL,
                    ...
) {
  if (!is.null(changepoints)) {
    n.changepoints <- length(changepoints)
  }

  if (is.null(backend)) backend <- get_stan_backend()

  m <- list(
    growth = growth,
    changepoints = changepoints,
    n.changepoints = n.changepoints,
    changepoint.range = changepoint.range,
    yearly.seasonality = yearly.seasonality,
    weekly.seasonality = weekly.seasonality,
    daily.seasonality = daily.seasonality,
    holidays = holidays,
    seasonality.mode = seasonality.mode,
    seasonality.prior.scale = seasonality.prior.scale,
    changepoint.prior.scale = changepoint.prior.scale,
    holidays.prior.scale = holidays.prior.scale,
    mcmc.samples = mcmc.samples,
    interval.width = interval.width,
    uncertainty.samples = uncertainty.samples,
    backend = backend,
    specified.changepoints = !is.null(changepoints),
    start = NULL,  # This and following attributes are set during fitting
    y.scale = NULL,
    logistic.floor = FALSE,
    t.scale = NULL,
    changepoints.t = NULL,
    seasonalities = list(),
    extra_regressors = list(),
    country_holidays = NULL,
    stan.fit = NULL,
    params = list(),
    history = NULL,
    history.dates = NULL,
    train.holiday.names = NULL,
    train.component.cols = NULL,
    component.modes = NULL,
    fit.kwargs = list()
  )
  m <- validate_inputs(m)
  class(m) <- append("prophet", class(m))
  if ((fit) && (!is.null(df))) {
    m <- fit.prophet(m, df, ...)
  }
  return(m)
}

#' Validates the inputs to Prophet.
#'
#' @param m Prophet object.
#'
#' @return The Prophet object.
#'
#' @keywords internal
validate_inputs <- function(m) {
  if (!(m$growth %in% c('linear', 'logistic', 'flat'))) {
    stop("Parameter 'growth' should be 'linear', 'logistic', or 'flat'.")
  }
  if ((m$changepoint.range < 0) | (m$changepoint.range > 1)) {
    stop("Parameter 'changepoint.range' must be in [0, 1]")
  }
  if (!is.null(m$holidays)) {
    if (!(exists('holiday', where = m$holidays))) {
      stop('Holidays dataframe must have holiday field.')
    }
    if (!(exists('ds', where = m$holidays))) {
      stop('Holidays dataframe must have ds field.')
    }
    m$holidays$ds <- as.Date(m$holidays$ds)
    if (any(is.na(m$holidays$ds)) | any(is.na(m$holidays$holiday))) {
      stop('Found NA in the holidays dataframe.')
    }
    has.lower <- exists('lower_window', where = m$holidays)
    has.upper <- exists('upper_window', where = m$holidays)
    if (has.lower + has.upper == 1) {
      stop(paste('Holidays must have both lower_window and upper_window,',
                 'or neither.'))
    }
    if (has.lower) {
      if(max(m$holidays$lower_window, na.rm=TRUE) > 0) {
        stop('Holiday lower_window should be <= 0')
      }
      if(min(m$holidays$upper_window, na.rm=TRUE) < 0) {
        stop('Holiday upper_window should be >= 0')
      }
    }
    for (h in unique(m$holidays$holiday)) {
      validate_column_name(m, h, check_holidays = FALSE)
    }
  }
  if (!(m$seasonality.mode %in% c('additive', 'multiplicative'))) {
    stop("seasonality.mode must be 'additive' or 'multiplicative'")
  }
  return(m)
}

#' Validates the name of a seasonality, holiday, or regressor.
#'
#' @param m Prophet object.
#' @param name string
#' @param check_holidays bool check if name already used for holiday
#' @param check_seasonalities bool check if name already used for seasonality
#' @param check_regressors bool check if name already used for regressor
#'
#' @keywords internal
validate_column_name <- function(
  m, name, check_holidays = TRUE, check_seasonalities = TRUE,
  check_regressors = TRUE
) {
  if (grepl("_delim_", name)) {
    stop('Holiday name cannot contain "_delim_"')
  }
  reserved_names = c(
    'trend', 'additive_terms', 'daily', 'weekly', 'yearly',
    'holidays', 'zeros', 'extra_regressors_additive', 'yhat',
    'extra_regressors_multiplicative', 'multiplicative_terms'
  )
  rn_l = paste(reserved_names,"_lower",sep="")
  rn_u = paste(reserved_names,"_upper",sep="")
  reserved_names = c(reserved_names, rn_l, rn_u,
    c("ds", "y", "cap", "floor", "y_scaled", "cap_scaled"))
  if(name %in% reserved_names){
    stop("Name ", name, " is reserved.")
  }
  if(check_holidays & !is.null(m$holidays) &
     (name %in% unique(m$holidays$holiday))){
    stop("Name ", name, " already used for a holiday.")
  }
  if(check_holidays & !is.null(m$country_holidays)){
    if(name %in% get_holiday_names(m$country_holidays)){
      stop("Name ", name, " is a holiday name in ", m$country_holidays, ".")
    }
  }
  if(check_seasonalities & (!is.null(m$seasonalities[[name]]))){
    stop("Name ", name, " already used for a seasonality.")
  }
  if(check_regressors & (!is.null(m$seasonalities[[name]]))){
    stop("Name ", name, " already used for an added regressor.")
  }
}

#' Convert date vector
#'
#' Convert the date to POSIXct object. Timezones are stripped and replaced
#' with GMT.
#'
#' @param ds Date vector
#'
#' @return vector of POSIXct object converted from date
#'
#' @keywords internal
set_date <- function(ds) {
  if (length(ds) == 0) {
    return(NULL)
  }

  if (is.factor(ds)) {
    ds <- as.character(ds)
  }

  # If a datetime, strip timezone and replace with GMT.
  if (lubridate::is.instant(ds)) {
    ds <- as.POSIXct(lubridate::force_tz(ds, "GMT"), tz = "GMT")
  }
  else {
    # Assume it can be coerced into POSIXct
    if (min(nchar(ds), na.rm=TRUE) < 12) {
        ds <- as.POSIXct(ds, format = "%Y-%m-%d", tz = "GMT")
    } else {
        ds <- as.POSIXct(ds, format = "%Y-%m-%d %H:%M:%S", tz = "GMT")
    }
  }

  attr(ds, "tzone") <- "GMT"
  return(ds)
}

#' Time difference between datetimes
#'
#' Compute time difference of two POSIXct objects
#'
#' @param ds1 POSIXct object
#' @param ds2 POSIXct object
#' @param units string units of difference, e.g. 'days' or 'secs'.
#'
#' @return numeric time difference
#'
#' @keywords internal
time_diff <- function(ds1, ds2, units = "days") {
  return(as.numeric(difftime(ds1, ds2, units = units)))
}

#' Prepare dataframe for fitting or predicting.
#'
#' Adds a time index and scales y. Creates auxiliary columns 't', 't_ix',
#' 'y_scaled', and 'cap_scaled'. These columns are used during both fitting
#' and predicting.
#'
#' @param m Prophet object.
#' @param df Data frame with columns ds, y, and cap if logistic growth. Any
#'  specified additional regressors must also be present.
#' @param initialize_scales Boolean set scaling factors in m from df.
#'
#' @return list with items 'df' and 'm'.
#'
#' @keywords internal
setup_dataframe <- function(m, df, initialize_scales = FALSE) {
  if (exists('y', where=df)) {
    df$y <- as.numeric(df$y)
    if (any(is.infinite(df$y))) {
      stop("Found infinity in column y.")
    }
  }
  df$ds <- set_date(df$ds)
  if (anyNA(df$ds)) {
    stop(paste('Unable to parse date format in column ds. Convert to date ',
               'format (%Y-%m-%d or %Y-%m-%d %H:%M:%S) and check that there',
               'are no NAs.'))
  }
  for (name in names(m$extra_regressors)) {
    if (!(name %in% colnames(df))) {
      stop('Regressor "', name, '" missing from dataframe')
    }
    df[[name]] <- as.numeric(df[[name]])
    if (anyNA(df[[name]])) {
      stop('Found NaN in column ', name)
    }
  }
  for (name in names(m$seasonalities)) {
    condition.name = m$seasonalities[[name]]$condition.name
    if (!is.null(condition.name)) {
      if (!(condition.name %in% colnames(df))) {
        stop('Condition "', name, '" missing from dataframe')
      }
      if(!all(df[[condition.name]] %in% c(FALSE,TRUE))) {
        stop('Found non-boolean in column ', name)
      }
      df[[condition.name]] <- as.logical(df[[condition.name]])
    }
  }

  df <- df %>%
    dplyr::arrange(ds)

  m <- initialize_scales_fn(m, initialize_scales, df)

  if (m$logistic.floor) {
    if (!('floor' %in% colnames(df))) {
      stop("Expected column 'floor'.")
    }
  } else {
    df$floor <- 0
  }

  if (m$growth == 'logistic') {
    if (!(exists('cap', where=df))) {
      stop('Capacities must be supplied for logistic growth.')
    }
    if (any(df$cap <= df$floor)) {
      stop('cap must be greater than floor (which defaults to 0).')
    }
    df <- df %>%
      dplyr::mutate(cap_scaled = (cap - floor) / m$y.scale)
  }

  df$t <- time_diff(df$ds, m$start, "secs") / m$t.scale
  if (exists('y', where=df)) {
    df$y_scaled <- (df$y - df$floor) / m$y.scale
  }

  for (name in names(m$extra_regressors)) {
    props <- m$extra_regressors[[name]]
    df[[name]] <- (df[[name]] - props$mu) / props$std
  }
  return(list("m" = m, "df" = df))
}

#' Initialize model scales.
#'
#' Sets model scaling factors using df.
#'
#' @param m Prophet object.
#' @param initialize_scales Boolean set the scales or not.
#' @param df Dataframe for setting scales.
#'
#' @return Prophet object with scales set.
#'
#' @keywords internal
initialize_scales_fn <- function(m, initialize_scales, df) {
  if (!initialize_scales) {
    return(m)
  }
  if ((m$growth == 'logistic') && ('floor' %in% colnames(df))) {
    m$logistic.floor <- TRUE
    floor <- df$floor
  } else {
    floor <- 0
  }
  m$y.scale <- max(abs(df$y - floor))
  if (m$y.scale == 0) {
    m$y.scale <- 1
  }
  m$start <- min(df$ds)
  m$t.scale <- time_diff(max(df$ds), m$start, "secs")
  for (name in names(m$extra_regressors)) {
    standardize <- m$extra_regressors[[name]]$standardize
    n.vals <- length(unique(df[[name]]))
    if (n.vals < 2) {
      standardize <- FALSE
    }
    if (standardize == 'auto') {
      if (n.vals == 2 && all(sort(unique(df[[name]])) == c(0, 1))) {
        # Don't standardize binary variables
        standardize <- FALSE
      } else {
        standardize <- TRUE
      }
    }
    if (standardize) {
      mu <- mean(df[[name]])
      std <- stats::sd(df[[name]])
      m$extra_regressors[[name]]$mu <- mu
      m$extra_regressors[[name]]$std <- std
    }
  }
  return(m)
}

#' Set changepoints
#'
#' Sets m$changepoints to the dates of changepoints. Either:
#' 1) The changepoints were passed in explicitly.
#'   A) They are empty.
#'   B) They are not empty, and need validation.
#' 2) We are generating a grid of them.
#' 3) The user prefers no changepoints be used.
#'
#' @param m Prophet object.
#'
#' @return m with changepoints set.
#'
#' @keywords internal
set_changepoints <- function(m) {
  if (!is.null(m$changepoints)) {
    if (length(m$changepoints) > 0) {
      m$changepoints <- set_date(m$changepoints)
      if (min(m$changepoints) < min(m$history$ds)
          || max(m$changepoints) > max(m$history$ds)) {
        stop('Changepoints must fall within training data.')
      }
    }
  } else {
    # Place potential changepoints evenly through the first changepoint.range
    # proportion of the history.
    hist.size <- floor(nrow(m$history) * m$changepoint.range)
    if (m$n.changepoints + 1 > hist.size) {
      m$n.changepoints <- hist.size - 1
      message('n.changepoints greater than number of observations. Using ',
              m$n.changepoints)
    }
    if (m$n.changepoints > 0) {
      cp.indexes <- round(seq.int(1, hist.size,
                                  length.out = (m$n.changepoints + 1))[-1])
      m$changepoints <- m$history$ds[cp.indexes]
    } else {
      m$changepoints <- c()
    }
  }
  if (length(m$changepoints) > 0) {
    m$changepoints.t <- sort(
      time_diff(m$changepoints, m$start, "secs")) / m$t.scale
  } else {
    m$changepoints.t <- c(0)  # dummy changepoint
  }
  return(m)
}

#' Provides Fourier series components with the specified frequency and order.
#'
#' @param dates Vector of dates.
#' @param period Number of days of the period.
#' @param series.order Number of components.
#'
#' @return Matrix with seasonality features.
#'
#' @keywords internal
fourier_series <- function(dates, period, series.order) {
  t <- time_diff(dates, set_date('1970-01-01 00:00:00'))
  features <- matrix(0, length(t), 2 * series.order)
  for (i in 1:series.order) {
    x <- as.numeric(2 * i * pi * t / period)
    features[, i * 2 - 1] <- sin(x)
    features[, i * 2] <- cos(x)
  }
  return(features)
}

#' Data frame with seasonality features.
#'
#' @param dates Vector of dates.
#' @param period Number of days of the period.
#' @param series.order Number of components.
#' @param prefix Column name prefix.
#'
#' @return Dataframe with seasonality.
#'
#' @keywords internal
make_seasonality_features <- function(dates, period, series.order, prefix) {
  features <- fourier_series(dates, period, series.order)
  colnames(features) <- paste(prefix, 1:ncol(features), sep = '_delim_')
  return(data.frame(features))
}

#' Construct a dataframe of holiday dates.
#'
#' @param m Prophet object.
#' @param dates Vector with dates used for computing seasonality.
#'
#' @return A dataframe of holiday dates, in holiday dataframe format used in
#'  initialization.
#'
#' @importFrom dplyr "%>%"
#' @keywords internal
construct_holiday_dataframe <- function(m, dates) {
  all.holidays <- data.frame()
  if (!is.null(m$holidays)){
    all.holidays <- m$holidays
  }
  if (!is.null(m$country_holidays)) {
    year.list <- as.numeric(unique(format(dates, "%Y")))
    country.holidays.df <- make_holidays_df(year.list, m$country_holidays)
    all.holidays <- suppressWarnings(dplyr::bind_rows(all.holidays, country.holidays.df))
  }
  # If the model has already been fit with a certain set of holidays,
  # make sure we are using those same ones.
  if (!is.null(m$train.holiday.names)) {
    row.to.keep <- which(all.holidays$holiday %in% m$train.holiday.names)
    all.holidays <- all.holidays[row.to.keep,]
    holidays.to.add <- data.frame(
      holiday=setdiff(m$train.holiday.names, all.holidays$holiday)
    )
    if (nrow(holidays.to.add) > 0) {
      all.holidays <- suppressWarnings(dplyr::bind_rows(all.holidays, holidays.to.add))
    }
  }
  return(all.holidays)
}

#' Construct a matrix of holiday features.
#'
#' @param m Prophet object.
#' @param dates Vector with dates used for computing seasonality.
#' @param holidays Dataframe containing holidays, as returned by
#'  construct_holiday_dataframe.
#'
#' @return A list with entries
#'  holiday.features: dataframe with a column for each holiday.
#'  prior.scales: array of prior scales for each holiday column.
#'  holiday.names: array of names of all holidays.
#'
#' @importFrom dplyr "%>%"
#' @keywords internal
make_holiday_features <- function(m, dates, holidays) {
  # Strip dates to be just days, for joining on holidays
  dates <- set_date(format(dates, "%Y-%m-%d"))
  wide <- holidays %>%
    dplyr::mutate(ds = set_date(ds)) %>%
    dplyr::group_by(holiday, ds) %>%
    dplyr::filter(dplyr::row_number() == 1) %>%
    dplyr::do({
      if (exists('lower_window', where = .) && !is.na(.$lower_window)
          && !is.na(.$upper_window)) {
        offsets <- seq(.$lower_window, .$upper_window)
      } else {
        offsets <- c(0)
      }
      names <- paste(.$holiday, '_delim_', ifelse(offsets < 0, '-', '+'),
                     abs(offsets), sep = '')
      dplyr::tibble(ds = .$ds + offsets * 24 * 3600, holiday = names)
    }) %>%
    dplyr::mutate(x = 1.) %>%
    tidyr::spread(holiday, x, fill = 0)

  holiday.features <- data.frame(ds = set_date(dates)) %>%
    dplyr::left_join(wide, by = 'ds') %>%
    dplyr::select(-ds)
  # Make sure column order is consistent
  holiday.features <- holiday.features %>% dplyr::select(sort(names(.)))
  holiday.features[is.na(holiday.features)] <- 0

  # Prior scales
  if (!('prior_scale' %in% colnames(holidays))) {
    holidays$prior_scale <- m$holidays.prior.scale
  }
  prior.scales.list <- list()
  for (name in unique(holidays$holiday)) {
    df.h <- holidays[holidays$holiday == name, ]
    ps <- unique(df.h$prior_scale)
    if (length(ps) > 1) {
      stop('Holiday ', name, ' does not have a consistent prior scale ',
           'specification')
    }
    if (is.na(ps)) {
      ps <- m$holidays.prior.scale
    }
    if (ps <= 0) {
      stop('Prior scale must be > 0.')
    }
    prior.scales.list[[name]] <- ps
  }

  prior.scales <- c()
  for (name in colnames(holiday.features)) {
    sn <- strsplit(name, '_delim_', fixed = TRUE)[[1]][1]
    prior.scales <- c(prior.scales, prior.scales.list[[sn]])
  }
  holiday.names <- names(prior.scales.list)
  if (is.null(m$train.holiday.names)){
    m$train.holiday.names <- holiday.names
  }
  return(list(m = m,
              holiday.features = holiday.features,
              prior.scales = prior.scales,
              holiday.names = holiday.names))
}

#' Add an additional regressor to be used for fitting and predicting.
#'
#' The dataframe passed to `fit` and `predict` will have a column with the
#' specified name to be used as a regressor. When standardize='auto', the
#' regressor will be standardized unless it is binary. The regression
#' coefficient is given a prior with the specified scale parameter.
#' Decreasing the prior scale will add additional regularization. If no
#' prior scale is provided, holidays.prior.scale will be used.
#' Mode can be specified as either 'additive' or 'multiplicative'. If not
#' specified, m$seasonality.mode will be used. 'additive' means the effect of
#' the regressor will be added to the trend, 'multiplicative' means it will
#' multiply the trend.
#'
#' @param m Prophet object.
#' @param name String name of the regressor
#' @param prior.scale Float scale for the normal prior. If not provided,
#'  holidays.prior.scale will be used.
#' @param standardize Bool, specify whether this regressor will be standardized
#'  prior to fitting. Can be 'auto' (standardize if not binary), True, or
#'  False.
#' @param mode Optional, 'additive' or 'multiplicative'. Defaults to
#'  m$seasonality.mode.
#'
#' @return  The prophet model with the regressor added.
#'
#' @export
add_regressor <- function(
  m, name, prior.scale = NULL, standardize = 'auto', mode = NULL
){
  if (!is.null(m$history)) {
    stop('Regressors must be added prior to model fitting.')
  }
  if (make.names(name, allow_ = TRUE) != name) {
    stop("You have provided a name that is not syntactically valid in R, ", name, ". ",
         "A syntactically valid name consists of letters, numbers and the dot or underline, ",
         "characters and starts with a letter or the dot not followed by a number.")
  }
  validate_column_name(m, name, check_regressors = FALSE)
  if (is.null(prior.scale)) {
    prior.scale <- m$holidays.prior.scale
  }
  if (is.null(mode)) {
    mode <- m$seasonality.mode
  }
  if(prior.scale <= 0) {
    stop("Prior scale must be > 0.")
  }
  if (!(mode %in% c('additive', 'multiplicative'))) {
    stop("mode must be 'additive' or 'multiplicative'")
  }
  m$extra_regressors[[name]] <- list(
    prior.scale = prior.scale,
    standardize = standardize,
    mu = 0,
    std = 1.0,
    mode = mode
  )
  return(m)
}

#' Add a seasonal component with specified period, number of Fourier
#' components, and prior scale.
#'
#' Increasing the number of Fourier components allows the seasonality to change
#' more quickly (at risk of overfitting). Default values for yearly and weekly
#' seasonalities are 10 and 3 respectively.
#'
#' Increasing prior scale will allow this seasonality component more
#' flexibility, decreasing will dampen it. If not provided, will use the
#' seasonality.prior.scale provided on Prophet initialization (defaults to 10).
#'
#' Mode can be specified as either 'additive' or 'multiplicative'. If not
#' specified, m$seasonality.mode will be used (defaults to 'additive').
#' Additive means the seasonality will be added to the trend, multiplicative
#' means it will multiply the trend.
#'
#' If condition.name is provided, the dataframe passed to `fit` and `predict`
#' should have a column with the specified condition.name containing booleans
#' which decides when to apply seasonality.
#'
#' @param m Prophet object.
#' @param name String name of the seasonality component.
#' @param period Float number of days in one period.
#' @param fourier.order Int number of Fourier components to use.
#' @param prior.scale Optional float prior scale for this component.
#' @param mode Optional 'additive' or 'multiplicative'.
#' @param condition.name String name of the seasonality condition.
#'
#' @return The prophet model with the seasonality added.
#'
#' @export
add_seasonality <- function(
  m, name, period, fourier.order, prior.scale = NULL, mode = NULL,
  condition.name = NULL
) {
  if (!is.null(m$history)) {
    stop("Seasonality must be added prior to model fitting.")
  }
  if (!(name %in% c('daily', 'weekly', 'yearly'))) {
    # Allow overriding built-in seasonalities
    if (make.names(name, allow_ = TRUE) != name) {
      stop("You have provided a name that is not syntactically valid in R, ", name, ". ",
           "A syntactically valid name consists of letters, numbers and the dot or underline, ",
           "characters and starts with a letter or the dot not followed by a number.")
    }
    validate_column_name(m, name, check_seasonalities = FALSE)
  }
  if (is.null(prior.scale)) {
    ps <- m$seasonality.prior.scale
  } else {
    ps <- prior.scale
  }
  if (ps <= 0) {
    stop('Prior scale must be > 0.')
  }
  if (fourier.order <= 0) {
    stop('Fourier order must be > 0.')
  }
  if (is.null(mode)) {
    mode <- m$seasonality.mode
  }
  if (!(mode %in% c('additive', 'multiplicative'))) {
    stop("mode must be 'additive' or 'multiplicative'")
  }
  if (!is.null(condition.name)) {
    validate_column_name(m, condition.name)
  }
  m$seasonalities[[name]] <- list(
    period = period,
    fourier.order = fourier.order,
    prior.scale = ps,
    mode = mode,
    condition.name = condition.name
  )
  return(m)
}

#' Add in built-in holidays for the specified country.
#'
#' These holidays will be included in addition to any specified on model
#' initialization.
#'
#' Holidays will be calculated for arbitrary date ranges in the history
#' and future. See the online documentation for the list of countries with
#' built-in holidays.
#'
#' Built-in country holidays can only be set for a single country.
#'
#' @param m Prophet object.
#' @param country_name Name of the country, like 'UnitedStates' or 'US'
#'
#' @return The prophet model with the holidays country set.
#'
#' @export
add_country_holidays <- function(m, country_name) {
  if (!is.null(m$history)) {
    stop("Country holidays must be added prior to model fitting.")
  }
  if (!(country_name %in% generated_holidays$country)){
      stop("Holidays in ", country_name," are not currently supported!")
    }
  # Validate names.
  for (name in get_holiday_names(country_name)) {
    # Allow merging with existing holidays
    validate_column_name(m, name, check_holidays = FALSE)
  }
  # Set the holidays.
  if (!is.null(m$country_holidays)) {
    message(
      'Changing country holidays from ', m$country_holidays, ' to ',
      country_name
    )
  }
  m$country_holidays = country_name
  return(m)
}

#' Dataframe with seasonality features.
#' Includes seasonality features, holiday features, and added regressors.
#'
#' @param m Prophet object.
#' @param df Dataframe with dates for computing seasonality features and any
#'  added regressors.
#'
#' @return List with items
#'  seasonal.features: Dataframe with regressor features,
#'  prior.scales: Array of prior scales for each column of the features
#'    dataframe.
#'  component.cols: Dataframe with indicators for which regression components
#'    correspond to which columns.
#'  modes: List with keys 'additive' and 'multiplicative' with arrays of
#'    component names for each mode of seasonality.
#'
#' @keywords internal
make_all_seasonality_features <- function(m, df) {
  seasonal.features <- data.frame(row.names = 1:nrow(df))
  prior.scales <- c()
  modes <- list(additive = c(), multiplicative = c())

  # Seasonality features
  for (name in names(m$seasonalities)) {
    props <- m$seasonalities[[name]]
    features <- make_seasonality_features(
      df$ds, props$period, props$fourier.order, name)
    if (!is.null(props$condition.name)) {
      features[!df[[props$condition.name]],] <- 0
    }
    seasonal.features <- cbind(seasonal.features, features)
    prior.scales <- c(prior.scales,
                      props$prior.scale * rep(1, ncol(features)))
    modes[[props$mode]] <- c(modes[[props$mode]], name)
  }

  # Holiday features
  holidays <- construct_holiday_dataframe(m, df$ds)
  if (nrow(holidays) > 0) {
    out <- make_holiday_features(m, df$ds, holidays)
    m <- out$m
    seasonal.features <- cbind(seasonal.features, out$holiday.features)
    prior.scales <- c(prior.scales, out$prior.scales)
    modes[[m$seasonality.mode]] <- c(
      modes[[m$seasonality.mode]], out$holiday.names
    )
  }

  # Additional regressors
  for (name in names(m$extra_regressors)) {
    props <- m$extra_regressors[[name]]
    seasonal.features[[name]] <- df[[name]]
    prior.scales <- c(prior.scales, props$prior.scale)
    modes[[props$mode]] <- c(modes[[props$mode]], name)
  }

  # Dummy to prevent empty X
  if (ncol(seasonal.features) == 0) {
    seasonal.features <- data.frame(zeros = rep(0, nrow(df)))
    prior.scales <- c(1.)
  }

  components.list <- regressor_column_matrix(m, seasonal.features, modes)
  return(list(m = m,
              seasonal.features = seasonal.features,
              prior.scales = prior.scales,
              component.cols = components.list$component.cols,
              modes = components.list$modes))
}

#' Dataframe indicating which columns of the feature matrix correspond to
#' which seasonality/regressor components.
#'
#' Includes combination components, like 'additive_terms'. These combination
#' components will be added to the 'modes' input.
#'
#' @param m Prophet object.
#' @param seasonal.features Constructed seasonal features dataframe.
#' @param modes List with keys 'additive' and 'multiplicative' with arrays of
#'  component names for each mode of seasonality.
#'
#' @return List with items
#'  component.cols: A binary indicator dataframe with columns seasonal
#'    components and rows columns in seasonal.features. Entry is 1 if that
#'    column is used in that component.
#'  modes: Updated input with combination components.
#'
#' @keywords internal
regressor_column_matrix <- function(m, seasonal.features, modes) {
  components <- dplyr::tibble(component = colnames(seasonal.features)) %>%
    dplyr::mutate(col = seq_len(dplyr::n())) %>%
    tidyr::separate(component, c('component', 'part'), sep = "_delim_",
                    extra = "merge", fill = "right") %>%
    dplyr::select(col, component)
  # Add total for holidays
  if(!is.null(m$train.holiday.names)){
    components <- add_group_component(
      components, 'holidays', unique(m$train.holiday.names))
  }
  # Add totals for additive and multiplicative components, and regressors
  for (mode in c('additive', 'multiplicative')) {
    components <- add_group_component(
      components, paste0(mode, '_terms'), modes[[mode]])
    regressors_by_mode <- c()
    for (name in names(m$extra_regressors)) {
      if (m$extra_regressors[[name]]$mode == mode) {
        regressors_by_mode <- c(regressors_by_mode, name)
      }
    }
    components <- add_group_component(
      components, paste0('extra_regressors_', mode), regressors_by_mode)
    # Add combination components to modes
    modes[[mode]] <- c(modes[[mode]], paste0(mode, '_terms'))
    modes[[mode]] <- c(modes[[mode]], paste0('extra_regressors_', mode))
  }
  # After all of the additive/multiplicative groups have been added,
  modes[[m$seasonality.mode]] <- c(modes[[m$seasonality.mode]], 'holidays')
  # Convert to a binary matrix
  component.cols <- as.data.frame.matrix(
    table(components$col, components$component)
  )
  component.cols <- (
    component.cols[order(as.numeric(row.names(component.cols))), ,
                   drop = FALSE]
  )
  # Add columns for additive and multiplicative terms, if missing
  for (name in c('additive_terms', 'multiplicative_terms')) {
    if (!(name %in% colnames(component.cols))) {
      component.cols[[name]] <- 0
    }
  }
  # Remove the placeholder
  components <- dplyr::filter(components, component != 'zeros')
  # Validation
  if (
    max(component.cols$additive_terms
    + component.cols$multiplicative_terms) > 1
  ) {
    stop('A bug occurred in seasonal components.')
  }
  # Compare to training, if set.
  if (!is.null(m$train.component.cols)) {
    component.cols <- component.cols[, colnames(m$train.component.cols)]
    if (!all(component.cols == m$train.component.cols)) {
      stop('A bug occurred in constructing regressors.')
    }
  }
  return(list(component.cols = component.cols, modes = modes))
}

#' Adds a component with given name that contains all of the components
#' in group.
#'
#' @param components Dataframe with components.
#' @param name Name of new group component.
#' @param group  List of components that form the group.
#'
#' @return Dataframe with components.
#'
#' @keywords internal
add_group_component <- function(components, name, group) {
  new_comp <- components[(components$component %in% group), ]
  group_cols <- unique(new_comp$col)
  if (length(group_cols) > 0) {
    new_comp <- data.frame(col=group_cols, component=name)
    components <- rbind(components, new_comp)
  }
  return(components)
}

#' Get number of Fourier components for built-in seasonalities.
#'
#' @param m Prophet object.
#' @param name String name of the seasonality component.
#' @param arg 'auto', TRUE, FALSE, or number of Fourier components as
#'  provided.
#' @param auto.disable Bool if seasonality should be disabled when 'auto'.
#' @param default.order Int default Fourier order.
#'
#' @return Number of Fourier components, or 0 for disabled.
#'
#' @keywords internal
parse_seasonality_args <- function(m, name, arg, auto.disable, default.order) {
  if (arg == 'auto') {
    fourier.order <- 0
    if (name %in% names(m$seasonalities)) {
      message('Found custom seasonality named "', name,
              '", disabling built-in ', name, ' seasonality.')
    } else if (auto.disable) {
      message('Disabling ', name, ' seasonality. Run prophet with ', name,
              '.seasonality=TRUE to override this.')
    } else {
      fourier.order <- default.order
    }
  } else if (isTRUE(arg)) {
    fourier.order <- default.order
  } else if (isFALSE(arg)) {
    fourier.order <- 0
  } else {
    fourier.order <- arg
  }
  return(fourier.order)
}

#' Set seasonalities that were left on auto.
#'
#' Turns on yearly seasonality if there is >=2 years of history.
#' Turns on weekly seasonality if there is >=2 weeks of history, and the
#' spacing between dates in the history is <7 days.
#' Turns on daily seasonality if there is >=2 days of history, and the spacing
#' between dates in the history is <1 day.
#'
#' @param m Prophet object.
#'
#' @return The prophet model with seasonalities set.
#'
#' @keywords internal
set_auto_seasonalities <- function(m) {
  first <- min(m$history$ds)
  last <- max(m$history$ds)
  dt <- diff(time_diff(m$history$ds, m$start))
  min.dt <- min(dt[dt > 0])

  yearly.disable <- time_diff(last, first) < 730
  fourier.order <- parse_seasonality_args(
    m, 'yearly', m$yearly.seasonality, yearly.disable, 10)
  if (fourier.order > 0) {
    m$seasonalities[['yearly']] <- list(
      period = 365.25,
      fourier.order = fourier.order,
      prior.scale = m$seasonality.prior.scale,
      mode = m$seasonality.mode,
      condition.name = NULL
    )
  }

  weekly.disable <- ((time_diff(last, first) < 14) || (min.dt >= 7))
  fourier.order <- parse_seasonality_args(
    m, 'weekly', m$weekly.seasonality, weekly.disable, 3)
  if (fourier.order > 0) {
    m$seasonalities[['weekly']] <- list(
      period = 7,
      fourier.order = fourier.order,
      prior.scale = m$seasonality.prior.scale,
      mode = m$seasonality.mode,
      condition.name = NULL
    )
  }

  daily.disable <- ((time_diff(last, first) < 2) || (min.dt >= 1))
  fourier.order <- parse_seasonality_args(
    m, 'daily', m$daily.seasonality, daily.disable, 4)
  if (fourier.order > 0) {
    m$seasonalities[['daily']] <- list(
      period = 1,
      fourier.order = fourier.order,
      prior.scale = m$seasonality.prior.scale,
      mode = m$seasonality.mode,
      condition.name = NULL
    )
  }
  return(m)
}

#' Initialize flat growth.
#'
#' Provides a strong initialization for flat growth by setting the
#' growth to 0 and calculates the offset parameter that pass the
#' function through the mean of the the y_scaled values.
#'
#' @param df Data frame with columns ds (date), y_scaled (scaled time series),
#'  and t (scaled time).
#'
#' @return A vector (k, m) with the rate (k) and offset (m) of the flat
#'  growth function.
#'
#' @keywords internal
flat_growth_init <- function(df) {
  # Initialize the rate
  k <- 0
  # And the offset
  m <- mean(df$y_scaled)
  return(c(k, m))
}

#' Initialize constant growth.
#'
#' Provides a strong initialization for linear growth by calculating the
#' growth and offset parameters that pass the function through the first and
#' last points in the time series.
#'
#' @param df Data frame with columns ds (date), y_scaled (scaled time series),
#'  and t (scaled time).
#'
#' @return A vector (k, m) with the rate (k) and offset (m) of the linear
#'  growth function.
#'
#' @keywords internal
linear_growth_init <- function(df) {
  i0 <- which.min(df$ds)
  i1 <- which.max(df$ds)
  T <- df$t[i1] - df$t[i0]
  # Initialize the rate
  k <- (df$y_scaled[i1] - df$y_scaled[i0]) / T
  # And the offset
  m <- df$y_scaled[i0] - k * df$t[i0]
  return(c(k, m))
}

#' Initialize logistic growth.
#'
#' Provides a strong initialization for logistic growth by calculating the
#' growth and offset parameters that pass the function through the first and
#' last points in the time series.
#'
#' @param df Data frame with columns ds (date), cap_scaled (scaled capacity),
#'  y_scaled (scaled time series), and t (scaled time).
#'
#' @return A vector (k, m) with the rate (k) and offset (m) of the logistic
#'  growth function.
#'
#' @keywords internal
logistic_growth_init <- function(df) {
  i0 <- which.min(df$ds)
  i1 <- which.max(df$ds)
  T <- df$t[i1] - df$t[i0]

  # Force valid values, in case y > cap or y < 0
  C0 <- df$cap_scaled[i0]
  C1 <- df$cap_scaled[i1]
  y0 <- max(0.01 * C0, min(0.99 * C0, df$y_scaled[i0]))
  y1 <- max(0.01 * C1, min(0.99 * C1, df$y_scaled[i1]))

  r0 <- C0 / y0
  r1 <- C1 / y1

  if (abs(r0 - r1) <= 0.01) {
    r0 <- 1.05 * r0
  }
  L0 <- log(r0 - 1)
  L1 <- log(r1 - 1)
  # Initialize the offset
  m <- L0 * T / (L0 - L1)
  # And the rate
  k <- (L0 - L1) / T
  return(c(k, m))
}

#' Fit the prophet model.
#'
#' This sets m$params to contain the fitted model parameters. It is a list
#' with the following elements:
#'   k (M array): M posterior samples of the initial slope.
#'   m (M array): The initial intercept.
#'   delta (MxN matrix): The slope change at each of N changepoints.
#'   beta (MxK matrix): Coefficients for K seasonality features.
#'   sigma_obs (M array): Noise level.
#' Note that M=1 if MAP estimation.
#'
#' @param m Prophet object.
#' @param df Data frame.
#' @param ... Additional arguments passed to the \code{optimizing} or
#'  \code{sampling} functions in Stan.
#'
#' @export
fit.prophet <- function(m, df, ...) {
  if (!is.null(m$history)) {
    stop("Prophet object can only be fit once. Instantiate a new object.")
  }
  if (!(exists('ds', where = df)) | !(exists('y', where = df))) {
    stop(paste(
      "Dataframe must have columns 'ds' and 'y' with the dates and values",
      "respectively."
    ))
  }
  history <- df %>%
    dplyr::filter(!is.na(y))
  if (nrow(history) < 2) {
    stop("Dataframe has less than 2 non-NA rows.")
  }
  m$history.dates <- sort(set_date(unique(df$ds)))

  out <- setup_dataframe(m, history, initialize_scales = TRUE)
  history <- out$df
  m <- out$m
  m$history <- history
  m <- set_auto_seasonalities(m)
  out2 <- make_all_seasonality_features(m, history)
  m <- out2$m
  seasonal.features <- out2$seasonal.features
  prior.scales <- out2$prior.scales
  component.cols <- out2$component.cols
  m$train.component.cols <- component.cols
  m$component.modes <- out2$modes
  m$fit.kwargs <- list(...)

  m <- set_changepoints(m)

  # Construct input to stan
  dat <- list(
    T = nrow(history),
    K = ncol(seasonal.features),
    S = length(m$changepoints.t),
    y = history$y_scaled,
    t = history$t,
    t_change = array(m$changepoints.t),
    X = as.matrix(seasonal.features),
    sigmas = array(prior.scales),
    tau = m$changepoint.prior.scale,
    trend_indicator = switch(m$growth, 'linear'=0, 'logistic'=1, 'flat'=2),
    s_a = array(component.cols$additive_terms),
    s_m = array(component.cols$multiplicative_terms)
  )

  # Run stan
  if (m$growth == 'linear') {
    dat$cap <- rep(0, nrow(history))  # Unused inside Stan
    kinit <- linear_growth_init(history)
  } else if (m$growth == 'flat') {
    dat$cap <- rep(0, nrow(history)) # Unused inside Stan
    kinit <- flat_growth_init(history)
  } else if (m$growth == 'logistic') {
    dat$cap <- history$cap_scaled  # Add capacities to the Stan data
    kinit <- logistic_growth_init(history)
  }

  model <- .load_model(m$backend)

  stan_init <- function() {
    list(k = kinit[1],
         m = kinit[2],
         delta = array(rep(0, length(m$changepoints.t))),
         beta = array(rep(0, ncol(seasonal.features))),
         sigma_obs = 1
    )
  }

  if (min(history$y) == max(history$y) &
        (m$growth %in% c('linear', 'flat'))) {
    # Nothing to fit.
    m$params <- stan_init()
    m$params$sigma_obs <- 0.
    n.iteration <- 1.
  } else {
    if (m$mcmc.samples > 0) {
      args <- .stan_args(model, dat, stan_init, m$backend, type = "mcmc", m$mcmc.samples, ...)
      model_output <- .sampling(args, m$backend)
    } else {
      args <- .stan_args(model, dat, stan_init, m$backend, type = "optimize", ...)
      model_output <- .fit(args, m$backend)
    }
    m$stan.fit <- model_output$stan_fit
    m$params <- model_output$params
    n.iteration <- model_output$n_iteration
  }
  # Cast the parameters to have consistent form, whether full bayes or MAP
  for (name in c('delta', 'beta')){
    m$params[[name]] <- matrix(m$params[[name]], nrow = n.iteration)
  }
  # rstan::sampling returns 1d arrays; converts to atomic vectors.
  for (name in c('k', 'm', 'sigma_obs')){
    m$params[[name]] <- c(m$params[[name]])
  }
  # If no changepoints were requested, replace delta with 0s
  if (m$n.changepoints == 0) {
    # Fold delta into the base rate k
    m$params$k <- m$params$k + m$params$delta[, 1]
    m$params$delta <- matrix(rep(0, length(m$params$delta)), nrow = n.iteration)
  }
  return(m)
}

#' Predict using the prophet model.
#'
#' @param object Prophet object.
#' @param df Dataframe with dates for predictions (column ds), and capacity
#'  (column cap) if logistic growth. If not provided, predictions are made on
#'  the history.
#' @param ... additional arguments.
#'
#' @return A dataframe with the forecast components.
#'
#' @examples
#' \dontrun{
#' history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
#'                       y = sin(1:366/200) + rnorm(366)/10)
#' m <- prophet(history)
#' future <- make_future_dataframe(m, periods = 365)
#' forecast <- predict(m, future)
#' plot(m, forecast)
#' }
#'
#' @export
predict.prophet <- function(object, df = NULL, ...) {
  if (is.null(object$history)) {
    stop("Model must be fit before predictions can be made.")
  }
  if (is.null(df)) {
    df <- object$history
  } else {
    if (nrow(df) == 0) {
      stop("Dataframe has no rows.")
    }
    out <- setup_dataframe(object, df)
    df <- out$df
  }

  df$trend <- predict_trend(object, df)
  seasonal.components <- predict_seasonal_components(object, df)
  if (object$uncertainty.samples) {
    intervals <- predict_uncertainty(object, df)
  } else {
    intervals <- NULL
    }

  # Drop columns except ds, cap, floor, and trend
  cols <- c('ds', 'trend')
  if ('cap' %in% colnames(df)) {
    cols <- c(cols, 'cap')
  }
  if (object$logistic.floor) {
    cols <- c(cols, 'floor')
  }
  df <- df[cols]
  df <- dplyr::bind_cols(df, seasonal.components, intervals)
  df$yhat <- df$trend * (1 + df$multiplicative_terms) + df$additive_terms
  return(df)
}

#' Evaluate the flat trend function.
#'
#' @param t Vector of times on which the function is evaluated.
#' @param m Float initial offset.
#'
#' @return Vector y(t).
#'
#' @keywords internal
flat_trend <- function(t, m) {
  y <- rep(m, length(t))
  return(y)
}

#' Evaluate the piecewise linear function.
#'
#' @param t Vector of times on which the function is evaluated.
#' @param deltas Vector of rate changes at each changepoint.
#' @param k Float initial rate.
#' @param m Float initial offset.
#' @param changepoint.ts Vector of changepoint times.
#'
#' @return Vector y(t).
#'
#' @keywords internal
piecewise_linear <- function(t, deltas, k, m, changepoint.ts) {
  # Intercept changes
  gammas <- -changepoint.ts * deltas
  # Get cumulative slope and intercept at each t
  k_t <- rep(k, length(t))
  m_t <- rep(m, length(t))
  for (s in 1:length(changepoint.ts)) {
    indx <- t >= changepoint.ts[s]
    k_t[indx] <- k_t[indx] + deltas[s]
    m_t[indx] <- m_t[indx] + gammas[s]
  }
  y <- k_t * t + m_t
  return(y)
}

#' Evaluate the piecewise logistic function.
#'
#' @param t Vector of times on which the function is evaluated.
#' @param cap Vector of capacities at each t.
#' @param deltas Vector of rate changes at each changepoint.
#' @param k Float initial rate.
#' @param m Float initial offset.
#' @param changepoint.ts Vector of changepoint times.
#'
#' @return Vector y(t).
#'
#' @keywords internal
piecewise_logistic <- function(t, cap, deltas, k, m, changepoint.ts) {
  # Compute offset changes
  k.cum <- c(k, cumsum(deltas) + k)
  gammas <- rep(0, length(changepoint.ts))
  for (i in 1:length(changepoint.ts)) {
    gammas[i] <- ((changepoint.ts[i] - m - sum(gammas))
                  * (1 - k.cum[i] / k.cum[i + 1]))
  }
  # Get cumulative rate and offset at each t
  k_t <- rep(k, length(t))
  m_t <- rep(m, length(t))
  for (s in 1:length(changepoint.ts)) {
    indx <- t >= changepoint.ts[s]
    k_t[indx] <- k_t[indx] + deltas[s]
    m_t[indx] <- m_t[indx] + gammas[s]
  }
  y <- cap / (1 + exp(-k_t * (t - m_t)))
  return(y)
}

#' Predict trend using the prophet model.
#'
#' @param model Prophet object.
#' @param df Prediction dataframe.
#'
#' @return Vector with trend on prediction dates.
#'
#' @keywords internal
predict_trend <- function(model, df) {
  k <- mean(model$params$k, na.rm = TRUE)
  param.m <- mean(model$params$m, na.rm = TRUE)
  deltas <- colMeans(model$params$delta, na.rm = TRUE)

  t <- df$t
  if (model$growth == 'linear') {
    trend <- piecewise_linear(t, deltas, k, param.m, model$changepoints.t)
  } else if (model$growth == 'flat') {
     trend <- flat_trend(t, param.m)
  } else if (model$growth == 'logistic') {
    cap <- df$cap_scaled
    trend <- piecewise_logistic(
      t, cap, deltas, k, param.m, model$changepoints.t)
  }
  return(trend * model$y.scale + df$floor)
}

#' Predict seasonality components, holidays, and added regressors.
#'
#' @param m Prophet object.
#' @param df Prediction dataframe.
#'
#' @return Dataframe with seasonal components.
#'
#' @keywords internal
predict_seasonal_components <- function(m, df) {
  out <- make_all_seasonality_features(m, df)
  m <- out$m
  seasonal.features <- out$seasonal.features
  component.cols <- out$component.cols
  if (m$uncertainty.samples){
    lower.p <- (1 - m$interval.width)/2
    upper.p <- (1 + m$interval.width)/2
  }

  X <- as.matrix(seasonal.features)
  component.predictions <- data.frame(matrix(ncol = 0, nrow = nrow(X)))
  for (component in colnames(component.cols)) {
    beta.c <- t(m$params$beta) * component.cols[[component]]

    comp <- X %*% beta.c
    if (component %in% m$component.modes$additive) {
      comp <- comp * m$y.scale
    }
    component.predictions[[component]] <- rowMeans(comp, na.rm = TRUE)
    if (m$uncertainty.samples){
      component.predictions[[paste0(component, '_lower')]] <- apply(
        comp, 1, stats::quantile, lower.p, na.rm = TRUE)
      component.predictions[[paste0(component, '_upper')]] <- apply(
        comp, 1, stats::quantile, upper.p, na.rm = TRUE)
    }
  }
  return(component.predictions)
}

#' Prophet posterior predictive samples.
#'
#' @param m Prophet object.
#' @param df Prediction dataframe.
#'
#' @return List with posterior predictive samples for the forecast yhat and
#'  for the trend component.
#'
#' @keywords internal
sample_posterior_predictive <- function(m, df) {
  # Sample trend, seasonality, and yhat from the extrapolation model.
  n.iterations <- length(m$params$k)
  samp.per.iter <- max(1, ceiling(m$uncertainty.samples / n.iterations))
  nsamp <- n.iterations * samp.per.iter  # The actual number of samples

  out <- make_all_seasonality_features(m, df)
  seasonal.features <- out$seasonal.features
  component.cols <- out$component.cols
  sim.values <- list("trend" = matrix(, nrow = nrow(df), ncol = nsamp),
                     "yhat" = matrix(, nrow = nrow(df), ncol = nsamp))

  for (i in 1:n.iterations) {
    # For each set of parameters from MCMC (or just 1 set for MAP),
    for (j in 1:samp.per.iter) {
      # Do a simulation with this set of parameters,
      sim <- sample_model(
        m = m,
        df = df,
        seasonal.features = seasonal.features,
        iteration = i,
        s_a = component.cols$additive_terms,
        s_m = component.cols$multiplicative_terms
      )
      # Store the results
      for (key in c("trend", "yhat")) {
        sim.values[[key]][,(i - 1) * samp.per.iter + j] <- sim[[key]]
      }
    }
  }
  return(sim.values)
}

#' Sample from the posterior predictive distribution.
#'
#' @param m Prophet object.
#' @param df Dataframe with dates for predictions (column ds), and capacity
#'  (column cap) if logistic growth.
#'
#' @return A list with items "trend" and "yhat" containing
#'  posterior predictive samples for that component.
#'
#' @export
predictive_samples <- function(m, df) {
  df <- setup_dataframe(m, df)$df
  sim.values <- sample_posterior_predictive(m, df)
  return(sim.values)
}

#' Prophet uncertainty intervals for yhat and trend
#'
#' @param m Prophet object.
#' @param df Prediction dataframe.
#'
#' @return Dataframe with uncertainty intervals.
#'
#' @keywords internal
predict_uncertainty <- function(m, df) {
  sim.values <- sample_posterior_predictive(m, df)
  # Add uncertainty estimates
  lower.p <- (1 - m$interval.width)/2
  upper.p <- (1 + m$interval.width)/2

  intervals <- cbind(
    t(apply(t(sim.values$yhat), 2, stats::quantile, c(lower.p, upper.p),
            na.rm = TRUE)),
    t(apply(t(sim.values$trend), 2, stats::quantile, c(lower.p, upper.p),
            na.rm = TRUE))
  )

  colnames(intervals) <- paste(rep(c('yhat', 'trend'), each=2),
                               c('lower', 'upper'), sep = "_")

  return(dplyr::as_tibble(intervals))
}

#' Simulate observations from the extrapolated generative model.
#'
#' @param m Prophet object.
#' @param df Prediction dataframe.
#' @param seasonal.features Data frame of seasonal features
#' @param iteration Int sampling iteration to use parameters from.
#' @param s_a Indicator vector for additive components
#' @param s_m Indicator vector for multiplicative components
#'
#' @return List of trend and yhat, each a vector like df$t.
#'
#' @keywords internal
sample_model <- function(m, df, seasonal.features, iteration, s_a, s_m) {
  trend <- sample_predictive_trend(m, df, iteration)

  beta <- m$params$beta[iteration,]
  Xb_a = as.matrix(seasonal.features) %*% (beta * s_a) * m$y.scale
  Xb_m = as.matrix(seasonal.features) %*% (beta * s_m)

  sigma <- m$params$sigma_obs[iteration]
  noise <- stats::rnorm(nrow(df), mean = 0, sd = sigma) * m$y.scale

  return(list("yhat" = trend * (1 + Xb_m) + Xb_a + noise,
              "trend" = trend))
}

#' Simulate the trend using the extrapolated generative model.
#'
#' @param model Prophet object.
#' @param df Prediction dataframe.
#' @param iteration Int sampling iteration to use parameters from.
#'
#' @return Vector of simulated trend over df$t.
#'
#' @keywords internal
sample_predictive_trend <- function(model, df, iteration) {
  k <- model$params$k[iteration]
  param.m <- model$params$m[iteration]
  deltas <- model$params$delta[iteration,]

  t <- df$t
  T <- max(t)

  # New changepoints from a Poisson process with rate S on [1, T]
  if (T > 1) {
    S <- length(model$changepoints.t)
    n.changes <- stats::rpois(1, S * (T - 1))
  } else {
    n.changes <- 0
  }
  if (n.changes > 0) {
    changepoint.ts.new <- 1 + stats::runif(n.changes) * (T - 1)
    changepoint.ts.new <- sort(changepoint.ts.new)
  } else {
    changepoint.ts.new <- c()
  }

  # Get the empirical scale of the deltas, plus epsilon to avoid NaNs.
  lambda <- mean(abs(c(deltas))) + 1e-8
  # Sample deltas
  deltas.new <- extraDistr::rlaplace(n.changes, mu = 0, sigma = lambda)

  # Combine with changepoints from the history
  changepoint.ts <- c(model$changepoints.t, changepoint.ts.new)
  deltas <- c(deltas, deltas.new)

  # Get the corresponding trend
  if (model$growth == 'linear') {
    trend <- piecewise_linear(t, deltas, k, param.m, changepoint.ts)
  } else if (model$growth == 'flat') {
    trend <- flat_trend(t, param.m)
  } else if (model$growth == 'logistic') {
    cap <- df$cap_scaled
    trend <- piecewise_logistic(t, cap, deltas, k, param.m, changepoint.ts)
  }
  return(trend * model$y.scale + df$floor)
}

#' Make dataframe with future dates for forecasting.
#'
#' @param m Prophet model object.
#' @param periods Int number of periods to forecast forward.
#' @param freq 'day', 'week', 'month', 'quarter', 'year', 1(1 sec), 60(1 minute) or 3600(1 hour).
#' @param include_history Boolean to include the historical dates in the data
#'  frame for predictions.
#'
#' @return Dataframe that extends forward from the end of m$history for the
#'  requested number of periods.
#'
#' @export
make_future_dataframe <- function(m, periods, freq = 'day',
                                  include_history = TRUE) {
  # For backwards compatibility with previous zoo date type,
  if (freq == 'm') {
    freq <- 'month'
  }
  if (is.null(m$history.dates)) {
    stop('Model must be fit before this can be used.')
  }
  dates <- seq(max(m$history.dates), length.out = periods + 1, by = freq)
  dates <- dates[2:(periods + 1)]  # Drop the first, which is max(history$ds)
  if (include_history) {
    dates <- c(m$history.dates, dates)
    attr(dates, "tzone") <- "GMT"
  }
  return(data.frame(ds = dates))
}


================================================
FILE: R/R/stan_backends.R
================================================
#' Get the stan backend defined in the environment variables.
#'
#' @return 'rstan' or 'cmdstanr'. 'rstan' if variable is not set.
#' @keywords internal
get_stan_backend <- function() {
  backend_setting <- Sys.getenv("R_STAN_BACKEND", "RSTAN")
  if (backend_setting %in% c("RSTAN", "CMDSTANR")) {
    backend <- switch(
      backend_setting,
      "RSTAN" = "rstan",
      "CMDSTANR" = "cmdstanr"
    )
    if (backend == "cmdstanr") check_cmdstanr()
    return(backend)
  } else {
    return("rstan")
  }
}

#' Check that the required packages for using the cmdstanr backend are installed.
#'
#' @return NULL if successful, and prints the current version of cmdstan being used.
#' @keywords internal
check_cmdstanr <- function() {
  if (!requireNamespace("cmdstanr", quietly = TRUE)) {
    stop(
      "Package \"cmdstanr\" needed to use cmdstanr backend. See installation instructions: https://mc-stan.org/cmdstanr/.",
      call. = FALSE
    )
  }
  if (!requireNamespace("posterior", quietly = TRUE)) {
    stop(
      "Package \"posterior\" needed to use cmdstanr backend. See installation instructions: https://mc-stan.org/posterior/.",
      call. = FALSE
    )
  }
  cmdstanr_version <- cmdstanr::cmdstan_version()
  return(invisible(TRUE))
}

#' Load the Prophet Stan model.
#'
#' @param backend "rstan" or "cmdstanr".
#'
#' @return stanmodel object if backend = "rstan", CmdStanModel object if backend = "cmdstanr"
#' @keywords internal
.load_model <- function(backend) {
  switch(
    backend,
    "rstan" = .load_model_rstan(),
    "cmdstanr" = .load_model_cmdstanr()
  )
}

#' @rdname .load_model
.load_model_rstan <- function() {
  if (exists(".prophet.stan.model", where = prophet_model_env)) {
    model <- get('.prophet.stan.model', envir = prophet_model_env)
  } else {
    model <- stanmodels$prophet
  }

  return(model)
}

#' @rdname .load_model
.load_model_cmdstanr <- function() {
  model_file <- system.file(
    "stan",
    "prophet.stan",
    package = "prophet",
    mustWork = TRUE
  )
  model <- cmdstanr::cmdstan_model(model_file)

  return(model)
}

#' Gives Stan arguments the appropriate names depending on the chosen Stan backend.
#'
#' @param model Model object.
#' @param dat List containing data to use in fitting.
#' @param stan_init Function to initialize parameters for stan fit.
#' @param backend "rstan" or "cmdstanr".
#' @param type "mcmc" or "optimize".
#' @param mcmc_samples Integer, if greater than 0, will do full Bayesian
#'  inference with the specified number of MCMC samples. If 0, will do MAP
#'  estimation.
#'
#' @return Named list of arguments.
#' @keywords internal
.stan_args <- function(model, dat, stan_init, backend, type, mcmc_samples = 0, ...) {
  args <- switch(
    backend,
    "rstan" = .stan_args_rstan(model, dat, stan_init, type, mcmc_samples),
    "cmdstanr" = .stan_args_cmdstanr(model, dat, stan_init, type, mcmc_samples)
  )
  args <- utils::modifyList(args, list(...))

  return(args)
}

#' @rdname .stan_args
.stan_args_rstan <- function(model, dat, stan_init, type, mcmc_samples = NULL) {
  if (type == "mcmc") {
    args <- list(
      object = model,
      data = dat,
      init = stan_init,
      iter = mcmc_samples,
      chains = 4
    )
  } else if (type == "optimize") {
    args <- list(
      object = model,
      data = dat,
      init = stan_init,
      algorithm = if(dat$T < 100) {'Newton'} else {'LBFGS'},
      iter = 1e4,
      as_vector = FALSE
    )
  }

  return(args)
}

#' @rdname .stan_args
.stan_args_cmdstanr <- function(model, dat, stan_init, type, mcmc_samples = NULL) {
  if (type == "mcmc") {
    args <- list(
      object = model,
      data = dat,
      init = stan_init,
      iter_warmup = mcmc_samples / 2,
      iter_sampling = mcmc_samples / 2,
      chains = 4,
      refresh = 0,
      show_messages = FALSE
    )
  } else if (type == "optimize") {
    args <- list(
      object = model,
      data = dat,
      init = stan_init,
      algorithm = if(dat$T < 100) {'newton'} else {'lbfgs'},
      iter = 1e4,
      refresh = 0
    )
  }

  return(args)
}

#' Obtain the point estimates of the parameters of the Prophet model using
#' stan's optimization algorithms.
#'
#' @param args Named list of arguments suitable for the chosen backend. Must
#'   include arguments required for optimization.
#' @param backend "rstan" or "cmdstanr".
#'
#' @return A named list containing "stan_fit" (the fitted stan object),
#'   "params", and "n_iteration"
#' @keywords internal
.fit <- function(args, backend) {
  switch(
    backend,
    "rstan" = .fit_rstan(args),
    "cmdstanr" = .fit_cmdstanr(args)
  )
}

#' Obtain the joint posterior distribution of the parameters of the Prophet
#' model using MCMC sampling.
#'
#' @param args Named list of arguments suitable for the chosen backend. Must
#'   include arguments required for MCMC sampling.
#' @param backend "rstan" or "cmdstanr".
#'
#' @return A named list containing "stan_fit" (the fitted stan object),
#'   "params", and "n_iteration"
#' @keywords internal
.sampling <- function(args, backend) {
  switch(
    backend,
    "rstan" = .sampling_rstan(args),
    "cmdstanr" = .sampling_cmdstanr(args)
  )
}

#' @rdname .fit
.fit_rstan <- function(args) {
  model_output <- list()
  model_output$stan_fit <- do.call(rstan::optimizing, args)
  if (model_output$stan_fit$return_code != 0) {
    message(
      'Optimization terminated abnormally. Falling back to Newton optimizer.'
    )
    args$algorithm = 'Newton'
    model_output$stan_fit <- do.call(rstan::optimizing, args)
  }
  model_output$params <- model_output$stan_fit$par
  model_output$n_iteration <- 1

  return(model_output)
}

#' @rdname .sampling
.sampling_rstan <- function(args) {
  model_output <- list()
  model_output$stan_fit <- do.call(rstan::sampling, args)
  model_output$params <- rstan::extract(model_output$stan_fit)
  model_output$n_iteration <- length(model_output$params$k)

  return(model_output)
}

#' @rdname .fit
.fit_cmdstanr <- function(args) {
  # TODO: Replace with method to extract parameter names once implemented in cmdstanr
  param_names <- c("k", "m", "delta", "sigma_obs", "beta", "trend")
  model_output <- list()
  model <- args$object
  args$object <- NULL
  model_output$stan_fit <- do.call(model$optimize, args)
  if (model_output$stan_fit$return_codes()[1] != 0) {
    message(
      'Optimization terminated abnormally. Falling back to Newton optimizer.'
    )
    args$algorithm = 'newton'
    model_output$stan_fit <- do.call(model$optimize, args)
  }
  model_output$params <- list()
  for (name in param_names) {
    model_output$params[[name]] <- unname(model_output$stan_fit$mle(name))
  }
  model_output$n_iteration <- 1

  return(model_output)
}

#' @rdname .sampling
.sampling_cmdstanr <- function(args) {
  param_names <- c("k", "m", "delta", "sigma_obs", "beta", "trend")
  model_output <- list()
  model <- args$object
  args$object <- NULL
  param_names <- c(param_names, "lp__")
  model_output$stan_fit <- do.call(model$sample, args)
  model_output$params <- list()
  for (name in param_names) {
    model_output$params[[name]] <- posterior::as_draws_matrix(model_output$stan_fit$draws(name))
  }
  model_output$n_iteration <- nrow(model_output$params$k)

  return(model_output)
}


================================================
FILE: R/R/stanmodels.R
================================================
# Generated by rstantools.  Do not edit by hand.

# names of stan models
stanmodels <- c("prophet")

# load each stan module
Rcpp::loadModule("stan_fit4prophet_mod", what = TRUE)

# instantiate each stanmodel object
stanmodels <- sapply(stanmodels, function(model_name) {
  # create C++ code for stan model
  stan_file <- if(dir.exists("stan")) "stan" else file.path("inst", "stan")
  stan_file <- file.path(stan_file, paste0(model_name, ".stan"))
  stanfit <- rstan::stanc_builder(stan_file,
                                  allow_undefined = TRUE,
                                  obfuscate_model_name = FALSE)
  stanfit$model_cpp <- list(model_cppname = stanfit$model_name,
                            model_cppcode = stanfit$cppcode)
  # create stanmodel object
  methods::new(Class = "stanmodel",
               model_name = stanfit$model_name,
               model_code = stanfit$model_code,
               model_cpp = stanfit$model_cpp,
               mk_cppmodule = function(x) get(paste0("rstantools_model_", model_name)))
})


================================================
FILE: R/R/utilities.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

#' Summarise the coefficients of the extra regressors used in the model.
#' For additive regressors, the coefficient represents the incremental impact
#' on \code{y} of a unit increase in the regressor. For multiplicative regressors,
#' the incremental impact is equal to \code{trend(t)} multiplied by the coefficient.
#'
#' Coefficients are measured on the original scale of the training data.
#'
#' @param m Prophet model object, after fitting.
#'
#' @return Dataframe with one row per regressor.
#' @details Output dataframe columns:
#' \itemize{
#'   \item{regressor: Name of the regressor}
#'   \item{regressor_mode: Whether the regressor has an additive or multiplicative
#' effect on \code{y}.}
#'   \item{center: The mean of the regressor if it was standardized. Otherwise 0.}
#'   \item{coef_lower: Lower bound for the coefficient, estimated from the MCMC samples.
#'     Only different to \code{coef} if \code{mcmc_samples > 0}.
#'   }
#'   \item{coef: Expected value of the coefficient.}
#'   \item{coef_upper: Upper bound for the coefficient, estimated from MCMC samples.
#'     Only to different to \code{coef} if \code{mcmc_samples > 0}.
#'   }
#' }
#'
#' @export
regressor_coefficients <- function(m){
  if (length(m$extra_regressors) == 0) {
    stop("No extra regressors found.")
  }
  regr_names <- names(m$extra_regressors)
  regr_modes <- unlist(lapply(m$extra_regressors, function(x) x$mode))
  regr_mus <- unlist(lapply(m$extra_regressors, function (x) x$mu))
  regr_stds <- unlist(lapply(m$extra_regressors, function(x) x$std))

  beta_indices <- which(m$train.component.cols[, regr_names, drop = FALSE] == 1, arr.ind = TRUE)[, "row"]
  betas <- m$params$beta[, beta_indices, drop = FALSE]
  # If regressor is additive, multiply by the scale factor to put coefficients on the original training data scale.
  y_scale_indicator <- matrix(
    data = ifelse(regr_modes == "additive", m$y.scale, 1),
    nrow = nrow(betas),
    ncol = ncol(betas),
    byrow = TRUE
  )
  coefs <- betas * y_scale_indicator  / regr_stds

  percentiles = c((1 - m$interval.width) / 2, 1 - (1 - m$interval.width) / 2)
  bounds <- apply(betas, 2, stats::quantile, probs = percentiles)

  df <- data.frame(
    regressor = regr_names,
    regressor_mode = regr_modes,
    center = regr_mus,
    coef_lower = bounds[1, ],
    coef = apply(betas, 2, mean),
    coef_upper = bounds[2, ],
    stringsAsFactors = FALSE,
    row.names = NULL
  )

  return(df)
}


================================================
FILE: R/R/zzz.R
================================================
# Copyright (c) Facebook, Inc. and its affiliates.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

.onLoad <- function(libname, pkgname) {
  # Create environment for storing stan model
  assign("prophet_model_env", new.env(), parent.env(environment()))
  tryCatch({
    if (.Platform$OS.type == "windows") {
      dest <- file.path('libs', .Platform$r_arch)
    } else {
      dest <- 'libs'
    }
    binary <- system.file(
      dest,
      'prophet_stan_model.RData',
      package = 'prophet',
      mustWork = TRUE
    )
    load(binary)
    obj.name <- 'model.stanm'
    stanm <- eval(parse(text = obj.name))

    ## Should cause an error if the model doesn't work.
    stanm@mk_cppmodule(stanm)

    assign(
      ".prophet.stan.model",
      stanm,
      envir=prophet_model_env
    )
  },
  error = function(cond) {}
  )
}

# IMPORTS ----
# StanHeaders - Used to prevent issues with Prophet dynload error

#' @import StanHeaders


================================================
FILE: R/configure
================================================
# Generated by rstantools.  Do not edit by hand.

#! /bin/sh
"${R_HOME}/bin/Rscript" -e "rstantools::rstan_config()"


================================================
FILE: R/configure.win
================================================
# Generated by rstantools.  Do not edit by hand.

#! /bin/sh
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rstantools::rstan_config()"


================================================
FILE: R/data-raw/generated_holidays.R
================================================
## Copyright (c) 2017-present, Facebook, Inc.
## All rights reserved.

## This source code is licensed under the BSD-style license found in the
## LICENSE file in the root directory of this source tree. An additional grant
## of patent rights can be found in the PATENTS file in the same directory.


generated_holidays <- read.csv("data-raw/generated_holidays.csv")
usethis::use_data(generated_holidays, overwrite = TRUE, internal = TRUE)


================================================
FILE: R/data-raw/generated_holidays.csv
================================================
[File too large to display: 12.0 MB]

================================================
FILE: R/inst/include/stan_meta_header.hpp
================================================
// Insert all #include<foo.hpp> statements here


================================================
FILE: R/inst/stan/prophet.stan
================================================
// Copyright (c) Facebook, Inc. and its affiliates.

// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

functions {
  matrix get_changepoint_matrix(vector t, vector t_change, int T, int S) {
    // Assumes t and t_change are sorted.
    matrix[T, S] A;
    row_vector[S] a_row;
    int cp_idx;

    // Start with an empty matrix.
    A = rep_matrix(0, T, S);
    a_row = rep_row_vector(0, S);
    cp_idx = 1;

    // Fill in each row of A.
    for (i in 1:T) {
      while ((cp_idx <= S) && (t[i] >= t_change[cp_idx])) {
        a_row[cp_idx] = 1;
        cp_idx = cp_idx + 1;
      }
      A[i] = a_row;
    }
    return A;
  }

  // Logistic trend functions
  vector logistic_gamma(real k, real m, vector delta, vector t_change, int S) {
    vector[S] gamma;  // adjusted offsets, for piecewise continuity
    vector[S + 1] k_s;  // actual rate in each segment
    real m_pr;

    // Compute the rate in each segment
    k_s = append_row(k, k + cumulative_sum(delta));

    // Piecewise offsets
    m_pr = m; // The offset in the previous segment
    for (i in 1:S) {
      gamma[i] = (t_change[i] - m_pr) * (1 - k_s[i] / k_s[i + 1]);
      m_pr = m_pr + gamma[i];  // update for the next segment
    }
    return gamma;
  }

  vector logistic_trend(
    real k,
    real m,
    vector delta,
    vector t,
    vector cap,
    matrix A,
    vector t_change,
    int S
  ) {
    vector[S] gamma;

    gamma = logistic_gamma(k, m, delta, t_change, S);
    return cap .* inv_logit((k + A * delta) .* (t - (m + A * gamma)));
  }

  // Linear trend function
  vector linear_trend(
    real k,
    real m,
    vector delta,
    vector t,
    matrix A,
    vector t_change
  ) {
    return (k + A * delta) .* t + (m + A * (-t_change .* delta));
  }

  // Flat trend function
  vector flat_trend(
    real m,
    int T
  ) {
    return rep_vector(m, T);
  }
}

data {
  int T;                // Number of time periods
  int<lower=1> K;       // Number of regressors
  vector[T] t;          // Time
  vector[T] cap;        // Capacities for logistic trend
  vector[T] y;          // Time series
  int S;                // Number of changepoints
  vector[S] t_change;   // Times of trend changepoints
  matrix[T,K] X;        // Regressors
  vector[K] sigmas;     // Scale on seasonality prior
  real<lower=0> tau;    // Scale on changepoints prior
  int trend_indicator;  // 0 for linear, 1 for logistic, 2 for flat
  vector[K] s_a;        // Indicator of additive features
  vector[K] s_m;        // Indicator of multiplicative features
}

transformed data {
  matrix[T, S] A = get_changepoint_matrix(t, t_change, T, S);
  matrix[T, K] X_sa = X .* rep_matrix(s_a', T);
  matrix[T, K] X_sm = X .* rep_matrix(s_m', T);
}

parameters {
  real k;                   // Base trend growth rate
  real m;                   // Trend offset
  vector[S] delta;          // Trend rate adjustments
  real<lower=0> sigma_obs;  // Observation noise
  vector[K] beta;           // Regressor coefficients
}

transformed parameters {
  vector[T] trend;
  if (trend_indicator == 0) {
    trend = linear_trend(k, m, delta, t, A, t_change);
  } else if (trend_indicator == 1) {
    trend = logistic_trend(k, m, delta, t, cap, A, t_change, S);
  } else if (trend_indicator == 2) {
    trend = flat_trend(m, T);
  }
}

model {
  //priors
  k ~ normal(0, 5);
  m ~ normal(0, 5);
  delta ~ double_exponential(0, tau);
  sigma_obs ~ normal(0, 0.5);
  beta ~ normal(0, sigmas);

  // Likelihood
  y ~ normal_id_glm(
    X_sa,
    trend .* (1 + X_sm * beta),
    beta,
    sigma_obs
  );
}


================================================
FILE: R/man/add_changepoints_to_plot.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{add_changepoints_to_plot}
\alias{add_changepoints_to_plot}
\title{Get layers to overlay significant changepoints on prophet forecast plot.}
\usage{
add_changepoints_to_plot(
  m,
  threshold = 0.01,
  cp_color = "red",
  cp_linetype = "dashed",
  trend = TRUE,
  ...
)
}
\arguments{
\item{m}{Prophet model object.}

\item{threshold}{Numeric, changepoints where abs(delta) >= threshold are
significant. (Default 0.01)}

\item{cp_color}{Character, line color. (Default "red")}

\item{cp_linetype}{Character or integer, line type. (Default "dashed")}

\item{trend}{Logical, if FALSE, do not draw trend line. (Default TRUE)}

\item{...}{Other arguments passed on to layers.}
}
\value{
A list of ggplot2 layers.
}
\description{
Get layers to overlay significant changepoints on prophet forecast plot.
}
\examples{
\dontrun{
plot(m, fcst) + add_changepoints_to_plot(m)
}

}


================================================
FILE: R/man/add_country_holidays.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{add_country_holidays}
\alias{add_country_holidays}
\title{Add in built-in holidays for the specified country.}
\usage{
add_country_holidays(m, country_name)
}
\arguments{
\item{m}{Prophet object.}

\item{country_name}{Name of the country, like 'UnitedStates' or 'US'}
}
\value{
The prophet model with the holidays country set.
}
\description{
These holidays will be included in addition to any specified on model
initialization.
}
\details{
Holidays will be calculated for arbitrary date ranges in the history
and future. See the online documentation for the list of countries with
built-in holidays.

Built-in country holidays can only be set for a single country.
}


================================================
FILE: R/man/add_group_component.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{add_group_component}
\alias{add_group_component}
\title{Adds a component with given name that contains all of the components
in group.}
\usage{
add_group_component(components, name, group)
}
\arguments{
\item{components}{Dataframe with components.}

\item{name}{Name of new group component.}

\item{group}{List of components that form the group.}
}
\value{
Dataframe with components.
}
\description{
Adds a component with given name that contains all of the components
in group.
}
\keyword{internal}


================================================
FILE: R/man/add_regressor.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{add_regressor}
\alias{add_regressor}
\title{Add an additional regressor to be used for fitting and predicting.}
\usage{
add_regressor(m, name, prior.scale = NULL, standardize = "auto", mode = NULL)
}
\arguments{
\item{m}{Prophet object.}

\item{name}{String name of the regressor}

\item{prior.scale}{Float scale for the normal prior. If not provided,
holidays.prior.scale will be used.}

\item{standardize}{Bool, specify whether this regressor will be standardized
prior to fitting. Can be 'auto' (standardize if not binary), True, or
False.}

\item{mode}{Optional, 'additive' or 'multiplicative'. Defaults to
m$seasonality.mode.}
}
\value{
The prophet model with the regressor added.
}
\description{
The dataframe passed to `fit` and `predict` will have a column with the
specified name to be used as a regressor. When standardize='auto', the
regressor will be standardized unless it is binary. The regression
coefficient is given a prior with the specified scale parameter.
Decreasing the prior scale will add additional regularization. If no
prior scale is provided, holidays.prior.scale will be used.
Mode can be specified as either 'additive' or 'multiplicative'. If not
specified, m$seasonality.mode will be used. 'additive' means the effect of
the regressor will be added to the trend, 'multiplicative' means it will
multiply the trend.
}


================================================
FILE: R/man/add_seasonality.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{add_seasonality}
\alias{add_seasonality}
\title{Add a seasonal component with specified period, number of Fourier
components, and prior scale.}
\usage{
add_seasonality(
  m,
  name,
  period,
  fourier.order,
  prior.scale = NULL,
  mode = NULL,
  condition.name = NULL
)
}
\arguments{
\item{m}{Prophet object.}

\item{name}{String name of the seasonality component.}

\item{period}{Float number of days in one period.}

\item{fourier.order}{Int number of Fourier components to use.}

\item{prior.scale}{Optional float prior scale for this component.}

\item{mode}{Optional 'additive' or 'multiplicative'.}

\item{condition.name}{String name of the seasonality condition.}
}
\value{
The prophet model with the seasonality added.
}
\description{
Increasing the number of Fourier components allows the seasonality to change
more quickly (at risk of overfitting). Default values for yearly and weekly
seasonalities are 10 and 3 respectively.
}
\details{
Increasing prior scale will allow this seasonality component more
flexibility, decreasing will dampen it. If not provided, will use the
seasonality.prior.scale provided on Prophet initialization (defaults to 10).

Mode can be specified as either 'additive' or 'multiplicative'. If not
specified, m$seasonality.mode will be used (defaults to 'additive').
Additive means the seasonality will be added to the trend, multiplicative
means it will multiply the trend.

If condition.name is provided, the dataframe passed to `fit` and `predict`
should have a column with the specified condition.name containing booleans
which decides when to apply seasonality.
}


================================================
FILE: R/man/check_cmdstanr.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{check_cmdstanr}
\alias{check_cmdstanr}
\title{Check that the required packages for using the cmdstanr backend are installed.}
\usage{
check_cmdstanr()
}
\value{
NULL if successful, and prints the current version of cmdstan being used.
}
\description{
Check that the required packages for using the cmdstanr backend are installed.
}
\keyword{internal}


================================================
FILE: R/man/construct_holiday_dataframe.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{construct_holiday_dataframe}
\alias{construct_holiday_dataframe}
\title{Construct a dataframe of holiday dates.}
\usage{
construct_holiday_dataframe(m, dates)
}
\arguments{
\item{m}{Prophet object.}

\item{dates}{Vector with dates used for computing seasonality.}
}
\value{
A dataframe of holiday dates, in holiday dataframe format used in
 initialization.
}
\description{
Construct a dataframe of holiday dates.
}
\keyword{internal}


================================================
FILE: R/man/coverage.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{coverage}
\alias{coverage}
\title{Coverage}
\usage{
coverage(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of coverages
}
\description{
Coverage
}
\keyword{internal}


================================================
FILE: R/man/cross_validation.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{cross_validation}
\alias{cross_validation}
\title{Cross-validation for time series.}
\usage{
cross_validation(
  model,
  horizon,
  units,
  period = NULL,
  initial = NULL,
  cutoffs = NULL
)
}
\arguments{
\item{model}{Fitted Prophet model.}

\item{horizon}{Integer size of the horizon}

\item{units}{String unit of the horizon, e.g., "days", "secs".}

\item{period}{Integer amount of time between cutoff dates. Same units as
horizon. If not provided, 0.5 * horizon is used.}

\item{initial}{Integer size of the first training period. If not provided,
3 * horizon is used. Same units as horizon.}

\item{cutoffs}{Vector of cutoff dates to be used during
cross-validtation. If not provided works beginning from (end - horizon),
works backwards making cutoffs with a spacing of period until initial is
reached.}
}
\value{
A dataframe with the forecast, actual value, and cutoff date.
}
\description{
Computes forecasts from historical cutoff points which user can input.If
not provided, these are computed beginning from (end - horizon), and working
backwards making cutoffs with a spacing of period until initial is reached.
}
\details{
When period is equal to the time interval of the data, this is the
technique described in https://robjhyndman.com/hyndsight/tscv/ .
}


================================================
FILE: R/man/df_for_plotting.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{df_for_plotting}
\alias{df_for_plotting}
\title{Merge history and forecast for plotting.}
\usage{
df_for_plotting(m, fcst)
}
\arguments{
\item{m}{Prophet object.}

\item{fcst}{Data frame returned by prophet predict.}
}
\description{
Merge history and forecast for plotting.
}
\keyword{internal}


================================================
FILE: R/man/dot-fit.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{.fit}
\alias{.fit}
\title{Obtain the point estimates of the parameters of the Prophet model using
stan's optimization algorithms.}
\usage{
.fit(args, backend)
}
\arguments{
\item{args}{Named list of arguments suitable for the chosen backend. Must
include arguments required for optimization.}

\item{backend}{"rstan" or "cmdstanr".}
}
\value{
A named list containing "stan_fit" (the fitted stan object),
  "params", and "n_iteration"
}
\description{
Obtain the point estimates of the parameters of the Prophet model using
stan's optimization algorithms.
}
\keyword{internal}


================================================
FILE: R/man/dot-load_model.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{.load_model}
\alias{.load_model}
\title{Load the Prophet Stan model.}
\usage{
.load_model(backend)
}
\arguments{
\item{backend}{"rstan" or "cmdstanr".}
}
\value{
stanmodel object if backend = "rstan", CmdStanModel object if backend = "cmdstanr"
}
\description{
Load the Prophet Stan model.
}
\keyword{internal}


================================================
FILE: R/man/dot-sampling.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{.sampling}
\alias{.sampling}
\title{Obtain the joint posterior distribution of the parameters of the Prophet
model using MCMC sampling.}
\usage{
.sampling(args, backend)
}
\arguments{
\item{args}{Named list of arguments suitable for the chosen backend. Must
include arguments required for MCMC sampling.}

\item{backend}{"rstan" or "cmdstanr".}
}
\value{
A named list containing "stan_fit" (the fitted stan object),
  "params", and "n_iteration"
}
\description{
Obtain the joint posterior distribution of the parameters of the Prophet
model using MCMC sampling.
}
\keyword{internal}


================================================
FILE: R/man/dot-stan_args.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{.stan_args}
\alias{.stan_args}
\title{Gives Stan arguments the appropriate names depending on the chosen Stan backend.}
\usage{
.stan_args(model, dat, stan_init, backend, type, mcmc_samples = 0, ...)
}
\arguments{
\item{model}{Model object.}

\item{dat}{List containing data to use in fitting.}

\item{stan_init}{Function to initialize parameters for stan fit.}

\item{backend}{"rstan" or "cmdstanr".}

\item{type}{"mcmc" or "optimize".}

\item{mcmc_samples}{Integer, if greater than 0, will do full Bayesian
inference with the specified number of MCMC samples. If 0, will do MAP
estimation.}
}
\value{
Named list of arguments.
}
\description{
Gives Stan arguments the appropriate names depending on the chosen Stan backend.
}
\keyword{internal}


================================================
FILE: R/man/dyplot.prophet.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{dyplot.prophet}
\alias{dyplot.prophet}
\title{Plot the prophet forecast.}
\usage{
dyplot.prophet(x, fcst, uncertainty = TRUE, ...)
}
\arguments{
\item{x}{Prophet object.}

\item{fcst}{Data frame returned by predict(m, df).}

\item{uncertainty}{Optional boolean indicating if the uncertainty interval for yhat
should be plotted, which will only be done if x$uncertainty.samples > 0. Must be
present in fcst as yhat_lower and yhat_upper.}

\item{...}{additional arguments passed to dygraphs::dygraph}
}
\value{
A dygraph plot.
}
\description{
Plot the prophet forecast.
}
\examples{
\dontrun{
history <- data.frame(
 ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
 y = sin(1:366/200) + rnorm(366)/10)
m <- prophet(history)
future <- make_future_dataframe(m, periods = 365)
forecast <- predict(m, future)
dyplot.prophet(m, forecast)
}

}


================================================
FILE: R/man/fit.prophet.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{fit.prophet}
\alias{fit.prophet}
\title{Fit the prophet model.}
\usage{
fit.prophet(m, df, ...)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Data frame.}

\item{...}{Additional arguments passed to the \code{optimizing} or
\code{sampling} functions in Stan.}
}
\description{
This sets m$params to contain the fitted model parameters. It is a list
with the following elements:
  k (M array): M posterior samples of the initial slope.
  m (M array): The initial intercept.
  delta (MxN matrix): The slope change at each of N changepoints.
  beta (MxK matrix): Coefficients for K seasonality features.
  sigma_obs (M array): Noise level.
Note that M=1 if MAP estimation.
}


================================================
FILE: R/man/flat_growth_init.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{flat_growth_init}
\alias{flat_growth_init}
\title{Initialize flat growth.}
\usage{
flat_growth_init(df)
}
\arguments{
\item{df}{Data frame with columns ds (date), y_scaled (scaled time series),
and t (scaled time).}
}
\value{
A vector (k, m) with the rate (k) and offset (m) of the flat
 growth function.
}
\description{
Provides a strong initialization for flat growth by setting the
growth to 0 and calculates the offset parameter that pass the
function through the mean of the the y_scaled values.
}
\keyword{internal}


================================================
FILE: R/man/flat_trend.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{flat_trend}
\alias{flat_trend}
\title{Evaluate the flat trend function.}
\usage{
flat_trend(t, m)
}
\arguments{
\item{t}{Vector of times on which the function is evaluated.}

\item{m}{Float initial offset.}
}
\value{
Vector y(t).
}
\description{
Evaluate the flat trend function.
}
\keyword{internal}


================================================
FILE: R/man/fourier_series.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{fourier_series}
\alias{fourier_series}
\title{Provides Fourier series components with the specified frequency and order.}
\usage{
fourier_series(dates, period, series.order)
}
\arguments{
\item{dates}{Vector of dates.}

\item{period}{Number of days of the period.}

\item{series.order}{Number of components.}
}
\value{
Matrix with seasonality features.
}
\description{
Provides Fourier series components with the specified frequency and order.
}
\keyword{internal}


================================================
FILE: R/man/generate_cutoffs.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{generate_cutoffs}
\alias{generate_cutoffs}
\title{Generate cutoff dates}
\usage{
generate_cutoffs(df, horizon, initial, period)
}
\arguments{
\item{df}{Dataframe with historical data.}

\item{horizon}{timediff forecast horizon.}

\item{initial}{timediff initial window.}

\item{period}{timediff Simulated forecasts are done with this period.}
}
\value{
Array of datetimes.
}
\description{
Generate cutoff dates
}
\keyword{internal}


================================================
FILE: R/man/generated_holidays.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/data.R
\docType{data}
\name{generated_holidays}
\alias{generated_holidays}
\title{Generated table of holiday dates at the country level from 1995 to 2045}
\format{
A data frame with four variables: ds, holiday, country, year
}
\source{
\url{https://github.com/facebook/prophet/blob/main/python/scripts/generate_holidays_file.py}
}
\usage{
generated_holidays
}
\description{
The data is primarily based on the Python package [holidays](https://pypi.org/project/holidays/)
}
\keyword{datasets}


================================================
FILE: R/man/get_holiday_names.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/make_holidays.R
\name{get_holiday_names}
\alias{get_holiday_names}
\title{Return all possible holiday names of given country}
\usage{
get_holiday_names(country.name)
}
\arguments{
\item{country.name}{Country name (character).}
}
\value{
A vector of all possible holiday names (unique) of given country.
}
\description{
Return all possible holiday names of given country
}
\keyword{internal}


================================================
FILE: R/man/get_stan_backend.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/stan_backends.R
\name{get_stan_backend}
\alias{get_stan_backend}
\title{Get the stan backend defined in the environment variables.}
\usage{
get_stan_backend()
}
\value{
'rstan' or 'cmdstanr'. 'rstan' if variable is not set.
}
\description{
Get the stan backend defined in the environment variables.
}
\keyword{internal}


================================================
FILE: R/man/initialize_scales_fn.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{initialize_scales_fn}
\alias{initialize_scales_fn}
\title{Initialize model scales.}
\usage{
initialize_scales_fn(m, initialize_scales, df)
}
\arguments{
\item{m}{Prophet object.}

\item{initialize_scales}{Boolean set the scales or not.}

\item{df}{Dataframe for setting scales.}
}
\value{
Prophet object with scales set.
}
\description{
Sets model scaling factors using df.
}
\keyword{internal}


================================================
FILE: R/man/linear_growth_init.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{linear_growth_init}
\alias{linear_growth_init}
\title{Initialize constant growth.}
\usage{
linear_growth_init(df)
}
\arguments{
\item{df}{Data frame with columns ds (date), y_scaled (scaled time series),
and t (scaled time).}
}
\value{
A vector (k, m) with the rate (k) and offset (m) of the linear
 growth function.
}
\description{
Provides a strong initialization for linear growth by calculating the
growth and offset parameters that pass the function through the first and
last points in the time series.
}
\keyword{internal}


================================================
FILE: R/man/logistic_growth_init.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{logistic_growth_init}
\alias{logistic_growth_init}
\title{Initialize logistic growth.}
\usage{
logistic_growth_init(df)
}
\arguments{
\item{df}{Data frame with columns ds (date), cap_scaled (scaled capacity),
y_scaled (scaled time series), and t (scaled time).}
}
\value{
A vector (k, m) with the rate (k) and offset (m) of the logistic
 growth function.
}
\description{
Provides a strong initialization for logistic growth by calculating the
growth and offset parameters that pass the function through the first and
last points in the time series.
}
\keyword{internal}


================================================
FILE: R/man/mae.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{mae}
\alias{mae}
\title{Mean absolute error}
\usage{
mae(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of mean absolute errors.
}
\description{
Mean absolute error
}
\keyword{internal}


================================================
FILE: R/man/make_all_seasonality_features.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{make_all_seasonality_features}
\alias{make_all_seasonality_features}
\title{Dataframe with seasonality features.
Includes seasonality features, holiday features, and added regressors.}
\usage{
make_all_seasonality_features(m, df)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Dataframe with dates for computing seasonality features and any
added regressors.}
}
\value{
List with items
 seasonal.features: Dataframe with regressor features,
 prior.scales: Array of prior scales for each column of the features
   dataframe.
 component.cols: Dataframe with indicators for which regression components
   correspond to which columns.
 modes: List with keys 'additive' and 'multiplicative' with arrays of
   component names for each mode of seasonality.
}
\description{
Dataframe with seasonality features.
Includes seasonality features, holiday features, and added regressors.
}
\keyword{internal}


================================================
FILE: R/man/make_future_dataframe.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{make_future_dataframe}
\alias{make_future_dataframe}
\title{Make dataframe with future dates for forecasting.}
\usage{
make_future_dataframe(m, periods, freq = "day", include_history = TRUE)
}
\arguments{
\item{m}{Prophet model object.}

\item{periods}{Int number of periods to forecast forward.}

\item{freq}{'day', 'week', 'month', 'quarter', 'year', 1(1 sec), 60(1 minute) or 3600(1 hour).}

\item{include_history}{Boolean to include the historical dates in the data
frame for predictions.}
}
\value{
Dataframe that extends forward from the end of m$history for the
 requested number of periods.
}
\description{
Make dataframe with future dates for forecasting.
}


================================================
FILE: R/man/make_holiday_features.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{make_holiday_features}
\alias{make_holiday_features}
\title{Construct a matrix of holiday features.}
\usage{
make_holiday_features(m, dates, holidays)
}
\arguments{
\item{m}{Prophet object.}

\item{dates}{Vector with dates used for computing seasonality.}

\item{holidays}{Dataframe containing holidays, as returned by
construct_holiday_dataframe.}
}
\value{
A list with entries
 holiday.features: dataframe with a column for each holiday.
 prior.scales: array of prior scales for each holiday column.
 holiday.names: array of names of all holidays.
}
\description{
Construct a matrix of holiday features.
}
\keyword{internal}


================================================
FILE: R/man/make_holidays_df.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/make_holidays.R
\name{make_holidays_df}
\alias{make_holidays_df}
\title{Make dataframe of holidays for given years and countries}
\usage{
make_holidays_df(years, country.name)
}
\arguments{
\item{years}{List of years for which to include holiday dates.}

\item{country.name}{Country name (character).}
}
\value{
Dataframe with 'ds' and 'holiday', which can directly feed
 to 'holidays' params in Prophet
}
\description{
Make dataframe of holidays for given years and countries
}
\keyword{internal}


================================================
FILE: R/man/make_seasonality_features.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{make_seasonality_features}
\alias{make_seasonality_features}
\title{Data frame with seasonality features.}
\usage{
make_seasonality_features(dates, period, series.order, prefix)
}
\arguments{
\item{dates}{Vector of dates.}

\item{period}{Number of days of the period.}

\item{series.order}{Number of components.}

\item{prefix}{Column name prefix.}
}
\value{
Dataframe with seasonality.
}
\description{
Data frame with seasonality features.
}
\keyword{internal}


================================================
FILE: R/man/mape.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{mape}
\alias{mape}
\title{Mean absolute percent error}
\usage{
mape(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of mean absolute percent errors.
}
\description{
Mean absolute percent error
}
\keyword{internal}


================================================
FILE: R/man/mdape.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{mdape}
\alias{mdape}
\title{Median absolute percent error}
\usage{
mdape(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of median absolute percent errors.
}
\description{
Median absolute percent error
}
\keyword{internal}


================================================
FILE: R/man/mse.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{mse}
\alias{mse}
\title{Mean squared error}
\usage{
mse(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of mean squared errors.
}
\description{
Mean squared error
}
\keyword{internal}


================================================
FILE: R/man/parse_seasonality_args.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{parse_seasonality_args}
\alias{parse_seasonality_args}
\title{Get number of Fourier components for built-in seasonalities.}
\usage{
parse_seasonality_args(m, name, arg, auto.disable, default.order)
}
\arguments{
\item{m}{Prophet object.}

\item{name}{String name of the seasonality component.}

\item{arg}{'auto', TRUE, FALSE, or number of Fourier components as
provided.}

\item{auto.disable}{Bool if seasonality should be disabled when 'auto'.}

\item{default.order}{Int default Fourier order.}
}
\value{
Number of Fourier components, or 0 for disabled.
}
\description{
Get number of Fourier components for built-in seasonalities.
}
\keyword{internal}


================================================
FILE: R/man/performance_metrics.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{performance_metrics}
\alias{performance_metrics}
\title{Compute performance metrics from cross-validation results.}
\usage{
performance_metrics(df, metrics = NULL, rolling_window = 0.1)
}
\arguments{
\item{df}{The dataframe returned by cross_validation.}

\item{metrics}{An array of performance metrics to compute. If not provided,
will use c('mse', 'rmse', 'mae', 'mape', 'mdape', 'smape', 'coverage').}

\item{rolling_window}{Proportion of data to use in each rolling window for
computing the metrics. Should be in [0, 1] to average.}
}
\value{
A dataframe with a column for each metric, and column 'horizon'.
}
\description{
Computes a suite of performance metrics on the output of cross-validation.
By default the following metrics are included:
'mse': mean squared error,
'rmse': root mean squared error,
'mae': mean absolute error,
'mape': mean percent error,
'mdape': median percent error,
'smape': symmetric mean absolute percentage error,
'coverage': coverage of the upper and lower intervals
}
\details{
A subset of these can be specified by passing a list of names as the
`metrics` argument.

Metrics are calculated over a rolling window of cross validation
predictions, after sorting by horizon. Averaging is first done within each
value of the horizon, and then across horizons as needed to reach the
window size. The size of that window (number of simulated forecast points)
is determined by the rolling_window argument, which specifies a proportion
of simulated forecast points to include in each window. rolling_window=0
will compute it separately for each horizon. The default of
rolling_window=0.1 will use 10% of the rows in df in each window.
rolling_window=1 will compute the metric across all simulated forecast
points. The results are set to the right edge of the window.

If rolling_window < 0, then metrics are computed at each datapoint with no
averaging (i.e., 'mse' will actually be squared error with no mean).

The output is a dataframe containing column 'horizon' along with columns
for each of the metrics computed.
}


================================================
FILE: R/man/piecewise_linear.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{piecewise_linear}
\alias{piecewise_linear}
\title{Evaluate the piecewise linear function.}
\usage{
piecewise_linear(t, deltas, k, m, changepoint.ts)
}
\arguments{
\item{t}{Vector of times on which the function is evaluated.}

\item{deltas}{Vector of rate changes at each changepoint.}

\item{k}{Float initial rate.}

\item{m}{Float initial offset.}

\item{changepoint.ts}{Vector of changepoint times.}
}
\value{
Vector y(t).
}
\description{
Evaluate the piecewise linear function.
}
\keyword{internal}


================================================
FILE: R/man/piecewise_logistic.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{piecewise_logistic}
\alias{piecewise_logistic}
\title{Evaluate the piecewise logistic function.}
\usage{
piecewise_logistic(t, cap, deltas, k, m, changepoint.ts)
}
\arguments{
\item{t}{Vector of times on which the function is evaluated.}

\item{cap}{Vector of capacities at each t.}

\item{deltas}{Vector of rate changes at each changepoint.}

\item{k}{Float initial rate.}

\item{m}{Float initial offset.}

\item{changepoint.ts}{Vector of changepoint times.}
}
\value{
Vector y(t).
}
\description{
Evaluate the piecewise logistic function.
}
\keyword{internal}


================================================
FILE: R/man/plot.prophet.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot.prophet}
\alias{plot.prophet}
\title{Plot the prophet forecast.}
\usage{
\method{plot}{prophet}(
  x,
  fcst,
  uncertainty = TRUE,
  plot_cap = TRUE,
  xlabel = "ds",
  ylabel = "y",
  ...
)
}
\arguments{
\item{x}{Prophet object.}

\item{fcst}{Data frame returned by predict(m, df).}

\item{uncertainty}{Optional boolean indicating if the uncertainty interval for yhat
should be plotted, which will only be done if x$uncertainty.samples > 0.
Must be present in fcst as yhat_lower and yhat_upper.}

\item{plot_cap}{Boolean indicating if the capacity should be shown in the
figure, if available.}

\item{xlabel}{Optional label for x-axis}

\item{ylabel}{Optional label for y-axis}

\item{...}{additional arguments}
}
\value{
A ggplot2 plot.
}
\description{
Plot the prophet forecast.
}
\examples{
\dontrun{
history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
                      y = sin(1:366/200) + rnorm(366)/10)
m <- prophet(history)
future <- make_future_dataframe(m, periods = 365)
forecast <- predict(m, future)
plot(m, forecast)
}

}


================================================
FILE: R/man/plot_cross_validation_metric.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_cross_validation_metric}
\alias{plot_cross_validation_metric}
\title{Plot a performance metric vs. forecast horizon from cross validation.
Cross validation produces a collection of out-of-sample model predictions
that can be compared to actual values, at a range of different horizons
(distance from the cutoff). This computes a specified performance metric
for each prediction, and aggregated over a rolling window with horizon.}
\usage{
plot_cross_validation_metric(df_cv, metric, rolling_window = 0.1)
}
\arguments{
\item{df_cv}{The output from fbprophet.diagnostics.cross_validation.}

\item{metric}{Metric name, one of 'mse', 'rmse', 'mae', 'mape', 'coverage'.}

\item{rolling_window}{Proportion of data to use for rolling average of
metric. In [0, 1]. Defaults to 0.1.}
}
\value{
A ggplot2 plot.
}
\description{
This uses fbprophet.diagnostics.performance_metrics to compute the metrics.
Valid values of metric are 'mse', 'rmse', 'mae', 'mape', and 'coverage'.
}
\details{
rolling_window is the proportion of data included in the rolling window of
aggregation. The default value of 0.1 means 10% of data are included in the
aggregation for computing the metric.

As a concrete example, if metric='mse', then this plot will show the
squared error for each cross validation prediction, along with the MSE
averaged over rolling windows of 10% of the data.
}


================================================
FILE: R/man/plot_forecast_component.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_forecast_component}
\alias{plot_forecast_component}
\title{Plot a particular component of the forecast.}
\usage{
plot_forecast_component(m, fcst, name, uncertainty = TRUE, plot_cap = FALSE)
}
\arguments{
\item{m}{Prophet model}

\item{fcst}{Dataframe output of `predict`.}

\item{name}{String name of the component to plot (column of fcst).}

\item{uncertainty}{Optional boolean to plot uncertainty intervals, which will 
only be done if m$uncertainty.samples > 0.}

\item{plot_cap}{Boolean indicating if the capacity should be shown in the
figure, if available.}
}
\value{
A ggplot2 plot.
}
\description{
Plot a particular component of the forecast.
}


================================================
FILE: R/man/plot_seasonality.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_seasonality}
\alias{plot_seasonality}
\title{Plot a custom seasonal component.}
\usage{
plot_seasonality(m, name, uncertainty = TRUE)
}
\arguments{
\item{m}{Prophet model object.}

\item{name}{String name of the seasonality.}

\item{uncertainty}{Optional boolean to plot uncertainty intervals, which
will only be done if m$uncertainty.samples > 0.}
}
\value{
A ggplot2 plot.
}
\description{
Plot a custom seasonal component.
}
\keyword{internal}


================================================
FILE: R/man/plot_weekly.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_weekly}
\alias{plot_weekly}
\title{Plot the weekly component of the forecast.}
\usage{
plot_weekly(m, uncertainty = TRUE, weekly_start = 0, name = "weekly")
}
\arguments{
\item{m}{Prophet model object}

\item{uncertainty}{Optional boolean to plot uncertainty intervals, which will
only be done if m$uncertainty.samples > 0.}

\item{weekly_start}{Integer specifying the start day of the weekly
seasonality plot. 0 (default) starts the week on Sunday. 1 shifts by 1 day
to Monday, and so on.}

\item{name}{Name of seasonality component if previously changed
from default 'weekly'.}
}
\value{
A ggplot2 plot.
}
\description{
Plot the weekly component of the forecast.
}
\keyword{internal}


================================================
FILE: R/man/plot_yearly.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot_yearly}
\alias{plot_yearly}
\title{Plot the yearly component of the forecast.}
\usage{
plot_yearly(m, uncertainty = TRUE, yearly_start = 0, name = "yearly")
}
\arguments{
\item{m}{Prophet model object.}

\item{uncertainty}{Optional boolean to plot uncertainty intervals, which
will only be done if m$uncertainty.samples > 0.}

\item{yearly_start}{Integer specifying the start day of the yearly
seasonality plot. 0 (default) starts the year on Jan 1. 1 shifts by 1 day
to Jan 2, and so on.}

\item{name}{Name of seasonality component if previously changed
from default 'yearly'.}
}
\value{
A ggplot2 plot.
}
\description{
Plot the yearly component of the forecast.
}
\keyword{internal}


================================================
FILE: R/man/predict.prophet.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{predict.prophet}
\alias{predict.prophet}
\title{Predict using the prophet model.}
\usage{
\method{predict}{prophet}(object, df = NULL, ...)
}
\arguments{
\item{object}{Prophet object.}

\item{df}{Dataframe with dates for predictions (column ds), and capacity
(column cap) if logistic growth. If not provided, predictions are made on
the history.}

\item{...}{additional arguments.}
}
\value{
A dataframe with the forecast components.
}
\description{
Predict using the prophet model.
}
\examples{
\dontrun{
history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
                      y = sin(1:366/200) + rnorm(366)/10)
m <- prophet(history)
future <- make_future_dataframe(m, periods = 365)
forecast <- predict(m, future)
plot(m, forecast)
}

}


================================================
FILE: R/man/predict_seasonal_components.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{predict_seasonal_components}
\alias{predict_seasonal_components}
\title{Predict seasonality components, holidays, and added regressors.}
\usage{
predict_seasonal_components(m, df)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Prediction dataframe.}
}
\value{
Dataframe with seasonal components.
}
\description{
Predict seasonality components, holidays, and added regressors.
}
\keyword{internal}


================================================
FILE: R/man/predict_trend.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{predict_trend}
\alias{predict_trend}
\title{Predict trend using the prophet model.}
\usage{
predict_trend(model, df)
}
\arguments{
\item{model}{Prophet object.}

\item{df}{Prediction dataframe.}
}
\value{
Vector with trend on prediction dates.
}
\description{
Predict trend using the prophet model.
}
\keyword{internal}


================================================
FILE: R/man/predict_uncertainty.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{predict_uncertainty}
\alias{predict_uncertainty}
\title{Prophet uncertainty intervals for yhat and trend}
\usage{
predict_uncertainty(m, df)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Prediction dataframe.}
}
\value{
Dataframe with uncertainty intervals.
}
\description{
Prophet uncertainty intervals for yhat and trend
}
\keyword{internal}


================================================
FILE: R/man/predictive_samples.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{predictive_samples}
\alias{predictive_samples}
\title{Sample from the posterior predictive distribution.}
\usage{
predictive_samples(m, df)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Dataframe with dates for predictions (column ds), and capacity
(column cap) if logistic growth.}
}
\value{
A list with items "trend" and "yhat" containing
 posterior predictive samples for that component.
}
\description{
Sample from the posterior predictive distribution.
}


================================================
FILE: R/man/prophet.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{prophet}
\alias{prophet}
\title{Prophet forecaster.}
\usage{
prophet(
  df = NULL,
  growth = "linear",
  changepoints = NULL,
  n.changepoints = 25,
  changepoint.range = 0.8,
  yearly.seasonality = "auto",
  weekly.seasonality = "auto",
  daily.seasonality = "auto",
  holidays = NULL,
  seasonality.mode = "additive",
  seasonality.prior.scale = 10,
  holidays.prior.scale = 10,
  changepoint.prior.scale = 0.05,
  mcmc.samples = 0,
  interval.width = 0.8,
  uncertainty.samples = 1000,
  fit = TRUE,
  backend = NULL,
  ...
)
}
\arguments{
\item{df}{(optional) Dataframe containing the history. Must have columns ds
(date type) and y, the time series. If growth is logistic, then df must
also have a column cap that specifies the capacity at each ds. If not
provided, then the model object will be instantiated but not fit; use
fit.prophet(m, df) to fit the model.}

\item{growth}{String 'linear', 'logistic', or 'flat' to specify a linear,
logistic or flat trend.}

\item{changepoints}{Vector of dates at which to include potential
changepoints. If not specified, potential changepoints are selected
automatically.}

\item{n.changepoints}{Number of potential changepoints to include. Not used
if input `changepoints` is supplied. If `changepoints` is not supplied,
then n.changepoints potential changepoints are selected uniformly from the
first `changepoint.range` proportion of df$ds.}

\item{changepoint.range}{Proportion of history in which trend changepoints
will be estimated. Defaults to 0.8 for the first 80%. Not used if
`changepoints` is specified.}

\item{yearly.seasonality}{Fit yearly seasonality. Can be 'auto', TRUE, FALSE,
or a number of Fourier terms to generate.}

\item{weekly.seasonality}{Fit weekly seasonality. Can be 'auto', TRUE, FALSE,
or a number of Fourier terms to generate.}

\item{daily.seasonality}{Fit daily seasonality. Can be 'auto', TRUE, FALSE,
or a number of Fourier terms to generate.}

\item{holidays}{data frame with columns holiday (character) and ds (date
type)and optionally columns lower_window and upper_window which specify a
range of days around the date to be included as holidays. lower_window=-2
will include 2 days prior to the date as holidays. Also optionally can have
a column prior_scale specifying the prior scale for each holiday.}

\item{seasonality.mode}{'additive' (default) or 'multiplicative'.}

\item{seasonality.prior.scale}{Parameter modulating the strength of the
seasonality model. Larger values allow the model to fit larger seasonal
fluctuations, smaller values dampen the seasonality. Can be specified for
individual seasonalities using add_seasonality.}

\item{holidays.prior.scale}{Parameter modulating the strength of the holiday
components model, unless overridden in the holidays input.}

\item{changepoint.prior.scale}{Parameter modulating the flexibility of the
automatic changepoint selection. Large values will allow many changepoints,
small values will allow few changepoints.}

\item{mcmc.samples}{Integer, if greater than 0, will do full Bayesian
inference with the specified number of MCMC samples. If 0, will do MAP
estimation.}

\item{interval.width}{Numeric, width of the uncertainty intervals provided
for the forecast. If mcmc.samples=0, this will be only the uncertainty in
the trend using the MAP estimate of the extrapolated generative model. If
mcmc.samples>0, this will be integrated over all model parameters, which
will include uncertainty in seasonality.}

\item{uncertainty.samples}{Number of simulated draws used to estimate
uncertainty intervals. Settings this value to 0 or False will disable
uncertainty estimation and speed up the calculation.}

\item{fit}{Boolean, if FALSE the model is initialized but not fit.}

\item{backend}{Whether to use the "rstan" or "cmdstanr" backend to fit the
model. If not provided, uses the R_STAN_BACKEND environment variable.}

\item{...}{Additional arguments, passed to \code{\link{fit.prophet}}}
}
\value{
A prophet model.
}
\description{
Prophet forecaster.
}
\examples{
\dontrun{
history <- data.frame(ds = seq(as.Date('2015-01-01'), as.Date('2016-01-01'), by = 'd'),
                      y = sin(1:366/200) + rnorm(366)/10)
m <- prophet(history)
}

}


================================================
FILE: R/man/prophet_copy.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{prophet_copy}
\alias{prophet_copy}
\title{Copy Prophet object.}
\usage{
prophet_copy(m, cutoff = NULL)
}
\arguments{
\item{m}{Prophet model object.}

\item{cutoff}{Date, possibly as string. Changepoints are only retained if
changepoints <= cutoff.}
}
\value{
An unfitted Prophet model object with the same parameters as the
 input model.
}
\description{
Copy Prophet object.
}
\keyword{internal}


================================================
FILE: R/man/prophet_plot_components.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{prophet_plot_components}
\alias{prophet_plot_components}
\title{Plot the components of a prophet forecast.
Prints a ggplot2 with whichever are available of: trend, holidays, weekly
seasonality, yearly seasonality, and additive and multiplicative extra
regressors.}
\usage{
prophet_plot_components(
  m,
  fcst,
  uncertainty = TRUE,
  plot_cap = TRUE,
  weekly_start = 0,
  yearly_start = 0,
  render_plot = TRUE
)
}
\arguments{
\item{m}{Prophet object.}

\item{fcst}{Data frame returned by predict(m, df).}

\item{uncertainty}{Optional boolean indicating if the uncertainty interval should be
plotted for the trend, from fcst columns trend_lower and trend_upper.This will
only be done if m$uncertainty.samples > 0.}

\item{plot_cap}{Boolean indicating if the capacity should be shown in the
figure, if available.}

\item{weekly_start}{Integer specifying the start day of the weekly
seasonality plot. 0 (default) starts the week on Sunday. 1 shifts by 1 day
to Monday, and so on.}

\item{yearly_start}{Integer specifying the start day of the yearly
seasonality plot. 0 (default) starts the year on Jan 1. 1 shifts by 1 day
to Jan 2, and so on.}

\item{render_plot}{Boolean indicating if the plots should be rendered.
Set to FALSE if you want the function to only return the list of panels.}
}
\value{
Invisibly return a list containing the plotted ggplot objects
}
\description{
Plot the components of a prophet forecast.
Prints a ggplot2 with whichever are available of: trend, holidays, weekly
seasonality, yearly seasonality, and additive and multiplicative extra
regressors.
}


================================================
FILE: R/man/regressor_coefficients.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utilities.R
\name{regressor_coefficients}
\alias{regressor_coefficients}
\title{Summarise the coefficients of the extra regressors used in the model.
For additive regressors, the coefficient represents the incremental impact
on \code{y} of a unit increase in the regressor. For multiplicative regressors,
the incremental impact is equal to \code{trend(t)} multiplied by the coefficient.}
\usage{
regressor_coefficients(m)
}
\arguments{
\item{m}{Prophet model object, after fitting.}
}
\value{
Dataframe with one row per regressor.
}
\description{
Coefficients are measured on the original scale of the training data.
}
\details{
Output dataframe columns:
\itemize{
  \item{regressor: Name of the regressor}
  \item{regressor_mode: Whether the regressor has an additive or multiplicative
effect on \code{y}.}
  \item{center: The mean of the regressor if it was standardized. Otherwise 0.}
  \item{coef_lower: Lower bound for the coefficient, estimated from the MCMC samples.
    Only different to \code{coef} if \code{mcmc_samples > 0}.
  }
  \item{coef: Expected value of the coefficient.}
  \item{coef_upper: Upper bound for the coefficient, estimated from MCMC samples.
    Only to different to \code{coef} if \code{mcmc_samples > 0}.
  }
}
}


================================================
FILE: R/man/regressor_column_matrix.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{regressor_column_matrix}
\alias{regressor_column_matrix}
\title{Dataframe indicating which columns of the feature matrix correspond to
which seasonality/regressor components.}
\usage{
regressor_column_matrix(m, seasonal.features, modes)
}
\arguments{
\item{m}{Prophet object.}

\item{seasonal.features}{Constructed seasonal features dataframe.}

\item{modes}{List with keys 'additive' and 'multiplicative' with arrays of
component names for each mode of seasonality.}
}
\value{
List with items
 component.cols: A binary indicator dataframe with columns seasonal
   components and rows columns in seasonal.features. Entry is 1 if that
   column is used in that component.
 modes: Updated input with combination components.
}
\description{
Includes combination components, like 'additive_terms'. These combination
components will be added to the 'modes' input.
}
\keyword{internal}


================================================
FILE: R/man/rmse.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{rmse}
\alias{rmse}
\title{Root mean squared error}
\usage{
rmse(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of root mean squared errors.
}
\description{
Root mean squared error
}
\keyword{internal}


================================================
FILE: R/man/rolling_mean_by_h.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{rolling_mean_by_h}
\alias{rolling_mean_by_h}
\title{Compute a rolling mean of x, after first aggregating by h}
\usage{
rolling_mean_by_h(x, h, w, name)
}
\arguments{
\item{x}{Array.}

\item{h}{Array of horizon for each value in x.}

\item{w}{Integer window size (number of elements).}

\item{name}{String name for metric in result dataframe.}
}
\value{
Dataframe with columns horizon and name, the rolling mean of x.
}
\description{
Right-aligned. Computes a single mean for each unique value of h. Each mean
is over at least w samples.
}
\keyword{internal}


================================================
FILE: R/man/rolling_median_by_h.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{rolling_median_by_h}
\alias{rolling_median_by_h}
\title{Compute a rolling median of x, after first aggregating by h}
\usage{
rolling_median_by_h(x, h, w, name)
}
\arguments{
\item{x}{Array.}

\item{h}{Array of horizon for each value in x.}

\item{w}{Integer window size (number of elements).}

\item{name}{String name for metric in result dataframe.}
}
\value{
Dataframe with columns horizon and name, the rolling median of x.
}
\description{
Right-aligned. Computes a single median for each unique value of h. Each median
is over at least w samples.
}
\details{
For each h where there are fewer than w samples, we take samples from the previous h,
}


================================================
FILE: R/man/sample_model.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{sample_model}
\alias{sample_model}
\title{Simulate observations from the extrapolated generative model.}
\usage{
sample_model(m, df, seasonal.features, iteration, s_a, s_m)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Prediction dataframe.}

\item{seasonal.features}{Data frame of seasonal features}

\item{iteration}{Int sampling iteration to use parameters from.}

\item{s_a}{Indicator vector for additive components}

\item{s_m}{Indicator vector for multiplicative components}
}
\value{
List of trend and yhat, each a vector like df$t.
}
\description{
Simulate observations from the extrapolated generative model.
}
\keyword{internal}


================================================
FILE: R/man/sample_posterior_predictive.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{sample_posterior_predictive}
\alias{sample_posterior_predictive}
\title{Prophet posterior predictive samples.}
\usage{
sample_posterior_predictive(m, df)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Prediction dataframe.}
}
\value{
List with posterior predictive samples for the forecast yhat and
 for the trend component.
}
\description{
Prophet posterior predictive samples.
}
\keyword{internal}


================================================
FILE: R/man/sample_predictive_trend.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{sample_predictive_trend}
\alias{sample_predictive_trend}
\title{Simulate the trend using the extrapolated generative model.}
\usage{
sample_predictive_trend(model, df, iteration)
}
\arguments{
\item{model}{Prophet object.}

\item{df}{Prediction dataframe.}

\item{iteration}{Int sampling iteration to use parameters from.}
}
\value{
Vector of simulated trend over df$t.
}
\description{
Simulate the trend using the extrapolated generative model.
}
\keyword{internal}


================================================
FILE: R/man/seasonality_plot_df.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{seasonality_plot_df}
\alias{seasonality_plot_df}
\title{Prepare dataframe for plotting seasonal components.}
\usage{
seasonality_plot_df(m, ds)
}
\arguments{
\item{m}{Prophet object.}

\item{ds}{Array of dates for column ds.}
}
\value{
A dataframe with seasonal components on ds.
}
\description{
Prepare dataframe for plotting seasonal components.
}
\keyword{internal}


================================================
FILE: R/man/set_auto_seasonalities.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{set_auto_seasonalities}
\alias{set_auto_seasonalities}
\title{Set seasonalities that were left on auto.}
\usage{
set_auto_seasonalities(m)
}
\arguments{
\item{m}{Prophet object.}
}
\value{
The prophet model with seasonalities set.
}
\description{
Turns on yearly seasonality if there is >=2 years of history.
Turns on weekly seasonality if there is >=2 weeks of history, and the
spacing between dates in the history is <7 days.
Turns on daily seasonality if there is >=2 days of history, and the spacing
between dates in the history is <1 day.
}
\keyword{internal}


================================================
FILE: R/man/set_changepoints.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{set_changepoints}
\alias{set_changepoints}
\title{Set changepoints}
\usage{
set_changepoints(m)
}
\arguments{
\item{m}{Prophet object.}
}
\value{
m with changepoints set.
}
\description{
Sets m$changepoints to the dates of changepoints. Either:
1) The changepoints were passed in explicitly.
  A) They are empty.
  B) They are not empty, and need validation.
2) We are generating a grid of them.
3) The user prefers no changepoints be used.
}
\keyword{internal}


================================================
FILE: R/man/set_date.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{set_date}
\alias{set_date}
\title{Convert date vector}
\usage{
set_date(ds)
}
\arguments{
\item{ds}{Date vector}
}
\value{
vector of POSIXct object converted from date
}
\description{
Convert the date to POSIXct object. Timezones are stripped and replaced
with GMT.
}
\keyword{internal}


================================================
FILE: R/man/setup_dataframe.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{setup_dataframe}
\alias{setup_dataframe}
\title{Prepare dataframe for fitting or predicting.}
\usage{
setup_dataframe(m, df, initialize_scales = FALSE)
}
\arguments{
\item{m}{Prophet object.}

\item{df}{Data frame with columns ds, y, and cap if logistic growth. Any
specified additional regressors must also be present.}

\item{initialize_scales}{Boolean set scaling factors in m from df.}
}
\value{
list with items 'df' and 'm'.
}
\description{
Adds a time index and scales y. Creates auxiliary columns 't', 't_ix',
'y_scaled', and 'cap_scaled'. These columns are used during both fitting
and predicting.
}
\keyword{internal}


================================================
FILE: R/man/single_cutoff_forecast.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{single_cutoff_forecast}
\alias{single_cutoff_forecast}
\title{Forecast for a single cutoff.
Used in cross_validation function when evaluating for multiple cutoffs.}
\usage{
single_cutoff_forecast(df, model, cutoff, horizon.dt, predict_columns)
}
\arguments{
\item{df}{Dataframe with history for cutoff.}

\item{model}{Prophet model object.}

\item{cutoff}{Datetime of cutoff.}

\item{horizon.dt}{timediff forecast horizon.}

\item{predict_columns}{Array of names of columns to be returned in output.}
}
\value{
Dataframe with forecast, actual value, and cutoff.
}
\description{
Forecast for a single cutoff.
Used in cross_validation function when evaluating for multiple cutoffs.
}
\keyword{internal}


================================================
FILE: R/man/smape.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/diagnostics.R
\name{smape}
\alias{smape}
\title{Symmetric mean absolute percentage error
based on Chen and Yang (2004) formula}
\usage{
smape(df, w)
}
\arguments{
\item{df}{Cross-validation results dataframe.}

\item{w}{Aggregation window size.}
}
\value{
Array of symmetric mean absolute percent errors.
}
\description{
Symmetric mean absolute percentage error
based on Chen and Yang (2004) formula
}
\keyword{internal}


================================================
FILE: R/man/time_diff.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{time_diff}
\alias{time_diff}
\title{Time difference between datetimes}
\usage{
time_diff(ds1, ds2, units = "days")
}
\arguments{
\item{ds1}{POSIXct object}

\item{ds2}{POSIXct object}

\item{units}{string units of difference, e.g. 'days' or 'secs'.}
}
\value{
numeric time difference
}
\description{
Compute time difference of two POSIXct objects
}
\keyword{internal}


================================================
FILE: R/man/validate_column_name.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{validate_column_name}
\alias{validate_column_name}
\title{Validates the name of a seasonality, holiday, or regressor.}
\usage{
validate_column_name(
  m,
  name,
  check_holidays = TRUE,
  check_seasonalities = TRUE,
  check_regressors = TRUE
)
}
\arguments{
\item{m}{Prophet object.}

\item{name}{string}

\item{check_holidays}{bool check if name already used for holiday}

\item{check_seasonalities}{bool check if name already used for seasonality}

\item{check_regressors}{bool check if name already used for regressor}
}
\description{
Validates the name of a seasonality, holiday, or regressor.
}
\keyword{internal}


================================================
FILE: R/man/validate_inputs.Rd
================================================
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/prophet.R
\name{validate_inputs}
\alias{validate_inputs}
\title{Validates the inputs to Prophet.}
\usage{
validate_inputs(m)
}
\arguments{
\item{m}{Prophet object.}
}
\value{
The Prophet object.
}
\description{
Validates the inputs to Prophet.
}
\keyword{internal}


================================================
FILE: R/prophet.Rproj
================================================
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: knitr
LaTeX: pdfLaTeX

AutoAppendNewline: Yes
StripTrailingWhitespace: Yes

BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd,collate,namespace


================================================
FILE: R/src/Makevars
================================================
# Generated by rstantools.  Do not edit by hand.

STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders")

STANC_FLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "cat(ifelse(utils::packageVersion('rstan') >= 2.26, '-DUSE_STANC3',''))")
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error $(STANC_FLAGS)
PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()")
PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()")

CXX_STD = CXX17


================================================
FILE: R/src/Makevars.win
================================================
# Generated by rstantools.  Do not edit by hand.

STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders")

STANC_FLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "cat(ifelse(utils::packageVersion('rstan') >= 2.26, '-DUSE_STANC3',''))")
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 $(STANC_FLAGS)
PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()")
PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()")

CXX_STD = CXX17


================================================
FILE: R/tests/testthat/data.csv
================================================
ds,y
2012-05-18,38.23
2012-05-21,34.03
2012-05-22,31.0
2012-05-23,32.0
2012-05-24,33.03
2012-05-25,31.91
2012-05-29,28.84
2012-05-30,28.19
2012-05-31,29.6
2012-06-01,27.72
2012-06-04,26.9
2012-06-05,25.87
2012-06-06,26.81
2012-06-07,26.31
2012-06-08,27.1
2012-06-11,27.01
2012-06-12,27.4
2012-06-13,27.27
2012-06-14,28.29
2012-06-15,30.01
2012-06-18,31.41
2012-06-19,31.91
2012-06-20,31.6
2012-06-21,31.84
2012-06-22,33.05
2012-06-25,32.06
2012-06-26,33.1
2012-06-27,32.23
2012-06-28,31.36
2012-06-29,31.1
2012-07-02,30.77
2012-07-03,31.2
2012-07-05,31.47
2012-07-06,31.73
2012-07-09,32.17
2012-07-10,31.47
2012-07-11,30.97
2012-07-12,30.81
2012-07-13,30.72
2012-07-16,28.25
2012-07-17,28.09
2012-07-18,29.11
2012-07-19,29.0
2012-07-20,28.76
2012-07-23,28.75
2012-07-24,28.45
2012-07-25,29.34
2012-07-26,26.85
2012-07-27,23.71
2012-07-30,23.15
2012-07-31,21.71
2012-08-01,20.88
2012-08-02,20.04
2012-08-03,21.09
2012-08-06,21.92
2012-08-07,20.72
2012-08-08,20.72
2012-08-09,21.01
2012-08-10,21.81
2012-08-13,21.6
2012-08-14,20.38
2012-08-15,21.2
2012-08-16,19.87
2012-08-17,19.05
2012-08-20,20.01
2012-08-21,19.16
2012-08-22,19.44
2012-08-23,19.44
2012-08-24,19.41
2012-08-27,19.15
2012-08-28,19.34
2012-08-29,19.1
2012-08-30,19.09
2012-08-31,18.06
2012-09-04,17.73
2012-09-05,18.58
2012-09-06,18.96
2012-09-07,18.98
2012-09-10,18.81
2012-09-11,19.43
2012-09-12,20.93
2012-09-13,20.71
2012-09-14,22.0
2012-09-17,21.52
2012-09-18,21.87
2012-09-19,23.29
2012-09-20,22.59
2012-09-21,22.86
2012-09-24,20.79
2012-09-25,20.28
2012-09-26,20.62
2012-09-27,20.32
2012-09-28,21.66
2012-10-01,21.99
2012-10-02,22.27
2012-10-03,21.83
2012-10-04,21.95
2012-10-05,20.91
2012-10-08,20.4
2012-10-09,20.23
2012-10-10,19.64
2012-10-11,19.75
2012-10-12,19.52
2012-10-15,19.52
2012-10-16,19.48
2012-10-17,19.88
2012-10-18,18.98
2012-10-19,19.0
2012-10-22,19.32
2012-10-23,19.5
2012-10-24,23.23
2012-10-25,22.56
2012-10-26,21.94
2012-10-31,21.11
2012-11-01,21.21
2012-11-02,21.18
2012-11-05,21.25
2012-11-06,21.17
2012-11-07,20.47
2012-11-08,19.99
2012-11-09,19.21
2012-11-12,20.07
2012-11-13,19.86
2012-11-14,22.36
2012-11-15,22.17
2012-11-16,23.56
2012-11-19,22.92
2012-11-20,23.1
2012-11-21,24.32
2012-11-23,24.0
2012-11-26,25.94
2012-11-27,26.15
2012-11-28,26.36
2012-11-29,27.32
2012-11-30,28.0
2012-12-03,27.04
2012-12-04,27.46
2012-12-05,27.71
2012-12-06,26.97
2012-12-07,27.49
2012-12-10,27.84
2012-12-11,27.98
2012-12-12,27.58
2012-12-13,28.24
2012-12-14,26.81
2012-12-17,26.75
2012-12-18,27.71
2012-12-19,27.41
2012-12-20,27.36
2012-12-21,26.26
2012-12-24,26.93
2012-12-26,26.51
2012-12-27,26.05
2012-12-28,25.91
2012-12-31,26.62
2013-01-02,28.0
2013-01-03,27.77
2013-01-04,28.76
2013-01-07,29.42
2013-01-08,29.06
2013-01-09,30.59
2013-01-10,31.3
2013-01-11,31.72
2013-01-14,30.95
2013-01-15,30.1
2013-01-16,29.85
2013-01-17,30.14
2013-01-18,29.66
2013-01-22,30.73
2013-01-23,30.82
2013-01-24,31.08
2013-01-25,31.54
2013-01-28,32.47
2013-01-29,30.79
2013-01-30,31.24
2013-01-31,30.98
2013-02-01,29.73
2013-02-04,28.11
2013-02-05,28.64
2013-02-06,29.05
2013-02-07,28.65
2013-02-08,28.55
2013-02-11,28.26
2013-02-12,27.37
2013-02-13,27.91
2013-02-14,28.5
2013-02-15,28.32
2013-02-19,28.93
2013-02-20,28.46
2013-02-21,27.28
2013-02-22,27.13
2013-02-25,27.27
2013-02-26,27.39
2013-02-27,26.87
2013-02-28,27.25
2013-03-01,27.78
2013-03-04,27.72
2013-03-05,27.52
2013-03-06,27.45
2013-03-07,28.58
2013-03-08,27.96
2013-03-11,28.14
2013-03-12,27.83
2013-03-13,27.08
2013-03-14,27.04
2013-03-15,26.65
2013-03-18,26.49
2013-03-19,26.55
2013-03-20,25.86
2013-03-21,25.74
2013-03-22,25.73
2013-03-25,25.13
2013-03-26,25.21
2013-03-27,26.09
2013-03-28,25.58
2013-04-01,25.53
2013-04-02,25.42
2013-04-03,26.25
2013-04-04,27.07
2013-04-05,27.39
2013-04-08,26.85
2013-04-09,26.59
2013-04-10,27.57
2013-04-11,28.02
2013-04-12,27.4
2013-04-15,26.52
2013-04-16,26.92
2013-04-17,26.63
2013-04-18,25.69
2013-04-19,25.73
2013-04-22,25.97
2013-04-23,25.98
2013-04-24,26.11
2013-04-25,26.14
2013-04-26,26.85
2013-04-29,26.98
2013-04-30,27.77
2013-05-01,27.43
2013-05-0
Download .txt
gitextract_w0ay2q3a/

├── .deepsource.toml
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build-and-test.yml
│       └── wheel.yml
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── Makefile
├── R/
│   ├── .Rbuildignore
│   ├── .gitignore
│   ├── DESCRIPTION
│   ├── LICENSE
│   ├── NAMESPACE
│   ├── R/
│   │   ├── data.R
│   │   ├── diagnostics.R
│   │   ├── make_holidays.R
│   │   ├── plot.R
│   │   ├── prophet.R
│   │   ├── stan_backends.R
│   │   ├── stanmodels.R
│   │   ├── sysdata.rda
│   │   ├── utilities.R
│   │   └── zzz.R
│   ├── configure
│   ├── configure.win
│   ├── data-raw/
│   │   ├── generated_holidays.R
│   │   └── generated_holidays.csv
│   ├── inst/
│   │   ├── include/
│   │   │   └── stan_meta_header.hpp
│   │   └── stan/
│   │       └── prophet.stan
│   ├── man/
│   │   ├── add_changepoints_to_plot.Rd
│   │   ├── add_country_holidays.Rd
│   │   ├── add_group_component.Rd
│   │   ├── add_regressor.Rd
│   │   ├── add_seasonality.Rd
│   │   ├── check_cmdstanr.Rd
│   │   ├── construct_holiday_dataframe.Rd
│   │   ├── coverage.Rd
│   │   ├── cross_validation.Rd
│   │   ├── df_for_plotting.Rd
│   │   ├── dot-fit.Rd
│   │   ├── dot-load_model.Rd
│   │   ├── dot-sampling.Rd
│   │   ├── dot-stan_args.Rd
│   │   ├── dyplot.prophet.Rd
│   │   ├── fit.prophet.Rd
│   │   ├── flat_growth_init.Rd
│   │   ├── flat_trend.Rd
│   │   ├── fourier_series.Rd
│   │   ├── generate_cutoffs.Rd
│   │   ├── generated_holidays.Rd
│   │   ├── get_holiday_names.Rd
│   │   ├── get_stan_backend.Rd
│   │   ├── initialize_scales_fn.Rd
│   │   ├── linear_growth_init.Rd
│   │   ├── logistic_growth_init.Rd
│   │   ├── mae.Rd
│   │   ├── make_all_seasonality_features.Rd
│   │   ├── make_future_dataframe.Rd
│   │   ├── make_holiday_features.Rd
│   │   ├── make_holidays_df.Rd
│   │   ├── make_seasonality_features.Rd
│   │   ├── mape.Rd
│   │   ├── mdape.Rd
│   │   ├── mse.Rd
│   │   ├── parse_seasonality_args.Rd
│   │   ├── performance_metrics.Rd
│   │   ├── piecewise_linear.Rd
│   │   ├── piecewise_logistic.Rd
│   │   ├── plot.prophet.Rd
│   │   ├── plot_cross_validation_metric.Rd
│   │   ├── plot_forecast_component.Rd
│   │   ├── plot_seasonality.Rd
│   │   ├── plot_weekly.Rd
│   │   ├── plot_yearly.Rd
│   │   ├── predict.prophet.Rd
│   │   ├── predict_seasonal_components.Rd
│   │   ├── predict_trend.Rd
│   │   ├── predict_uncertainty.Rd
│   │   ├── predictive_samples.Rd
│   │   ├── prophet.Rd
│   │   ├── prophet_copy.Rd
│   │   ├── prophet_plot_components.Rd
│   │   ├── regressor_coefficients.Rd
│   │   ├── regressor_column_matrix.Rd
│   │   ├── rmse.Rd
│   │   ├── rolling_mean_by_h.Rd
│   │   ├── rolling_median_by_h.Rd
│   │   ├── sample_model.Rd
│   │   ├── sample_posterior_predictive.Rd
│   │   ├── sample_predictive_trend.Rd
│   │   ├── seasonality_plot_df.Rd
│   │   ├── set_auto_seasonalities.Rd
│   │   ├── set_changepoints.Rd
│   │   ├── set_date.Rd
│   │   ├── setup_dataframe.Rd
│   │   ├── single_cutoff_forecast.Rd
│   │   ├── smape.Rd
│   │   ├── time_diff.Rd
│   │   ├── validate_column_name.Rd
│   │   └── validate_inputs.Rd
│   ├── prophet.Rproj
│   ├── src/
│   │   ├── Makevars
│   │   └── Makevars.win
│   ├── tests/
│   │   ├── testthat/
│   │   │   ├── data.csv
│   │   │   ├── data2.csv
│   │   │   ├── test_diagnostics.R
│   │   │   ├── test_prophet.R
│   │   │   ├── test_stan_functions.R
│   │   │   └── test_utilities.R
│   │   └── testthat.R
│   └── vignettes/
│       └── quick_start.Rmd
├── README.md
├── docker-compose.yml
├── docs/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── Gemfile
│   ├── LICENSE
│   ├── Makefile
│   ├── README.md
│   ├── _config.yml
│   ├── _data/
│   │   ├── authors.yml
│   │   ├── features.yml
│   │   ├── nav.yml
│   │   ├── nav_docs.yml
│   │   ├── powered_by.yml
│   │   ├── powered_by_highlight.yml
│   │   └── promo.yml
│   ├── _docs/
│   │   ├── additional_topics.md
│   │   ├── contributing.md
│   │   ├── diagnostics.md
│   │   ├── handling_shocks.md
│   │   ├── holiday_effects.md
│   │   ├── installation.md
│   │   ├── multiplicative_seasonality.md
│   │   ├── non-daily_data.md
│   │   ├── outliers.md
│   │   ├── quick_start.md
│   │   ├── saturating_forecasts.md
│   │   ├── seasonality,_holiday_effects,_and_regressors.md
│   │   ├── trend_changepoints.md
│   │   └── uncertainty_intervals.md
│   ├── _includes/
│   │   ├── blog_pagination.html
│   │   ├── content/
│   │   │   ├── gridblocks.html
│   │   │   └── items/
│   │   │       └── gridblock.html
│   │   ├── doc.html
│   │   ├── doc_paging.html
│   │   ├── footer.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── hero.html
│   │   ├── home_header.html
│   │   ├── katex_import.html
│   │   ├── katex_render.html
│   │   ├── nav/
│   │   │   ├── collection_nav.html
│   │   │   ├── collection_nav_group.html
│   │   │   ├── collection_nav_group_item.html
│   │   │   └── header_nav.html
│   │   ├── nav.html
│   │   ├── nav_search.html
│   │   ├── plugins/
│   │   │   ├── all_share.html
│   │   │   ├── ascii_cinema.html
│   │   │   ├── button.html
│   │   │   ├── github_star.html
│   │   │   ├── github_watch.html
│   │   │   ├── google_share.html
│   │   │   ├── iframe.html
│   │   │   ├── like_button.html
│   │   │   ├── plugin_row.html
│   │   │   ├── post_social_plugins.html
│   │   │   ├── slideshow.html
│   │   │   ├── twitter_follow.html
│   │   │   └── twitter_share.html
│   │   ├── post.html
│   │   ├── powered_by.html
│   │   ├── social_plugins.html
│   │   └── ui/
│   │       └── button.html
│   ├── _layouts/
│   │   ├── basic.html
│   │   ├── blog.html
│   │   ├── blog_default.html
│   │   ├── default.html
│   │   ├── doc_default.html
│   │   ├── doc_page.html
│   │   ├── docs.html
│   │   ├── home.html
│   │   ├── page.html
│   │   ├── plain.html
│   │   ├── post.html
│   │   ├── redirect.html
│   │   └── top-level.html
│   ├── _sass/
│   │   ├── _base.scss
│   │   ├── _blog.scss
│   │   ├── _buttons.scss
│   │   ├── _footer.scss
│   │   ├── _gridBlock.scss
│   │   ├── _header.scss
│   │   ├── _poweredby.scss
│   │   ├── _promo.scss
│   │   ├── _react_docs_nav.scss
│   │   ├── _react_header_nav.scss
│   │   ├── _reset.scss
│   │   ├── _search.scss
│   │   ├── _slideshow.scss
│   │   ├── _syntax-highlighting.scss
│   │   └── _tables.scss
│   ├── blog/
│   │   ├── all.html
│   │   └── index.html
│   ├── css/
│   │   └── main.scss
│   ├── docs/
│   │   └── index.html
│   ├── feed.xml
│   ├── index.md
│   └── nbconvert_template.tpl
├── examples/
│   ├── example_air_passengers.csv
│   ├── example_pedestrians_covid.csv
│   ├── example_pedestrians_multivariate.csv
│   ├── example_retail_sales.csv
│   ├── example_wp_log_R.csv
│   ├── example_wp_log_R_outliers1.csv
│   ├── example_wp_log_R_outliers2.csv
│   ├── example_wp_log_peyton_manning.csv
│   └── example_yosemite_temps.csv
├── notebooks/
│   ├── additional_topics.ipynb
│   ├── diagnostics.ipynb
│   ├── handling_shocks.ipynb
│   ├── multiplicative_seasonality.ipynb
│   ├── non-daily_data.ipynb
│   ├── outliers.ipynb
│   ├── quick_start.ipynb
│   ├── saturating_forecasts.ipynb
│   ├── seasonality,_holiday_effects,_and_regressors.ipynb
│   ├── trend_changepoints.ipynb
│   └── uncertainty_intervals.ipynb
├── python/
│   ├── LICENSE
│   ├── MANIFEST.in
│   ├── README.md
│   ├── prophet/
│   │   ├── __init__.py
│   │   ├── __version__.py
│   │   ├── diagnostics.py
│   │   ├── forecaster.py
│   │   ├── make_holidays.py
│   │   ├── models.py
│   │   ├── plot.py
│   │   ├── py.typed
│   │   ├── serialize.py
│   │   ├── tests/
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── data.csv
│   │   │   ├── data2.csv
│   │   │   ├── data3.csv
│   │   │   ├── serialized_model_v0.6.1.dev0.json
│   │   │   ├── serialized_model_v0.7.1.json
│   │   │   ├── serialized_model_v1.0.1.json
│   │   │   ├── test_diagnostics.py
│   │   │   ├── test_prophet.py
│   │   │   ├── test_serialize.py
│   │   │   └── test_utilities.py
│   │   └── utilities.py
│   ├── pyproject.toml
│   ├── scripts/
│   │   └── generate_holidays_file.py
│   ├── setup.py
│   └── stan/
│       └── prophet.stan
└── python_shim/
    ├── LICENSE
    ├── MANIFEST.in
    ├── README.md
    ├── fbprophet/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── forecaster.py
    │   ├── make_holidays.py
    │   ├── models.py
    │   ├── plot.py
    │   ├── serialize.py
    │   └── tests/
    │       ├── __init__.py
    │       ├── data.csv
    │       └── test_package.py
    ├── requirements.txt
    └── setup.py
Download .txt
SYMBOL INDEX (233 symbols across 15 files)

FILE: python/prophet/diagnostics.py
  class _SupportsMap (line 40) | class _SupportsMap(Protocol):
    method map (line 41) | def map(self, __f: Callable[..., object], *its: Iterable[object]) -> A...
  function generate_cutoffs (line 47) | def generate_cutoffs(
  function cross_validation (line 93) | def cross_validation(
  function single_cutoff_forecast (line 260) | def single_cutoff_forecast(
  function prophet_copy (line 324) | def prophet_copy(m: _ModelT, cutoff: pd.Timestamp | None = None) -> _Mod...
  function register_performance_metric (line 382) | def register_performance_metric(func: _PerformanceMetricT) -> _Performan...
  function performance_metrics (line 398) | def performance_metrics(
  function rolling_mean_by_h (line 488) | def rolling_mean_by_h(x: np.ndarray, h: np.ndarray, w: int, name: str) -...
  function rolling_median_by_h (line 541) | def rolling_median_by_h(x: np.ndarray, h: np.ndarray, w: int, name: str)...
  function mse (line 599) | def mse(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function rmse (line 623) | def rmse(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function mae (line 642) | def mae(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function mape (line 666) | def mape(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function mdape (line 690) | def mdape(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function smape (line 714) | def smape(df: pd.DataFrame, w: int) -> pd.DataFrame:
  function coverage (line 740) | def coverage(df: pd.DataFrame, w: int) -> pd.DataFrame:

FILE: python/prophet/forecaster.py
  class Prophet (line 35) | class Prophet:
    method __init__ (line 128) | def __init__(
    method _load_stan_backend (line 201) | def _load_stan_backend(self, stan_backend: str | None) -> None:
    method validate_inputs (line 216) | def validate_inputs(self) -> None:
    method validate_column_name (line 260) | def validate_column_name(
    method setup_dataframe (line 315) | def setup_dataframe(self, df: pd.DataFrame, initialize_scales: bool = ...
    method initialize_scales (line 407) | def initialize_scales(self, initialize_scales: bool, df: pd.DataFrame)...
    method set_changepoints (line 456) | def set_changepoints(self) -> None:
    method fourier_series (line 504) | def fourier_series(
    method make_seasonality_features (line 537) | def make_seasonality_features(
    method construct_holiday_dataframe (line 565) | def construct_holiday_dataframe(self, dates: pd.Series[pd.Timestamp]) ...
    method make_holiday_features (line 612) | def make_holiday_features(
    method add_regressor (line 687) | def add_regressor(
    method add_seasonality (line 743) | def add_seasonality(
    method add_country_holidays (line 815) | def add_country_holidays(self, country_name: str) -> Self:
    method make_all_seasonality_features (line 856) | def make_all_seasonality_features(self, df: pd.DataFrame) -> tuple[
    method regressor_column_matrix (line 927) | def regressor_column_matrix(
    method add_group_component (line 998) | def add_group_component(
    method parse_seasonality_args (line 1024) | def parse_seasonality_args(
    method set_auto_seasonalities (line 1067) | def set_auto_seasonalities(self) -> None:
    method linear_growth_init (line 1124) | def linear_growth_init(df: pd.DataFrame) -> tuple[float, float]:
    method logistic_growth_init (line 1148) | def logistic_growth_init(df: pd.DataFrame) -> tuple[float, float]:
    method flat_growth_init (line 1190) | def flat_growth_init(df: pd.DataFrame) -> tuple[float, float]:
    method preprocess (line 1210) | def preprocess(self, df: pd.DataFrame, **kwargs: Any) -> ModelInputData:
    method calculate_initial_params (line 1258) | def calculate_initial_params(self, num_total_regressors: int) -> Model...
    method fit (line 1282) | def fit(self, df: pd.DataFrame, **kwargs: Any) -> Self:
    method predict (line 1342) | def predict(self, df: pd.DataFrame | None = None, vectorized: bool = T...
    method piecewise_linear (line 1390) | def piecewise_linear(
    method piecewise_logistic (line 1417) | def piecewise_logistic(
    method flat_trend (line 1461) | def flat_trend(
    method predict_trend (line 1479) | def predict_trend(
    method predict_seasonal_components (line 1511) | def predict_seasonal_components(self, df: pd.DataFrame) -> pd.DataFrame:
    method predict_uncertainty (line 1546) | def predict_uncertainty(self, df: pd.DataFrame, vectorized: bool) -> p...
    method sample_posterior_predictive (line 1572) | def sample_posterior_predictive(
    method sample_model (line 1624) | def sample_model(
    method sample_model_vectorized (line 1662) | def sample_model_vectorized(
    method sample_predictive_trend (line 1704) | def sample_predictive_trend(self, df: pd.DataFrame, iteration: int) ->...
    method sample_predictive_trend_vectorized (line 1759) | def sample_predictive_trend_vectorized(
    method _sample_uncertainty (line 1804) | def _sample_uncertainty(
    method _make_trend_shift_matrix (line 1867) | def _make_trend_shift_matrix(
    method _make_historical_mat_time (line 1884) | def _make_historical_mat_time(
    method _logistic_uncertainty (line 1908) | def _logistic_uncertainty(
    method predictive_samples (line 1969) | def predictive_samples(self, df: pd.DataFrame, vectorized: bool = True...
    method percentile (line 1994) | def percentile(self, a: npt.ArrayLike, *args: Any, **kwargs: Any) -> n...
    method make_future_dataframe (line 2005) | def make_future_dataframe(
    method plot (line 2043) | def plot(
    method plot_components (line 2078) | def plot_components(

FILE: python/prophet/make_holidays.py
  function get_country_holidays_class (line 14) | def get_country_holidays_class(country: str) -> type[holidays.HolidayBase]:
  function get_holiday_names (line 36) | def get_holiday_names(country: str) -> set[str]:
  function make_holidays_df (line 51) | def make_holidays_df(

FILE: python/prophet/models.py
  class _IStanBackendOptions (line 29) | class _IStanBackendOptions(TypedDict, total=False):
  class TrendIndicator (line 34) | class TrendIndicator(Enum):
  class ModelInputData (line 40) | class ModelInputData:
  class ModelParams (line 56) | class ModelParams:
  class IStanBackend (line 64) | class IStanBackend(ABC):
    method __init__ (line 69) | def __init__(self) -> None:
    method set_options (line 74) | def set_options(self, **kwargs: Unpack[_IStanBackendOptions]) -> None:
    method cleanup (line 85) | def cleanup(self) -> None:
    method get_type (line 92) | def get_type() -> str:
    method load_model (line 96) | def load_model(self) -> Any:
    method fit (line 100) | def fit(
    method sampling (line 109) | def sampling(
  class CmdStanPyBackend (line 119) | class CmdStanPyBackend(IStanBackend):
    method __init__ (line 125) | def __init__(self) -> None:
    method get_type (line 137) | def get_type() -> str:
    method load_model (line 140) | def load_model(self) -> CmdStanModel:
    method fit (line 145) | def fit(
    method sampling (line 179) | def sampling(
    method cleanup (line 219) | def cleanup(self) -> None:
    method sanitize_custom_inits (line 235) | def sanitize_custom_inits(
    method prepare_data (line 254) | def prepare_data(
    method stan_to_dict_numpy (line 285) | def stan_to_dict_numpy(
  class StanBackendEnum (line 328) | class StanBackendEnum(Enum):
    method get_backend_class (line 332) | def get_backend_class(name: str) -> type[IStanBackend]:

FILE: python/prophet/plot.py
  class _PlotlyProps (line 29) | class _PlotlyProps(TypedDict):
  function plot (line 60) | def plot(
  function plot_components (line 123) | def plot_components(
  function plot_forecast_component (line 234) | def plot_forecast_component(
  function seasonality_plot_df (line 289) | def seasonality_plot_df(
  function plot_weekly (line 316) | def plot_weekly(
  function plot_yearly (line 369) | def plot_yearly(
  function plot_seasonality (line 423) | def plot_seasonality(
  function set_y_as_percent (line 498) | def set_y_as_percent(ax: _AxT) -> _AxT:
  function add_changepoints_to_plot (line 506) | def add_changepoints_to_plot(
  function plot_cross_validation_metric (line 548) | def plot_cross_validation_metric(
  function plot_plotly (line 638) | def plot_plotly(
  function plot_components_plotly (line 807) | def plot_components_plotly(
  function plot_forecast_component_plotly (line 875) | def plot_forecast_component_plotly(
  function plot_seasonality_plotly (line 913) | def plot_seasonality_plotly(
  function get_forecast_component_plotly_props (line 946) | def get_forecast_component_plotly_props(
  function get_seasonality_plotly_props (line 1061) | def get_seasonality_plotly_props(

FILE: python/prophet/serialize.py
  function model_to_dict (line 42) | def model_to_dict(model: Prophet) -> dict[str, Any]:
  function model_to_json (line 109) | def model_to_json(model: Prophet) -> str:
  function _handle_simple_attributes_backwards_compat (line 128) | def _handle_simple_attributes_backwards_compat(model_dict: dict[str, Any...
  function model_from_dict (line 138) | def model_from_dict(model_dict: dict[str, Any]) -> Prophet:
  function model_from_json (line 200) | def model_from_json(model_json: str) -> Prophet:

FILE: python/prophet/tests/conftest.py
  function daily_univariate_ts (line 8) | def daily_univariate_ts() -> pd.DataFrame:
  function subdaily_univariate_ts (line 14) | def subdaily_univariate_ts() -> pd.DataFrame:
  function large_numbers_ts (line 20) | def large_numbers_ts() -> pd.DataFrame:
  function pytest_configure (line 25) | def pytest_configure(config):
  function pytest_addoption (line 29) | def pytest_addoption(parser):
  function pytest_collection_modifyitems (line 39) | def pytest_collection_modifyitems(config, items):
  function pytest_generate_tests (line 48) | def pytest_generate_tests(metafunc):

FILE: python/prophet/tests/test_diagnostics.py
  function ts_short (line 17) | def ts_short(daily_univariate_ts):
  class CustomParallelBackend (line 21) | class CustomParallelBackend:
    method map (line 22) | def map(self, func, *iterables):
  function mase (line 37) | def mase(df, w):
  class TestCrossValidation (line 58) | class TestCrossValidation:
    method test_cross_validation (line 60) | def test_cross_validation(self, ts_short, parallel_method, backend):
    method test_bad_parallel_methods (line 87) | def test_bad_parallel_methods(self, ts_short, backend):
    method test_check_single_cutoff_forecast_func_calls (line 97) | def test_check_single_cutoff_forecast_func_calls(self, ts_short, monke...
    method test_check_extra_output_columns_cross_validation (line 127) | def test_check_extra_output_columns_cross_validation(self, ts_short, b...
    method test_cross_validation_logistic_or_flat_growth (line 140) | def test_cross_validation_logistic_or_flat_growth(self, growth, ts_sho...
    method test_cross_validation_extra_regressors (line 153) | def test_cross_validation_extra_regressors(self, ts_short, backend):
    method test_cross_validation_default_value_check (line 180) | def test_cross_validation_default_value_check(self, ts_short, backend):
    method test_cross_validation_custom_cutoffs (line 191) | def test_cross_validation_custom_cutoffs(self, ts_short, backend):
    method test_cross_validation_uncertainty_disabled (line 204) | def test_cross_validation_uncertainty_disabled(self, ts_short, backend):
  class TestPerformanceMetrics (line 218) | class TestPerformanceMetrics:
    method test_performance_metrics (line 219) | def test_performance_metrics(self, ts_short, backend):
    method test_rolling_mean (line 284) | def test_rolling_mean(self):
    method test_rolling_median (line 306) | def test_rolling_median(self):
  class TestProphetCopy (line 330) | class TestProphetCopy:
    method data (line 332) | def data(self, daily_univariate_ts):
    method test_prophet_copy (line 338) | def test_prophet_copy(self, data, backend):
    method test_prophet_copy_custom (line 392) | def test_prophet_copy_custom(self, data, backend):

FILE: python/prophet/tests/test_prophet.py
  function train_test_split (line 14) | def train_test_split(ts_data: pd.DataFrame, n_test_rows: int) -> pd.Data...
  function rmse (line 20) | def rmse(predictions, targets) -> float:
  class TestProphetFitPredictDefault (line 24) | class TestProphetFitPredictDefault:
    method test_fit_predict (line 30) | def test_fit_predict(self, daily_univariate_ts, backend, scaling, expe...
    method test_fit_predict_newton (line 47) | def test_fit_predict_newton(self, daily_univariate_ts, backend, scalin...
    method test_fit_predict_large_numbers (line 63) | def test_fit_predict_large_numbers(self, large_numbers_ts, backend, sc...
    method test_fit_predict_sampling (line 75) | def test_fit_predict_sampling(self, daily_univariate_ts, backend):
    method test_fit_predict_no_seasons (line 88) | def test_fit_predict_no_seasons(self, daily_univariate_ts, backend):
    method test_fit_predict_no_changepoints (line 99) | def test_fit_predict_no_changepoints(self, daily_univariate_ts, backend):
    method test_fit_predict_no_changepoints_mcmc (line 109) | def test_fit_predict_no_changepoints_mcmc(self, daily_univariate_ts, b...
    method test_fit_changepoint_not_in_history (line 118) | def test_fit_changepoint_not_in_history(self, daily_univariate_ts, bac...
    method test_fit_predict_duplicates (line 130) | def test_fit_predict_duplicates(self, daily_univariate_ts, backend):
    method test_fit_predict_constant_history (line 144) | def test_fit_predict_constant_history(self, daily_univariate_ts, backe...
    method test_fit_predict_uncertainty_disabled (line 156) | def test_fit_predict_uncertainty_disabled(self, daily_univariate_ts, b...
  class TestProphetDataPrep (line 174) | class TestProphetDataPrep:
    method test_setup_dataframe (line 175) | def test_setup_dataframe(self, daily_univariate_ts, backend):
    method test_setup_dataframe_ds_column (line 188) | def test_setup_dataframe_ds_column(self, daily_univariate_ts, backend):
    method test_logistic_floor (line 197) | def test_logistic_floor(self, daily_univariate_ts, backend):
    method test_logistic_floor_minmax (line 213) | def test_logistic_floor_minmax(self, daily_univariate_ts, backend):
    method test_make_future_dataframe (line 233) | def test_make_future_dataframe(self, daily_univariate_ts, backend):
    method test_make_future_dataframe_include_history (line 247) | def test_make_future_dataframe_include_history(self, daily_univariate_...
  class TestProphetTrendComponent (line 258) | class TestProphetTrendComponent:
    method test_invalid_growth_input (line 259) | def test_invalid_growth_input(self, backend):
    method test_growth_init (line 264) | def test_growth_init(self, daily_univariate_ts, backend):
    method test_growth_init_minmax (line 283) | def test_growth_init_minmax(self, daily_univariate_ts, backend):
    method test_flat_growth (line 303) | def test_flat_growth(self, backend, scaling):
    method test_piecewise_linear (line 321) | def test_piecewise_linear(self, backend):
    method test_piecewise_logistic (line 339) | def test_piecewise_logistic(self, backend):
    method test_flat_trend (line 372) | def test_flat_trend(self, backend):
    method test_get_changepoints (line 384) | def test_get_changepoints(self, daily_univariate_ts, backend):
    method test_set_changepoint_range (line 400) | def test_set_changepoint_range(self, daily_univariate_ts, backend):
    method test_get_zero_changepoints (line 416) | def test_get_zero_changepoints(self, daily_univariate_ts, backend):
    method test_override_n_changepoints (line 426) | def test_override_n_changepoints(self, daily_univariate_ts, backend):
  class TestProphetSeasonalComponent (line 437) | class TestProphetSeasonalComponent:
    method test_fourier_series_weekly (line 438) | def test_fourier_series_weekly(self, daily_univariate_ts):
    method test_fourier_series_yearly (line 444) | def test_fourier_series_yearly(self, daily_univariate_ts):
    method test_auto_weekly_seasonality (line 452) | def test_auto_weekly_seasonality(self, daily_univariate_ts, backend):
    method test_auto_yearly_seasonality (line 489) | def test_auto_yearly_seasonality(self, daily_univariate_ts, backend):
    method test_auto_daily_seasonality (line 520) | def test_auto_daily_seasonality(self, daily_univariate_ts, subdaily_un...
    method test_set_seasonality_mode (line 554) | def test_set_seasonality_mode(self, backend):
    method test_set_holidays_mode (line 563) | def test_set_holidays_mode(self, backend):
    method test_seasonality_modes (line 574) | def test_seasonality_modes(self, daily_univariate_ts, backend):
  class TestProphetCustomSeasonalComponent (line 615) | class TestProphetCustomSeasonalComponent:
    method test_custom_monthly_seasonality (line 616) | def test_custom_monthly_seasonality(self, backend):
    method test_duplicate_component_names (line 627) | def test_duplicate_component_names(self, backend):
    method test_custom_fourier_order (line 643) | def test_custom_fourier_order(self, backend):
    method test_custom_priors (line 651) | def test_custom_priors(self, daily_univariate_ts, backend):
    method test_conditional_custom_seasonality (line 690) | def test_conditional_custom_seasonality(self, daily_univariate_ts, bac...
  class TestProphetHolidays (line 731) | class TestProphetHolidays:
    method test_holidays_lower_window (line 732) | def test_holidays_lower_window(self, backend):
    method test_holidays_upper_window (line 749) | def test_holidays_upper_window(self, backend):
    method test_holidays_priors (line 766) | def test_holidays_priors(self, backend):
    method test_holidays_bad_priors (line 812) | def test_holidays_bad_priors(self, backend):
    method test_fit_with_holidays (line 828) | def test_fit_with_holidays(self, daily_univariate_ts, backend):
    method test_fit_predict_with_country_holidays (line 840) | def test_fit_predict_with_country_holidays(self, daily_univariate_ts, ...
    method test_subdaily_holidays (line 867) | def test_subdaily_holidays(self, subdaily_univariate_ts, backend):
  class TestProphetRegressors (line 881) | class TestProphetRegressors:
    method test_added_regressors (line 882) | def test_added_regressors(self, daily_univariate_ts, backend):
    method test_constant_regressor (line 960) | def test_constant_regressor(self, daily_univariate_ts, backend):
  class TestProphetWarmStart (line 969) | class TestProphetWarmStart:
    method test_fit_warm_start (line 970) | def test_fit_warm_start(self, daily_univariate_ts, backend):
    method test_sampling_warm_start (line 977) | def test_sampling_warm_start(self, daily_univariate_ts, backend):

FILE: python/prophet/tests/test_serialize.py
  class TestSerialize (line 17) | class TestSerialize:
    method test_simple_serialize (line 18) | def test_simple_serialize(self, daily_univariate_ts, backend):
    method test_full_serialize (line 60) | def test_full_serialize(self, daily_univariate_ts, backend):
    method test_backwards_compatibility (line 132) | def test_backwards_compatibility(self):

FILE: python/prophet/tests/test_utilities.py
  class TestUtilities (line 12) | class TestUtilities:
    method test_regressor_coefficients (line 13) | def test_regressor_coefficients(self, daily_univariate_ts, backend):

FILE: python/prophet/utilities.py
  function regressor_index (line 18) | def regressor_index(m: Prophet, name: str) -> np.intp:
  function regressor_coefficients (line 33) | def regressor_coefficients(m: Prophet) -> pd.DataFrame:
  function warm_start_params (line 84) | def warm_start_params(m: Prophet) -> dict[str, npt.NDArray[np.float64] |...

FILE: python/scripts/generate_holidays_file.py
  function utf8_to_ascii (line 16) | def utf8_to_ascii(text: str) -> str:
  function generate_holidays_df (line 31) | def generate_holidays_df() -> pd.DataFrame:

FILE: python/setup.py
  function prune_cmdstan (line 32) | def prune_cmdstan(cmdstan_dir: str) -> None:
  function repackage_cmdstan (line 58) | def repackage_cmdstan():
  function maybe_install_cmdstan_toolchain (line 62) | def maybe_install_cmdstan_toolchain() -> bool:
  function install_cmdstan_deps (line 80) | def install_cmdstan_deps(cmdstan_dir: Path):
  function build_cmdstan_model (line 102) | def build_cmdstan_model(target_dir):
  function get_backends_from_env (line 142) | def get_backends_from_env() -> List[str]:
  function build_models (line 146) | def build_models(target_dir):
  class BuildPyCommand (line 154) | class BuildPyCommand(build_py):
    method run (line 157) | def run(self):
  class BuildExtCommand (line 166) | class BuildExtCommand(build_ext):
    method run (line 169) | def run(self):
  class EditableWheel (line 173) | class EditableWheel(editable_wheel):
    method run (line 176) | def run(self):
  class BDistWheelABINone (line 185) | class BDistWheelABINone(bdist_wheel):
    method finalize_options (line 186) | def finalize_options(self):
    method get_tag (line 190) | def get_tag(self):

FILE: python_shim/fbprophet/tests/test_package.py
  class TestFbprophet (line 21) | class TestFbprophet(TestCase):
    method test_shim (line 23) | def test_shim(self):
Condensed preview — 277 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9,647K chars).
[
  {
    "path": ".deepsource.toml",
    "chars": 232,
    "preview": "version = 1\r\n\r\ntest_patterns = [\"python/prophet/tests/**\"]\r\nexclude_patterns = [\"R/**\", \"notebooks/**\", \"docs/**\", \"exam"
  },
  {
    "path": ".gitattributes",
    "chars": 99,
    "preview": "docs/* linguist-documentation\nexamples/* linguist-documentation\nnotebooks/* linguist-documentation\n"
  },
  {
    "path": ".github/workflows/build-and-test.yml",
    "chars": 3475,
    "preview": "name: Build\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  build-and-test-python:\n\n"
  },
  {
    "path": ".github/workflows/wheel.yml",
    "chars": 3165,
    "preview": "name: \"Create Python distributions and upload to PyPI\"\n\non:\n  release:\n    types: [ published ]\n  workflow_dispatch: {}\n"
  },
  {
    "path": ".gitignore",
    "chars": 609,
    "preview": "# Compiled python modules.\n*.pyc\n\n# Persisted models.\n*.pkl\n\n# Setuptools distribution folder.\npython/dist/\npython_shim/"
  },
  {
    "path": ".travis.yml",
    "chars": 1120,
    "preview": "dist: xenial\naddons:\n  apt:\n    packages:\n      - libv8-dev\nlanguage: python\n\njobs:\n  include:\n    - language: python\n  "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 241,
    "preview": "# Code of Conduct\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read "
  },
  {
    "path": "Dockerfile",
    "chars": 174,
    "preview": "FROM python:3.7-stretch\n\nRUN apt-get -y install libc-dev\n\nRUN pip install --upgrade pip\n\nCOPY . .\n\nWORKDIR python\n\nRUN p"
  },
  {
    "path": "LICENSE",
    "chars": 1086,
    "preview": "MIT License\n\nCopyright (c) Facebook, Inc. and its affiliates.\n\nPermission is hereby granted, free of charge, to any pers"
  },
  {
    "path": "Makefile",
    "chars": 117,
    "preview": "build:\n\tdocker-compose build\n\npy-shell:\n\tdocker-compose run package ipython\n\nshell:\n\tdocker-compose run package bash\n"
  },
  {
    "path": "R/.Rbuildignore",
    "chars": 79,
    "preview": "^renv$\n^renv\\.lock$\n^data-raw$\n^libs$\n^doc$\n^Meta$\n^.*\\.Rproj$\n^\\.Rproj\\.user$\n"
  },
  {
    "path": "R/.gitignore",
    "chars": 737,
    "preview": ".DS_Store\n\n# History files\n.Rhistory\n.Rapp.history\n\n# Session Data files\n.RData\n\n# User-specific files\n.Ruserdata\n\n# Exa"
  },
  {
    "path": "R/DESCRIPTION",
    "chars": 1640,
    "preview": "Package: prophet\nTitle: Automatic Forecasting Procedure\nVersion: 1.2.2\nDate: 2026-01-25\nAuthors@R: c(\n  person(\"Cuong\", "
  },
  {
    "path": "R/LICENSE",
    "chars": 52,
    "preview": "YEAR: 2017-present\nCOPYRIGHT HOLDER: Facebook, Inc.\n"
  },
  {
    "path": "R/NAMESPACE",
    "chars": 662,
    "preview": "# Generated by roxygen2: do not edit by hand\n\nS3method(plot,prophet)\nS3method(predict,prophet)\nexport(add_changepoints_t"
  },
  {
    "path": "R/R/data.R",
    "chars": 567,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/diagnostics.R",
    "chars": 18195,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/make_holidays.R",
    "chars": 1536,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/plot.R",
    "chars": 20233,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/prophet.R",
    "chars": 56231,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/stan_backends.R",
    "chars": 7265,
    "preview": "#' Get the stan backend defined in the environment variables.\n#'\n#' @return 'rstan' or 'cmdstanr'. 'rstan' if variable i"
  },
  {
    "path": "R/R/stanmodels.R",
    "chars": 1037,
    "preview": "# Generated by rstantools.  Do not edit by hand.\n\n# names of stan models\nstanmodels <- c(\"prophet\")\n\n# load each stan mo"
  },
  {
    "path": "R/R/utilities.R",
    "chars": 2630,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/R/zzz.R",
    "chars": 1016,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/configure",
    "chars": 117,
    "preview": "# Generated by rstantools.  Do not edit by hand.\n\n#! /bin/sh\n\"${R_HOME}/bin/Rscript\" -e \"rstantools::rstan_config()\"\n"
  },
  {
    "path": "R/configure.win",
    "chars": 134,
    "preview": "# Generated by rstantools.  Do not edit by hand.\n\n#! /bin/sh\n\"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe\" -e \"rstantools::rs"
  },
  {
    "path": "R/data-raw/generated_holidays.R",
    "chars": 440,
    "preview": "## Copyright (c) 2017-present, Facebook, Inc.\n## All rights reserved.\n\n## This source code is licensed under the BSD-sty"
  },
  {
    "path": "R/inst/include/stan_meta_header.hpp",
    "chars": 48,
    "preview": "// Insert all #include<foo.hpp> statements here\n"
  },
  {
    "path": "R/inst/stan/prophet.stan",
    "chars": 3631,
    "preview": "// Copyright (c) Facebook, Inc. and its affiliates.\n\n// This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "R/man/add_changepoints_to_plot.Rd",
    "chars": 959,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{add_changepoints_to_plot}\n\\al"
  },
  {
    "path": "R/man/add_country_holidays.Rd",
    "chars": 762,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{add_country_holidays}\n\\ali"
  },
  {
    "path": "R/man/add_group_component.Rd",
    "chars": 594,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{add_group_component}\n\\alia"
  },
  {
    "path": "R/man/add_regressor.Rd",
    "chars": 1441,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{add_regressor}\n\\alias{add_"
  },
  {
    "path": "R/man/add_seasonality.Rd",
    "chars": 1701,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{add_seasonality}\n\\alias{ad"
  },
  {
    "path": "R/man/check_cmdstanr.Rd",
    "chars": 451,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{check_cmdstanr}\n\\ali"
  },
  {
    "path": "R/man/construct_holiday_dataframe.Rd",
    "chars": 528,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{construct_holiday_datafram"
  },
  {
    "path": "R/man/coverage.Rd",
    "chars": 338,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{coverage}\n\\alias{cover"
  },
  {
    "path": "R/man/cross_validation.Rd",
    "chars": 1370,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{cross_validation}\n\\ali"
  },
  {
    "path": "R/man/df_for_plotting.Rd",
    "chars": 386,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{df_for_plotting}\n\\alias{df_fo"
  },
  {
    "path": "R/man/dot-fit.Rd",
    "chars": 675,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{.fit}\n\\alias{.fit}\n\\"
  },
  {
    "path": "R/man/dot-load_model.Rd",
    "chars": 411,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{.load_model}\n\\alias{"
  },
  {
    "path": "R/man/dot-sampling.Rd",
    "chars": 683,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{.sampling}\n\\alias{.s"
  },
  {
    "path": "R/man/dot-stan_args.Rd",
    "chars": 846,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{.stan_args}\n\\alias{."
  },
  {
    "path": "R/man/dyplot.prophet.Rd",
    "chars": 945,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{dyplot.prophet}\n\\alias{dyplot"
  },
  {
    "path": "R/man/fit.prophet.Rd",
    "chars": 769,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{fit.prophet}\n\\alias{fit.pr"
  },
  {
    "path": "R/man/flat_growth_init.Rd",
    "chars": 616,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{flat_growth_init}\n\\alias{f"
  },
  {
    "path": "R/man/flat_trend.Rd",
    "chars": 395,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{flat_trend}\n\\alias{flat_tr"
  },
  {
    "path": "R/man/fourier_series.Rd",
    "chars": 559,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{fourier_series}\n\\alias{fou"
  },
  {
    "path": "R/man/generate_cutoffs.Rd",
    "chars": 530,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{generate_cutoffs}\n\\ali"
  },
  {
    "path": "R/man/generated_holidays.Rd",
    "chars": 570,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/data.R\n\\docType{data}\n\\name{generated_holi"
  },
  {
    "path": "R/man/get_holiday_names.Rd",
    "chars": 469,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/make_holidays.R\n\\name{get_holiday_names}\n\\"
  },
  {
    "path": "R/man/get_stan_backend.Rd",
    "chars": 398,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stan_backends.R\n\\name{get_stan_backend}\n\\a"
  },
  {
    "path": "R/man/initialize_scales_fn.Rd",
    "chars": 489,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{initialize_scales_fn}\n\\ali"
  },
  {
    "path": "R/man/linear_growth_init.Rd",
    "chars": 624,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{linear_growth_init}\n\\alias"
  },
  {
    "path": "R/man/logistic_growth_init.Rd",
    "chars": 664,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{logistic_growth_init}\n\\ali"
  },
  {
    "path": "R/man/mae.Rd",
    "chars": 357,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{mae}\n\\alias{mae}\n\\titl"
  },
  {
    "path": "R/man/make_all_seasonality_features.Rd",
    "chars": 993,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{make_all_seasonality_featu"
  },
  {
    "path": "R/man/make_future_dataframe.Rd",
    "chars": 761,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{make_future_dataframe}\n\\al"
  },
  {
    "path": "R/man/make_holiday_features.Rd",
    "chars": 721,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{make_holiday_features}\n\\al"
  },
  {
    "path": "R/man/make_holidays_df.Rd",
    "chars": 576,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/make_holidays.R\n\\name{make_holidays_df}\n\\a"
  },
  {
    "path": "R/man/make_seasonality_features.Rd",
    "chars": 556,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{make_seasonality_features}"
  },
  {
    "path": "R/man/mape.Rd",
    "chars": 384,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{mape}\n\\alias{mape}\n\\ti"
  },
  {
    "path": "R/man/mdape.Rd",
    "chars": 393,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{mdape}\n\\alias{mdape}\n\\"
  },
  {
    "path": "R/man/mse.Rd",
    "chars": 354,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{mse}\n\\alias{mse}\n\\titl"
  },
  {
    "path": "R/man/parse_seasonality_args.Rd",
    "chars": 748,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{parse_seasonality_args}\n\\a"
  },
  {
    "path": "R/man/performance_metrics.Rd",
    "chars": 2148,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{performance_metrics}\n\\"
  },
  {
    "path": "R/man/piecewise_linear.Rd",
    "chars": 596,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{piecewise_linear}\n\\alias{p"
  },
  {
    "path": "R/man/piecewise_logistic.Rd",
    "chars": 656,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{piecewise_logistic}\n\\alias"
  },
  {
    "path": "R/man/plot.prophet.Rd",
    "chars": 1174,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot.prophet}\n\\alias{plot.pro"
  },
  {
    "path": "R/man/plot_cross_validation_metric.Rd",
    "chars": 1457,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot_cross_validation_metric}"
  },
  {
    "path": "R/man/plot_forecast_component.Rd",
    "chars": 749,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot_forecast_component}\n\\ali"
  },
  {
    "path": "R/man/plot_seasonality.Rd",
    "chars": 542,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot_seasonality}\n\\alias{plot"
  },
  {
    "path": "R/man/plot_weekly.Rd",
    "chars": 782,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot_weekly}\n\\alias{plot_week"
  },
  {
    "path": "R/man/plot_yearly.Rd",
    "chars": 781,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot_yearly}\n\\alias{plot_year"
  },
  {
    "path": "R/man/predict.prophet.Rd",
    "chars": 872,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{predict.prophet}\n\\alias{pr"
  },
  {
    "path": "R/man/predict_seasonal_components.Rd",
    "chars": 495,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{predict_seasonal_component"
  },
  {
    "path": "R/man/predict_trend.Rd",
    "chars": 414,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{predict_trend}\n\\alias{pred"
  },
  {
    "path": "R/man/predict_uncertainty.Rd",
    "chars": 443,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{predict_uncertainty}\n\\alia"
  },
  {
    "path": "R/man/predictive_samples.Rd",
    "chars": 559,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{predictive_samples}\n\\alias"
  },
  {
    "path": "R/man/prophet.Rd",
    "chars": 4292,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{prophet}\n\\alias{prophet}\n\\"
  },
  {
    "path": "R/man/prophet_copy.Rd",
    "chars": 494,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{prophet_copy}\n\\alias{p"
  },
  {
    "path": "R/man/prophet_plot_components.Rd",
    "chars": 1672,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{prophet_plot_components}\n\\ali"
  },
  {
    "path": "R/man/regressor_coefficients.Rd",
    "chars": 1323,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utilities.R\n\\name{regressor_coefficients}\n"
  },
  {
    "path": "R/man/regressor_column_matrix.Rd",
    "chars": 974,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{regressor_column_matrix}\n\\"
  },
  {
    "path": "R/man/rmse.Rd",
    "chars": 372,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{rmse}\n\\alias{rmse}\n\\ti"
  },
  {
    "path": "R/man/rolling_mean_by_h.Rd",
    "chars": 656,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{rolling_mean_by_h}\n\\al"
  },
  {
    "path": "R/man/rolling_median_by_h.Rd",
    "chars": 749,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{rolling_median_by_h}\n\\"
  },
  {
    "path": "R/man/sample_model.Rd",
    "chars": 738,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{sample_model}\n\\alias{sampl"
  },
  {
    "path": "R/man/sample_posterior_predictive.Rd",
    "chars": 498,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{sample_posterior_predictiv"
  },
  {
    "path": "R/man/sample_predictive_trend.Rd",
    "chars": 561,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{sample_predictive_trend}\n\\"
  },
  {
    "path": "R/man/seasonality_plot_df.Rd",
    "chars": 460,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{seasonality_plot_df}\n\\alias{s"
  },
  {
    "path": "R/man/set_auto_seasonalities.Rd",
    "chars": 659,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{set_auto_seasonalities}\n\\a"
  },
  {
    "path": "R/man/set_changepoints.Rd",
    "chars": 556,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{set_changepoints}\n\\alias{s"
  },
  {
    "path": "R/man/set_date.Rd",
    "chars": 381,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{set_date}\n\\alias{set_date}"
  },
  {
    "path": "R/man/setup_dataframe.Rd",
    "chars": 721,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{setup_dataframe}\n\\alias{se"
  },
  {
    "path": "R/man/single_cutoff_forecast.Rd",
    "chars": 799,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{single_cutoff_forecast"
  },
  {
    "path": "R/man/smape.Rd",
    "chars": 499,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/diagnostics.R\n\\name{smape}\n\\alias{smape}\n\\"
  },
  {
    "path": "R/man/time_diff.Rd",
    "chars": 462,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{time_diff}\n\\alias{time_dif"
  },
  {
    "path": "R/man/validate_column_name.Rd",
    "chars": 714,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{validate_column_name}\n\\ali"
  },
  {
    "path": "R/man/validate_inputs.Rd",
    "chars": 343,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/prophet.R\n\\name{validate_inputs}\n\\alias{va"
  },
  {
    "path": "R/prophet.Rproj",
    "chars": 395,
    "preview": "Version: 1.0\n\nRestoreWorkspace: Default\nSaveWorkspace: Default\nAlwaysSaveHistory: Default\n\nEnableCodeIndexing: Yes\nUseSp"
  },
  {
    "path": "R/src/Makevars",
    "chars": 902,
    "preview": "# Generated by rstantools.  Do not edit by hand.\n\nSTANHEADERS_SRC = $(shell \"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript\" -e \"mes"
  },
  {
    "path": "R/src/Makevars.win",
    "chars": 878,
    "preview": "# Generated by rstantools.  Do not edit by hand.\n\nSTANHEADERS_SRC = $(shell \"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript\" -e \"mes"
  },
  {
    "path": "R/tests/testthat/data.csv",
    "chars": 8628,
    "preview": "ds,y\n2012-05-18,38.23\n2012-05-21,34.03\n2012-05-22,31.0\n2012-05-23,32.0\n2012-05-24,33.03\n2012-05-25,31.91\n2012-05-29,28.8"
  },
  {
    "path": "R/tests/testthat/data2.csv",
    "chars": 21518,
    "preview": "ds,y\n2017-01-01 00:05:00,0.0\n2017-01-01 00:10:00,0.0\n2017-01-01 00:15:00,0.0\n2017-01-01 00:20:00,0.0\n2017-01-01 00:25:00"
  },
  {
    "path": "R/tests/testthat/test_diagnostics.R",
    "chars": 10966,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/tests/testthat/test_prophet.R",
    "chars": 26915,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/tests/testthat/test_stan_functions.R",
    "chars": 3267,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/tests/testthat/test_utilities.R",
    "chars": 1614,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/tests/testthat.R",
    "chars": 262,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n\n# This source code is licensed under the MIT license found in the\n# "
  },
  {
    "path": "R/vignettes/quick_start.Rmd",
    "chars": 1867,
    "preview": "---\ntitle: \"Quick Start Guide to Using Prophet\"\nauthor: \"Sean J. Taylor and Ben Letham\"\ndate: \"`r Sys.Date()`\"\noutput: r"
  },
  {
    "path": "README.md",
    "chars": 11658,
    "preview": "\n# Prophet: Automatic Forecasting Procedure\n\n![Build](https://github.com/facebook/prophet/workflows/Build/badge.svg)\n\n[!"
  },
  {
    "path": "docker-compose.yml",
    "chars": 156,
    "preview": "version: \"3\"\nservices:\n  package:\n    image: facebook/prophet\n    build:\n      context: .\n      dockerfile: Dockerfile\n\n"
  },
  {
    "path": "docs/.gitignore",
    "chars": 73,
    "preview": ".DS_STORE\n_site/\n*.swo\n*.swp\n_site\n.sass-cache\n*.psd\n*~\n.jekyll-metadata\n"
  },
  {
    "path": "docs/CONTRIBUTING.md",
    "chars": 5216,
    "preview": "This provides guidance on how to contribute various content to the Prophet documentation.\n\n## Getting started\n\nYou shoul"
  },
  {
    "path": "docs/Gemfile",
    "chars": 74,
    "preview": "source 'https://rubygems.org'\n\ngem 'github-pages', group: :jekyll_plugins\n"
  },
  {
    "path": "docs/LICENSE",
    "chars": 18105,
    "preview": "Attribution 4.0 International\n\n=======================================================================\n\nCreative Commons"
  },
  {
    "path": "docs/Makefile",
    "chars": 324,
    "preview": "notebooks:\n\tfor f in ../notebooks/*.ipynb; \\\n\tdo \\\n\t    NAME=$$(basename $$f .ipynb); \\\n\t    jupyter nbconvert --to mark"
  },
  {
    "path": "docs/README.md",
    "chars": 3635,
    "preview": "## User Documentation for Prophet\n\nThis directory will contain the user and feature documentation for Prophet. The docum"
  },
  {
    "path": "docs/_config.yml",
    "chars": 3137,
    "preview": "# Site settings\npermalink: /blog/:year/:month/:day/:title.html\ntitle: Prophet\ntagline: Forecasting at scale.\ndescription"
  },
  {
    "path": "docs/_data/authors.yml",
    "chars": 97,
    "preview": "\nsjt:\n  full_name: Sean J. Taylor\n  fbid: 605889\n\nbletham:\n  full_name: Ben Letham\n  fbid: 605889"
  },
  {
    "path": "docs/_data/features.yml",
    "chars": 1048,
    "preview": "- title: Accurate and fast.\n  text: |\n        Prophet is used in many applications across Facebook for producing reliabl"
  },
  {
    "path": "docs/_data/nav.yml",
    "chars": 127,
    "preview": "- title: Docs\n  href: docs/\n  category: docs\n\n- title: GitHub\n  href: https://github.com/facebook/prophet\n  category: ex"
  },
  {
    "path": "docs/_data/nav_docs.yml",
    "chars": 502,
    "preview": "- title: Documentation\n  items:\n  - id: installation\n  - id: quick_start\n  - id: saturating_forecasts\n  - id: trend_chan"
  },
  {
    "path": "docs/_data/powered_by.yml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/_data/powered_by_highlight.yml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/_data/promo.yml",
    "chars": 504,
    "preview": "# This file determines the list of promotional elements added to the header of \\\n# your site's homepage. Full list of pl"
  },
  {
    "path": "docs/_docs/additional_topics.md",
    "chars": 19136,
    "preview": "---\nlayout: docs\ndocid: \"additional_topics\"\ntitle: \"Additional Topics\"\npermalink: /docs/additional_topics.html\nsubsectio"
  },
  {
    "path": "docs/_docs/contributing.md",
    "chars": 11269,
    "preview": "---\nlayout: docs\ndocid: \"contributing\"\ntitle: \"Getting Help and Contributing\"\npermalink: /docs/contributing.html\n---\n\n--"
  },
  {
    "path": "docs/_docs/diagnostics.md",
    "chars": 21664,
    "preview": "---\nlayout: docs\ndocid: \"diagnostics\"\ntitle: \"Diagnostics\"\npermalink: /docs/diagnostics.html\nsubsections:\n  - title: Cro"
  },
  {
    "path": "docs/_docs/handling_shocks.md",
    "chars": 15613,
    "preview": "---\nlayout: docs\ndocid: \"handling_shocks\"\ntitle: \"Handling Shocks\"\npermalink: /docs/handling_shocks.html\nsubsections:\n  "
  },
  {
    "path": "docs/_docs/holiday_effects.md",
    "chars": 7178,
    "preview": "---\nlayout: docs\ndocid: \"holiday_effects\"\ntitle: \"Holiday Effects\"\npermalink: /docs/holiday_effects.html\n---\n### Modelin"
  },
  {
    "path": "docs/_docs/installation.md",
    "chars": 2208,
    "preview": "---\nlayout: docs\ndocid: \"installation\"\ntitle: \"Installation\"\npermalink: /docs/installation.html\nsubsections:\n  - id: r\n "
  },
  {
    "path": "docs/_docs/multiplicative_seasonality.md",
    "chars": 3234,
    "preview": "---\nlayout: docs\ndocid: \"multiplicative_seasonality\"\ntitle: \"Multiplicative Seasonality\"\npermalink: /docs/multiplicative"
  },
  {
    "path": "docs/_docs/non-daily_data.md",
    "chars": 7395,
    "preview": "---\nlayout: docs\ndocid: \"non-daily_data\"\ntitle: \"Non-Daily Data\"\npermalink: /docs/non-daily_data.html\nsubsections:\n  - t"
  },
  {
    "path": "docs/_docs/outliers.md",
    "chars": 3125,
    "preview": "---\nlayout: docs\ndocid: \"outliers\"\ntitle: \"Outliers\"\npermalink: /docs/outliers.html\nsubsections:\n---\nThere are two main "
  },
  {
    "path": "docs/_docs/quick_start.md",
    "chars": 10024,
    "preview": "---\nlayout: docs\ndocid: \"quick_start\"\ntitle: \"Quick Start\"\npermalink: /docs/quick_start.html\nsubsections:\n  - title: Pyt"
  },
  {
    "path": "docs/_docs/saturating_forecasts.md",
    "chars": 3387,
    "preview": "---\nlayout: docs\ndocid: \"saturating_forecasts\"\ntitle: \"Saturating Forecasts\"\npermalink: /docs/saturating_forecasts.html\n"
  },
  {
    "path": "docs/_docs/seasonality,_holiday_effects,_and_regressors.md",
    "chars": 26222,
    "preview": "---\nlayout: docs\ndocid: \"seasonality,_holiday_effects,_and_regressors\"\ntitle: \"Seasonality, Holiday Effects, And Regress"
  },
  {
    "path": "docs/_docs/trend_changepoints.md",
    "chars": 5299,
    "preview": "---\nlayout: docs\ndocid: \"trend_changepoints\"\ntitle: \"Trend Changepoints\"\npermalink: /docs/trend_changepoints.html\nsubsec"
  },
  {
    "path": "docs/_docs/uncertainty_intervals.md",
    "chars": 3491,
    "preview": "---\nlayout: docs\ndocid: \"uncertainty_intervals\"\ntitle: \"Uncertainty Intervals\"\npermalink: /docs/uncertainty_intervals.ht"
  },
  {
    "path": "docs/_includes/blog_pagination.html",
    "chars": 909,
    "preview": "<!-- Pagination links - copied from http://jekyllrb.com/docs/pagination/ -->\n{% if paginator.total_pages > 1 %}\n<br />\n<"
  },
  {
    "path": "docs/_includes/content/gridblocks.html",
    "chars": 212,
    "preview": "<div class=\"gridBlock\">\n{% for item in {{include.data_source}} %}\n  {% include content/items/gridblock.html item=item la"
  },
  {
    "path": "docs/_includes/content/items/gridblock.html",
    "chars": 966,
    "preview": "{% if include.layout == \"fourColumn\" %}\n  {% assign layout = \"fourByGridBlock\" %}\n{% else %}\n  {% assign layout = \"twoBy"
  },
  {
    "path": "docs/_includes/doc.html",
    "chars": 850,
    "preview": "<div class=\"post\">\n  <header class=\"post-header\">\n    <h1 class=\"post-title\">{% if include.truncate %}<a href=\"{{ page.u"
  },
  {
    "path": "docs/_includes/doc_paging.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/_includes/footer.html",
    "chars": 3785,
    "preview": "<div class=\"footerContainer\">\n  <div id=\"footer_wrap\" class=\"wrapper footerWrapper\">\n    <div class=\"footerBlocks\">\n    "
  },
  {
    "path": "docs/_includes/head.html",
    "chars": 637,
    "preview": "<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"viewport\" content="
  },
  {
    "path": "docs/_includes/header.html",
    "chars": 831,
    "preview": "<div class=\"headerContainer\">\n  <div id=\"header_wrap\" class=\"wrapper headerWrapper\">\n    <div class=\"inner\">\n      <img "
  },
  {
    "path": "docs/_includes/hero.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/_includes/home_header.html",
    "chars": 823,
    "preview": "<div class=\"homeContainer\">\n  <div class=\"homeSplashFade\">\n    <div id=\"home_wrap\" class=\"wrapper homeWrapper\">\n      <d"
  },
  {
    "path": "docs/_includes/katex_import.html",
    "chars": 235,
    "preview": "<script src=\"//code.jquery.com/jquery-1.11.1.min.js\"></script>\n<link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/"
  },
  {
    "path": "docs/_includes/katex_render.html",
    "chars": 6238,
    "preview": "<script type=\"text/javascript\">\n/* global katex */\n\nvar findEndOfMath = function(delimiter, text, startIndex) {\n    // A"
  },
  {
    "path": "docs/_includes/nav/collection_nav.html",
    "chars": 2178,
    "preview": "<div class=\"docsNavContainer\">\n  <nav class=\"toc\" id=\"doc_nav\">\n    <div class=\"toggleNav\" id=\"collection_nav\">\n      <s"
  },
  {
    "path": "docs/_includes/nav/collection_nav_group.html",
    "chars": 661,
    "preview": "<div class=\"navGroup{% if currentgroup == group %} navGroupActive navGroupCurrent{% endif %}\">\n  <h3><i>+</i><span>{{ gr"
  },
  {
    "path": "docs/_includes/nav/collection_nav_group_item.html",
    "chars": 491,
    "preview": "<li class=\"navListItem\">\n    <a class=\"navItem {% if page.url == groupitem.url %} navItemActive {% endif %}\" href=\"{{ gr"
  },
  {
    "path": "docs/_includes/nav/header_nav.html",
    "chars": 1176,
    "preview": "<div id=\"header_nav\">\n  <div class=\"navSlideout\">\n    <i class=\"menuExpand\" id=\"header_nav_expander\"><span></span><span>"
  },
  {
    "path": "docs/_includes/nav.html",
    "chars": 1199,
    "preview": "<div id=\"fixed_header\" class=\"fixedHeaderContainer{% if include.alwayson %} visible{% endif %}\">\n  <div class=\"headerWra"
  },
  {
    "path": "docs/_includes/nav_search.html",
    "chars": 441,
    "preview": "<li class=\"navSearchWrapper\">\n  <input id=\"{{ include.inputselector }}\" type=\"search\" />\n</li>\n<script type=\"text/javasc"
  },
  {
    "path": "docs/_includes/plugins/all_share.html",
    "chars": 166,
    "preview": "<div class=\"pluginBlock allShareBlock\">\n  {% include plugins/like_button.html %}{% include plugins/twitter_share.html %}"
  },
  {
    "path": "docs/_includes/plugins/ascii_cinema.html",
    "chars": 242,
    "preview": "<div class=\"ascii-cinema pluginBlock\"></div>\n<script type=\"text/javascript\" src=\"https://asciinema.org/a/{{ include.href"
  },
  {
    "path": "docs/_includes/plugins/button.html",
    "chars": 128,
    "preview": "<div class=\"pluginWrapper buttonWrapper\">\n  <a\n    class=\"button\"\n    href=\"{{ include.href }}\"\n  >{{ include.text }}</a"
  },
  {
    "path": "docs/_includes/plugins/github_star.html",
    "chars": 460,
    "preview": "<div class=\"pluginWrapper ghStarWrapper\">\n  <a aria-label=\"Star {{ site.ghrepo }} on GitHub\" data-count-aria-label=\"# st"
  },
  {
    "path": "docs/_includes/plugins/github_watch.html",
    "chars": 459,
    "preview": "<div class=\"pluginWrapper ghWatchWrapper\">\n  <a aria-label=\"Watch {{ site.ghrepo }} on GitHub\" data-count-aria-label=\"# "
  },
  {
    "path": "docs/_includes/plugins/google_share.html",
    "chars": 160,
    "preview": "<div class=\"pluginBlock\">\n  <div class=\"g-plusone\" data-size=\"medium\"></div>\n</div>\n\n<script src=\"https://apis.google.co"
  },
  {
    "path": "docs/_includes/plugins/iframe.html",
    "chars": 216,
    "preview": "<div class=\"iframeContent\">\n  <iframe class=\"pluginIframe\" src=\"{{ include.href }}\" seamless></iframe>\n</div>\n<div class"
  },
  {
    "path": "docs/_includes/plugins/like_button.html",
    "chars": 597,
    "preview": "<div class=\"fb-like pluginWrapper likeButtonWrapper\" data-layout=\"button_count\" data-action=\"like\" data-show-faces=\"true"
  },
  {
    "path": "docs/_includes/plugins/plugin_row.html",
    "chars": 160,
    "preview": "<div class=\"pluginRowBlock\">\n{% for child in include.children %}\n  {% include plugins/{{child.type}}.html href=child.hre"
  },
  {
    "path": "docs/_includes/plugins/post_social_plugins.html",
    "chars": 1271,
    "preview": "<div class=\"postSocialPlugins\">\n  <a\n    href=\"https://twitter.com/share\"\n    class=\"twitter-share-button\"\n    data-url="
  },
  {
    "path": "docs/_includes/plugins/slideshow.html",
    "chars": 2598,
    "preview": "<div class=\"slideshowBlock pluginWrapper\" id=\"slideshow\"></div>\n<script>\n  var slideshowData = [\n    {% for image in sit"
  },
  {
    "path": "docs/_includes/plugins/twitter_follow.html",
    "chars": 477,
    "preview": "<div class=\"pluginBlock\">\n  <a href=\"https://twitter.com/{{ include.href }}\" class=\"twitter-follow-button pluginBlock\" d"
  },
  {
    "path": "docs/_includes/plugins/twitter_share.html",
    "chars": 477,
    "preview": "<div class=\"pluginWrapper twitterSharePlugin\">\n  <a href=\"https://twitter.com/share\" class=\"twitter-share-button\" data-h"
  },
  {
    "path": "docs/_includes/post.html",
    "chars": 1248,
    "preview": "<div class=\"post\">\n  {% assign author = site.data.authors[page.author] %}\n  <header class=\"post-header\">\n    {% if autho"
  },
  {
    "path": "docs/_includes/powered_by.html",
    "chars": 1231,
    "preview": "{% if site.data.powered_by.first.items or site.data.powered_by_highlight.first.items %}\n<div class=\"poweredByContainer\">"
  },
  {
    "path": "docs/_includes/social_plugins.html",
    "chars": 1022,
    "preview": "<a\n  href=\"https://twitter.com/share\"\n  class=\"twitter-share-button\"\n  data-url=\"http://facebook.github.io/fresco{{ page"
  },
  {
    "path": "docs/_includes/ui/button.html",
    "chars": 235,
    "preview": "<span class=\"buttonWrap {{ include.align }}\"><a class=\"button blockButton fbossFontLight pluginBlock margin{{ include.ma"
  },
  {
    "path": "docs/_layouts/basic.html",
    "chars": 217,
    "preview": "---\nlayout: doc_default\n---\n\n<div class=\"mainContainer blogContainer postContainer\">\n  <div id=\"main_wrap\" class=\"wrappe"
  },
  {
    "path": "docs/_layouts/blog.html",
    "chars": 187,
    "preview": "---\ncategory: blog\nlayout: blog_default\n---\n\n<div class=\"mainContainer blogContainer postContainer\">\n  <div id=\"main_wra"
  },
  {
    "path": "docs/_layouts/blog_default.html",
    "chars": 403,
    "preview": "<!DOCTYPE html>\n<html>\n  {% include head.html %}\n  <body class=\"docsNavVisible\">\n    {% include nav.html alwayson=true %"
  },
  {
    "path": "docs/_layouts/default.html",
    "chars": 209,
    "preview": "<!DOCTYPE html>\n<html>\n  {% include head.html %}\n  <body>\n    {% include nav.html alwayson=true %}\n    <div class=\"navPu"
  },
  {
    "path": "docs/_layouts/doc_default.html",
    "chars": 437,
    "preview": "<!DOCTYPE html>\n<html>\n  {% include head.html %}\n  <body class=\"docsNavVisible\">\n    {% include nav.html alwayson=true %"
  },
  {
    "path": "docs/_layouts/doc_page.html",
    "chars": 175,
    "preview": "---\nlayout: doc_default\n---\n\n<div class=\"mainContainer documentContainer postContainer\">\n  <div id=\"main_wrap\" class=\"wr"
  },
  {
    "path": "docs/_layouts/docs.html",
    "chars": 48,
    "preview": "---\nlayout: doc_page\n---\n\n{% include doc.html %}"
  },
  {
    "path": "docs/_layouts/home.html",
    "chars": 636,
    "preview": "<!DOCTYPE html>\n<html>\n  {% include head.html %}\n  <body>\n    <div class=\"socialBanner\">\n      <div>\n        Support Ukr"
  },
  {
    "path": "docs/_layouts/page.html",
    "chars": 21,
    "preview": "---\nlayout: blog\n---\n"
  },
  {
    "path": "docs/_layouts/plain.html",
    "chars": 167,
    "preview": "---\nlayout: default\n---\n\n<div class=\"mainContainer blogContainer postContainer\">\n  <div id=\"main_wrap\" class=\"wrapper ma"
  },
  {
    "path": "docs/_layouts/post.html",
    "chars": 92,
    "preview": "---\ncollection: blog\nlayout: blog\n---\n\n<div class=\"lonePost\">\n{% include post.html %}\n</div>"
  },
  {
    "path": "docs/_layouts/redirect.html",
    "chars": 110,
    "preview": "<html>\n<head>\n  <meta http-equiv=\"refresh\" content=\"0; {{ page.destination }}\">\n</head>\n<body></body>\n</html>\n"
  },
  {
    "path": "docs/_layouts/top-level.html",
    "chars": 167,
    "preview": "---\nlayout: default\n---\n\n<div class=\"mainContainer blogContainer postContainer\">\n  <div id=\"main_wrap\" class=\"wrapper ma"
  },
  {
    "path": "docs/_sass/_base.scss",
    "chars": 7745,
    "preview": "body {\n  background: $secondary-bg;\n  color: $text;\n\tfont: normal #{$base-font-size}/#{$base-line-height} $base-font-fam"
  },
  {
    "path": "docs/_sass/_blog.scss",
    "chars": 695,
    "preview": ".blogContainer {\n  .posts {\n    margin-top: 60px;\n\n    .post {\n      border: 1px solid $primary-bg;\n      border-radius:"
  },
  {
    "path": "docs/_sass/_buttons.scss",
    "chars": 779,
    "preview": ".button {\n  border: 1px solid $primary-bg;\n  border-radius: 3px;\n  color: $primary-bg;\n  display: inline-block;\n  font-s"
  },
  {
    "path": "docs/_sass/_footer.scss",
    "chars": 1412,
    "preview": ".footerContainer {\n  background: $secondary-bg;\n  color: $primary-bg;\n  overflow: hidden;\n  padding: 0 10px;\n  text-alig"
  },
  {
    "path": "docs/_sass/_gridBlock.scss",
    "chars": 1897,
    "preview": ".gridBlock {\n  margin: -5px 0;\n  padding: 0;\n  padding-bottom: 20px;\n\n  .blockElement {\n    padding: 5px 0;\n\n    img {\n "
  },
  {
    "path": "docs/_sass/_header.scss",
    "chars": 2276,
    "preview": ".fixedHeaderContainer {\n  background: $primary-bg;\n  color: $primary-overlay;\n  height: $header-height;\n  padding: $head"
  },
  {
    "path": "docs/_sass/_poweredby.scss",
    "chars": 1042,
    "preview": ".poweredByContainer {\n  background: $primary-bg;\n  color: $primary-overlay;\n  margin-bottom: 20px;\n\n  a {\n    color: $pr"
  },
  {
    "path": "docs/_sass/_promo.scss",
    "chars": 787,
    "preview": ".promoSection {\n  display: flex;\n  flex-flow: column wrap;\n  font-size: 125%;\n  line-height: 1.6em;\n  margin: -10px 0;\n "
  },
  {
    "path": "docs/_sass/_react_docs_nav.scss",
    "chars": 5872,
    "preview": ".docsNavContainer {\n  background: $sidenav;\n  height: 35px;\n  left: 0;\n  position: fixed;\n  width: 100%;\n  z-index: 100;"
  },
  {
    "path": "docs/_sass/_react_header_nav.scss",
    "chars": 2665,
    "preview": ".navigationFull {\n  display: none;\n}\n\n.navigationSlider {\n  position: absolute;\n  right: 0px;\n\n  .navSlideout {\n    curs"
  },
  {
    "path": "docs/_sass/_reset.scss",
    "chars": 988,
    "preview": "html, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, bi"
  }
]

// ... and 77 more files (download for full content)

About this extraction

This page contains the full source code of the facebook/prophet GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 277 files (21.1 MB), approximately 2.4M tokens, and a symbol index with 233 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!