prophet-rb 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b37dc1a6be57b67cd740727e0bf4ac0b3a4cf2e27ed19647b631094696787da
4
- data.tar.gz: 892af24ebdd897d7dba904ed7b11a83390533666de13bb3f57172e26839ade3a
3
+ metadata.gz: 6469e3c9b0f7d026678845025284f37f7c72f875e19a5f245d9bbc745d348a38
4
+ data.tar.gz: f3be6a4488cf07a9b2b36f2ce8dd20e9c42aa4297b36b7c56d0ac16bbd6a28f2
5
5
  SHA512:
6
- metadata.gz: 53bc289290cf1a7861419634a057253f3727994c2e911247af0adf7e39688a15c019e180274cb8dd1e2a140e94dafc90ef7ff996319446b535c5f08a9090a990
7
- data.tar.gz: 6b4ecdfcfb03f3e9da68f244fd8d25f5f9bee9a854bdc4d9f68d4907f59260a485df323eb70cc60cdc68e1c1e0d5e9b5431313785bd22da72758fd90fbda7bd2
6
+ metadata.gz: 6476dc943d7a23bf74e84a8fec345009b4587e1e514e9b8e22b32fdd02e44a0f60870eb918b5cb097cd47f1da3e9ad8481098f6800736eadc31fffd7db266f75
7
+ data.tar.gz: e831ae81325d98e12a3b53bf3e68f87fdc953ad8cba1f22daca5cd375c822a9d39e5f192a4c40eeaf5c62c852955fce3b300680538988a7449069fc3de25fefb
@@ -1,3 +1,7 @@
1
+ ## 0.2.1 (2020-07-15)
2
+
3
+ - Added `forecast` method
4
+
1
5
  ## 0.2.0 (2020-05-13)
2
6
 
3
7
  - Switched from Daru to Rover
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
- ## Documentation
23
+ ## Simple API
24
24
 
25
- Check out the [Prophet documentation](https://facebook.github.io/prophet/docs/quick_start.html) for a great explanation of all of the features. The Ruby API follows the Python API and supports the same features.
25
+ Get future predictions for a time series
26
26
 
27
- ## Quick Start
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(5)
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(5)
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(5)
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" => ["playoff"] * 14,
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" => [0] * 14,
157
- "upper_window" => [1] * 14
184
+ "lower_window" => 0,
185
+ "upper_window" => 1
158
186
  )
159
187
  superbowls = Rover::DataFrame.new(
160
- "holiday" => ["superbowl"] * 3,
188
+ "holiday" => "superbowl",
161
189
  "ds" => ["2010-02-07", "2014-02-02", "2016-02-07"],
162
- "lower_window" => [0] * 3,
163
- "upper_window" => [1] * 3
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.
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Prophet
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
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.0
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-05-14 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdstan