Time series forecasting for Ruby, ported from Prophet
Supports:
- Multiple seasonalities
- Linear and non-linear growth
- Holidays and special events
And gracefully handles missing data
Add this line to your application’s Gemfile:
gem "prophet-rb"Get future predictions for a time series
series = {
Date.parse("2020-01-01") => 100,
Date.parse("2020-01-02") => 150,
Date.parse("2020-01-03") => 136,
# ...
}
Prophet.forecast(series)Specify the number of predictions to return
Prophet.forecast(series, count: 3)Works great with Groupdate
series = User.group_by_day(:created_at).count
Prophet.forecast(series)Detect anomalies in a time series
Prophet.anomalies(series)Check out the Prophet documentation for a great explanation of all of the features. The advanced API follows the Python API and supports the same features. It uses Rover for data frames.
Create a data frame with ds and y columns - here’s an example you can use
df = Rover.read_csv("example_wp_log_peyton_manning.csv")
df.head| ds | y |
|---|---|
| 2007-12-10 | 9.59076113 |
| 2007-12-11 | 8.51959031 |
| 2007-12-12 | 8.18367658 |
| 2007-12-13 | 8.07246736 |
| 2007-12-14 | 7.89357207 |
Fit a model
m = Prophet.new
m.fit(df)Make a data frame with a ds column for future predictions
future = m.make_future_dataframe(periods: 365)
future.tail| ds |
|---|
| 2017-01-15 |
| 2017-01-16 |
| 2017-01-17 |
| 2017-01-18 |
| 2017-01-19 |
Make predictions
forecast = m.predict(future)
forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail| ds | yhat | yhat_lower | yhat_upper |
|---|---|---|---|
| 2017-01-15 | 8.21192840 | 7.52526442 | 8.92389960 |
| 2017-01-16 | 8.53696359 | 7.79124970 | 9.22620028 |
| 2017-01-17 | 8.32439891 | 7.62482699 | 9.04719328 |
| 2017-01-18 | 8.15702395 | 7.40079968 | 8.91301650 |
| 2017-01-19 | 8.16900433 | 7.45673678 | 8.83486188 |
For plots, install the matplotlib gem.
Plot the forecast
m.plot(forecast).savefig("forecast.png")Plot components
m.plot_components(forecast).savefig("components.png")Forecast logistic growth instead of linear
df = Rover.read_csv("example_wp_log_R.csv")
df["cap"] = 8.5
m = Prophet.new(growth: "logistic")
m.fit(df)
future = m.make_future_dataframe(periods: 365)
future["cap"] = 8.5
forecast = m.predict(future)Plot changepoints
fig = m.plot(forecast)
m.add_changepoints_to_plot(fig.gca, forecast)Adjust trend flexibility
m = Prophet.new(changepoint_prior_scale: 0.5)Specify the location of changepoints
m = Prophet.new(changepoints: ["2014-01-01"])Create a data frame with holiday and ds columns. Include all occurrences in your past data and future occurrences you’d like to forecast.
playoffs = Rover::DataFrame.new(
"holiday" => "playoff",
"ds" => ["2008-01-13", "2009-01-03", "2010-01-16",
"2010-01-24", "2010-02-07", "2011-01-08",
"2013-01-12", "2014-01-12", "2014-01-19",
"2014-02-02", "2015-01-11", "2016-01-17",
"2016-01-24", "2016-02-07"],
"lower_window" => 0,
"upper_window" => 1
)
superbowls = Rover::DataFrame.new(
"holiday" => "superbowl",
"ds" => ["2010-02-07", "2014-02-02", "2016-02-07"],
"lower_window" => 0,
"upper_window" => 1
)
holidays = playoffs.concat(superbowls)
m = Prophet.new(holidays: holidays)
m.fit(df)Add country-specific holidays
m = Prophet.new
m.add_country_holidays(country_name: "US")
m.fit(df)Specify custom seasonalities
m = Prophet.new(weekly_seasonality: false)
m.add_seasonality(name: "monthly", period: 30.5, fourier_order: 5)
forecast = m.fit(df).predict(future)Specify additional regressors
nfl_sunday = lambda do |ds|
date = ds.respond_to?(:to_date) ? ds.to_date : Date.parse(ds)
date.wday == 0 && (date.month > 8 || date.month < 2) ? 1 : 0
end
df["nfl_sunday"] = df["ds"].map(&nfl_sunday)
m = Prophet.new
m.add_regressor("nfl_sunday")
m.fit(df)
future["nfl_sunday"] = future["ds"].map(&nfl_sunday)
forecast = m.predict(future)df = Rover.read_csv("example_air_passengers.csv")
m = Prophet.new(seasonality_mode: "multiplicative")
m.fit(df)
future = m.make_future_dataframe(periods: 50, freq: "MS")
forecast = m.predict(future)Specify the width of uncertainty intervals (80% by default)
Prophet.new(interval_width: 0.95)Get uncertainty in seasonality
Prophet.new(mcmc_samples: 300)Sub-daily data
df = Rover.read_csv("example_yosemite_temps.csv")
m = Prophet.new(changepoint_prior_scale: 0.01).fit(df)
future = m.make_future_dataframe(periods: 300, freq: "H")
forecast = m.predict(future)Prophet now uses Rover instead of Daru. Two changes you may need to make are:
Rover.read_csvinstead ofDaru::DataFrame.from_csvdf[["ds", "yhat"]]instead ofdf["ds", "yhat"]
This library was ported from the Prophet Python library and is available under the same license.
View the changelog
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
git clone https://github.com/ankane/prophet-ruby.git
cd prophet-ruby
bundle install
bundle exec rake vendor:all
bundle exec rake test
