prophet-rb 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b32ff3ccea1dce9051e3e661ac61ed6c84e7f0f64189f169e11974033163f7e
4
- data.tar.gz: 5dfb93a8cfea394e235fd6597b80e192e3e22a7bf7965d5e13e00e2d8ccc0ed8
3
+ metadata.gz: 756e42a4e2c39e114610d2f41e2403d9b160e77da02c0483e43b4bf460dd828b
4
+ data.tar.gz: e7bce55f47410227131afcba9d2f90c9812dab093efd1c17465383b3a5e6dc73
5
5
  SHA512:
6
- metadata.gz: 47b944a25d3fa34e67d75ccd1cc558ab6777eef0f04c21e5af94328b4e5f03137e3ab29d005fef48cec064e0aeffea58e53997f851e6eee10a2b368c213807da
7
- data.tar.gz: fb27bf59a2d69f5b5444f0b28836a8c6edf0a528199c56ae757cfaee87e69b2caa4f4ef15f703813994b35a6ce74b086895c71fb6737930e482fa7148ad1ca29
6
+ metadata.gz: ec014f32ff39abd49195d7e9a7f38b3b297bc7f6fc28da3d1be6fb19b6edbe816a681c4fbb35d5ea79fc2ced0aa948b0468cff9f6d9d8293590761711944b71b
7
+ data.tar.gz: 87ecc8706c73e7f1063c8d75cc5c687ebc3fddb92d89e60bb115d21c90a60fbb6172648a0d414baeb11f04572b37e06777d4100acb07b8559dea8e8a711741fb
@@ -1,3 +1,7 @@
1
+ ## 0.2.3 (2020-10-14)
2
+
3
+ - Added support for times to `forecast` method
4
+
1
5
  ## 0.2.2 (2020-07-26)
2
6
 
3
7
  - Fixed error with constant series
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Andrew Kane
4
3
  Copyright (c) Facebook, Inc. and its affiliates.
4
+ Copyright (c) 2020 Andrew Kane
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining
7
7
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -118,7 +118,7 @@ Plot the forecast
118
118
  m.plot(forecast).savefig("forecast.png")
119
119
  ```
120
120
 
121
- ![Forecast](https://blazer.dokkuapp.com/assets/prophet/forecast-a9d43195b8ad23703eda7bb8b52b8a758efb4699e2313f32d7bbdfaa2f4275f6.png)
121
+ ![Forecast](https://blazer.dokkuapp.com/assets/prophet/forecast-77cf453fda67d1b462c6c22aee3a02572203b71c4517fedecc1f438cd374a876.png)
122
122
 
123
123
  Plot components
124
124
 
@@ -126,7 +126,7 @@ Plot components
126
126
  m.plot_components(forecast).savefig("components.png")
127
127
  ```
128
128
 
129
- ![Components](https://blazer.dokkuapp.com/assets/prophet/components-b9e31bfcf77e57bbd503c0bcff5e5544e66085b90709b06dd96c5f622a87d84f.png)
129
+ ![Components](https://blazer.dokkuapp.com/assets/prophet/components-2cdd260e23bc89824ecca25f6bfe394deb5821d60b7e0e551469c90d204acd67.png)
130
130
 
131
131
  ## Saturating Forecasts
132
132
 
@@ -21,19 +21,22 @@ module Prophet
21
21
  Forecaster.new(**kwargs)
22
22
  end
23
23
 
24
- # to add time support in future, see
25
- # https://github.com/ankane/prophet/commit/06e3562835cbcf06b8431f3a91fe2618d4703eb7
26
24
  def self.forecast(series, count: 10)
27
25
  raise ArgumentError, "Series must have at least 10 data points" if series.size < 10
28
26
 
27
+ # check type to determine output format
28
+ # check for before converting to time
29
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
30
+ dates = keys.all? { |k| k.is_a?(Date) }
31
+ time_zone = keys.first.time_zone if keys.first.respond_to?(:time_zone)
32
+ utc = keys.first.utc? if keys.first.respond_to?(:utc?)
33
+ times = keys.map(&:to_time)
32
34
 
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 }
35
+ day = times.all? { |t| t.hour == 0 && t.min == 0 && t.sec == 0 && t.nsec == 0 }
36
+ week = day && times.map { |k| k.wday }.uniq.size == 1
37
+ month = day && times.all? { |k| k.day == 1 }
38
+ quarter = month && times.all? { |k| k.month % 3 == 1 }
39
+ year = quarter && times.all? { |k| k.month == 1 }
37
40
 
38
41
  freq =
39
42
  if year
@@ -44,10 +47,20 @@ module Prophet
44
47
  "MS"
45
48
  elsif week
46
49
  "W"
47
- else
50
+ elsif day
48
51
  "D"
52
+ else
53
+ diff = Rover::Vector.new(times).sort.diff.to_numo[1..-1]
54
+ min_diff = diff.min.to_i
55
+
56
+ # could be another common divisor
57
+ # but keep it simple for now
58
+ raise "Unknown frequency" unless (diff % min_diff).eq(0).all?
59
+
60
+ "#{min_diff}S"
49
61
  end
50
62
 
63
+ # use series, not times, so dates are handled correctly
51
64
  df = Rover::DataFrame.new({"ds" => series.keys, "y" => series.values})
52
65
 
53
66
  m = Prophet.new
@@ -56,6 +69,18 @@ module Prophet
56
69
 
57
70
  future = m.make_future_dataframe(periods: count, include_history: false, freq: freq)
58
71
  forecast = m.predict(future)
59
- forecast[["ds", "yhat"]].to_a.map { |v| [v["ds"].to_date, v["yhat"]] }.to_h
72
+ result = forecast[["ds", "yhat"]].to_a
73
+
74
+ # use the same format as input
75
+ if dates
76
+ result.each { |v| v["ds"] = v["ds"].to_date }
77
+ elsif time_zone
78
+ result.each { |v| v["ds"] = v["ds"].in_time_zone(time_zone) }
79
+ elsif utc
80
+ result.each { |v| v["ds"] = v["ds"].utc }
81
+ else
82
+ result.each { |v| v["ds"] = v["ds"].localtime }
83
+ end
84
+ result.map { |v| [v["ds"], v["yhat"]] }.to_h
60
85
  end
61
86
  end
@@ -901,6 +901,9 @@ module Prophet
901
901
  # TODO add more freq
902
902
  # https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases
903
903
  case freq
904
+ when /\A\d+S\z/
905
+ secs = freq.to_i
906
+ dates = (periods + 1).times.map { |i| last_date + i * secs }
904
907
  when "H"
905
908
  hour = 3600
906
909
  dates = (periods + 1).times.map { |i| last_date + i * hour }
@@ -1,3 +1,3 @@
1
1
  module Prophet
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
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.2
4
+ version: 0.2.3
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-07-26 00:00:00.000000000 Z
11
+ date: 2020-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdstan
@@ -122,6 +122,34 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: tzinfo-data
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  description:
126
154
  email: andrew@chartkick.com
127
155
  executables: []