prophet-rb 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +49 -12
- data/lib/prophet.rb +38 -0
- data/lib/prophet/forecaster.rb +13 -0
- data/lib/prophet/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6469e3c9b0f7d026678845025284f37f7c72f875e19a5f245d9bbc745d348a38
|
4
|
+
data.tar.gz: f3be6a4488cf07a9b2b36f2ce8dd20e9c42aa4297b36b7c56d0ac16bbd6a28f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6476dc943d7a23bf74e84a8fec345009b4587e1e514e9b8e22b32fdd02e44a0f60870eb918b5cb097cd47f1da3e9ad8481098f6800736eadc31fffd7db266f75
|
7
|
+
data.tar.gz: e831ae81325d98e12a3b53bf3e68f87fdc953ad8cba1f22daca5cd375c822a9d39e5f192a4c40eeaf5c62c852955fce3b300680538988a7449069fc3de25fefb
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -20,11 +20,39 @@ Add this line to your application’s Gemfile:
|
|
20
20
|
gem 'prophet-rb'
|
21
21
|
```
|
22
22
|
|
23
|
-
##
|
23
|
+
## Simple API
|
24
24
|
|
25
|
-
|
25
|
+
Get future predictions for a time series
|
26
26
|
|
27
|
-
|
27
|
+
```ruby
|
28
|
+
series = {
|
29
|
+
Date.parse("2020-01-01") => 100,
|
30
|
+
Date.parse("2020-01-02") => 150,
|
31
|
+
Date.parse("2020-01-03") => 136,
|
32
|
+
# ...
|
33
|
+
}
|
34
|
+
|
35
|
+
Prophet.forecast(series)
|
36
|
+
```
|
37
|
+
|
38
|
+
Specify the number of predictions to return
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Prophet.forecast(series, count: 3)
|
42
|
+
```
|
43
|
+
|
44
|
+
Works great with [Groupdate](https://github.com/ankane/groupdate)
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
series = User.group_by_day(:created_at).count
|
48
|
+
Prophet.forecast(series)
|
49
|
+
```
|
50
|
+
|
51
|
+
## Advanced API
|
52
|
+
|
53
|
+
Check out the [Prophet documentation](https://facebook.github.io/prophet/docs/quick_start.html) for a great explanation of all of the features. The advanced API follows the Python API and supports the same features. It uses [Rover](https://github.com/ankane/rover) for data frames.
|
54
|
+
|
55
|
+
## Advanced Quick Start
|
28
56
|
|
29
57
|
[Explanation](https://facebook.github.io/prophet/docs/quick_start.html)
|
30
58
|
|
@@ -32,7 +60,7 @@ Create a data frame with `ds` and `y` columns - here’s [an example](examples/e
|
|
32
60
|
|
33
61
|
```ruby
|
34
62
|
df = Rover.read_csv("example_wp_log_peyton_manning.csv")
|
35
|
-
df.head
|
63
|
+
df.head
|
36
64
|
```
|
37
65
|
|
38
66
|
ds | y
|
@@ -54,7 +82,7 @@ Make a data frame with a `ds` column for future predictions
|
|
54
82
|
|
55
83
|
```ruby
|
56
84
|
future = m.make_future_dataframe(periods: 365)
|
57
|
-
future.tail
|
85
|
+
future.tail
|
58
86
|
```
|
59
87
|
|
60
88
|
ds |
|
@@ -69,7 +97,7 @@ Make predictions
|
|
69
97
|
|
70
98
|
```ruby
|
71
99
|
forecast = m.predict(future)
|
72
|
-
forecast["ds", "yhat", "yhat_lower", "yhat_upper"].tail
|
100
|
+
forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail
|
73
101
|
```
|
74
102
|
|
75
103
|
ds | yhat | yhat_lower | yhat_upper
|
@@ -147,20 +175,20 @@ Create a data frame with `holiday` and `ds` columns. Include all occurrences in
|
|
147
175
|
|
148
176
|
```ruby
|
149
177
|
playoffs = Rover::DataFrame.new(
|
150
|
-
"holiday" =>
|
178
|
+
"holiday" => "playoff",
|
151
179
|
"ds" => ["2008-01-13", "2009-01-03", "2010-01-16",
|
152
180
|
"2010-01-24", "2010-02-07", "2011-01-08",
|
153
181
|
"2013-01-12", "2014-01-12", "2014-01-19",
|
154
182
|
"2014-02-02", "2015-01-11", "2016-01-17",
|
155
183
|
"2016-01-24", "2016-02-07"],
|
156
|
-
"lower_window" =>
|
157
|
-
"upper_window" =>
|
184
|
+
"lower_window" => 0,
|
185
|
+
"upper_window" => 1
|
158
186
|
)
|
159
187
|
superbowls = Rover::DataFrame.new(
|
160
|
-
"holiday" =>
|
188
|
+
"holiday" => "superbowl",
|
161
189
|
"ds" => ["2010-02-07", "2014-02-02", "2016-02-07"],
|
162
|
-
"lower_window" =>
|
163
|
-
"upper_window" =>
|
190
|
+
"lower_window" => 0,
|
191
|
+
"upper_window" => 1
|
164
192
|
)
|
165
193
|
holidays = playoffs.concat(superbowls)
|
166
194
|
|
@@ -246,6 +274,15 @@ forecast = m.predict(future)
|
|
246
274
|
|
247
275
|
- [Forecasting at Scale](https://peerj.com/preprints/3190.pdf)
|
248
276
|
|
277
|
+
## Upgrading
|
278
|
+
|
279
|
+
### 0.2.0
|
280
|
+
|
281
|
+
Prophet now uses [Rover](https://github.com/ankane/rover) instead of Daru. Two changes you may need to make are:
|
282
|
+
|
283
|
+
- `Rover.read_csv` instead of `Daru::DataFrame.from_csv`
|
284
|
+
- `df[["ds", "yhat"]]` instead of `df["ds", "yhat"]`
|
285
|
+
|
249
286
|
## Credits
|
250
287
|
|
251
288
|
This library was ported from the [Prophet Python library](https://github.com/facebook/prophet) and is available under the same license.
|
data/lib/prophet.rb
CHANGED
@@ -20,4 +20,42 @@ module Prophet
|
|
20
20
|
def self.new(**kwargs)
|
21
21
|
Forecaster.new(**kwargs)
|
22
22
|
end
|
23
|
+
|
24
|
+
# to add time support in future, see
|
25
|
+
# https://github.com/ankane/prophet/commit/06e3562835cbcf06b8431f3a91fe2618d4703eb7
|
26
|
+
def self.forecast(series, count: 10)
|
27
|
+
raise ArgumentError, "Series must have at least 10 data points" if series.size < 10
|
28
|
+
|
29
|
+
keys = series.keys
|
30
|
+
bad_key = keys.find { |k| !k.is_a?(Date) }
|
31
|
+
raise ArgumentError, "Expected Date, got #{bad_key.class.name}" if bad_key
|
32
|
+
|
33
|
+
week = keys.map { |k| k.wday }.uniq.size == 1
|
34
|
+
month = keys.all? { |k| k.day == 1 }
|
35
|
+
quarter = month && keys.all? { |k| k.month % 3 == 1 }
|
36
|
+
year = quarter && keys.all? { |k| k.month == 1 }
|
37
|
+
|
38
|
+
freq =
|
39
|
+
if year
|
40
|
+
"YS"
|
41
|
+
elsif quarter
|
42
|
+
"QS"
|
43
|
+
elsif month
|
44
|
+
"MS"
|
45
|
+
elsif week
|
46
|
+
"W"
|
47
|
+
else
|
48
|
+
"D"
|
49
|
+
end
|
50
|
+
|
51
|
+
df = Rover::DataFrame.new({"ds" => series.keys, "y" => series.values})
|
52
|
+
|
53
|
+
m = Prophet.new
|
54
|
+
m.logger.level = ::Logger::FATAL # no logging
|
55
|
+
m.fit(df)
|
56
|
+
|
57
|
+
future = m.make_future_dataframe(periods: count, include_history: false, freq: freq)
|
58
|
+
forecast = m.predict(future)
|
59
|
+
forecast[["ds", "yhat"]].to_a.map { |v| [v["ds"].to_date, v["yhat"]] }.to_h
|
60
|
+
end
|
23
61
|
end
|
data/lib/prophet/forecaster.rb
CHANGED
@@ -911,9 +911,22 @@ module Prophet
|
|
911
911
|
dates = (periods + 1).times.map { |i| last_date + i * week }
|
912
912
|
when "MS"
|
913
913
|
dates = [last_date]
|
914
|
+
# TODO reset day from last date, but keep time
|
914
915
|
periods.times do
|
915
916
|
dates << dates.last.to_datetime.next_month.to_time.utc
|
916
917
|
end
|
918
|
+
when "QS"
|
919
|
+
dates = [last_date]
|
920
|
+
# TODO reset day and month from last date, but keep time
|
921
|
+
periods.times do
|
922
|
+
dates << dates.last.to_datetime.next_month.next_month.next_month.to_time.utc
|
923
|
+
end
|
924
|
+
when "YS"
|
925
|
+
dates = [last_date]
|
926
|
+
# TODO reset day and month from last date, but keep time
|
927
|
+
periods.times do
|
928
|
+
dates << dates.last.to_datetime.next_year.to_time.utc
|
929
|
+
end
|
917
930
|
else
|
918
931
|
raise ArgumentError, "Unknown freq: #{freq}"
|
919
932
|
end
|
data/lib/prophet/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prophet-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdstan
|