statsample-timeseries 0.0.2

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.
@@ -0,0 +1,164 @@
1
+ module Statsample
2
+ module TimeSeries
3
+ module Pacf
4
+ class Pacf
5
+
6
+ def self.pacf_yw(timeseries, max_lags, method = 'yw')
7
+ #partial autocorrelation by yule walker equations.
8
+ #Inspiration: StatsModels
9
+ pacf = [1.0]
10
+ (1..max_lags).map do |i|
11
+ pacf << yule_walker(timeseries, i, method)[0][-1]
12
+ end
13
+ pacf
14
+ end
15
+
16
+
17
+ #=Levinson-Durbin Algorithm
18
+ #==Parameters
19
+ #* *series*: timeseries, or a series of autocovariances
20
+ #* *nlags*: integer(default: 10): largest lag to include in recursion or order of the AR process
21
+ #* *is_acovf*: boolean(default: false): series is timeseries if it is false, else contains autocavariances
22
+ #
23
+ #==Returns:
24
+ #* *sigma_v*: estimate of the error variance
25
+ #* *arcoefs*: AR coefficients
26
+ #* *pacf*: pacf function
27
+ #* *sigma*: some function
28
+ def self.levinson_durbin(series, nlags = 10, is_acovf = false)
29
+
30
+ if is_acovf
31
+ series = series.map(&:to_f)
32
+ else
33
+ #nlags = order(k) of AR in this case
34
+ series = series.acvf.map(&:to_f)[0..nlags]
35
+ end
36
+ #phi = Array.new((nlags+1), 0.0) { Array.new(nlags+1, 0.0) }
37
+ order = nlags
38
+ phi = Matrix.zero(nlags + 1)
39
+ sig = Array.new(nlags+1)
40
+
41
+ #setting initial point for recursion:
42
+ phi[1,1] = series[1]/series[0]
43
+ #phi[1][1] = series[1]/series[0]
44
+ sig[1] = series[0] - phi[1, 1] * series[1]
45
+
46
+ 2.upto(order).each do |k|
47
+ phi[k, k] = (series[k] - (Statsample::Vector.new(phi[1...k, k-1]) * series[1...k].reverse.to_ts).sum) / sig[k-1]
48
+ #some serious refinement needed in above for matrix manipulation. Will do today
49
+ 1.upto(k-1).each do |j|
50
+ phi[j, k] = phi[j, k-1] - phi[k, k] * phi[k-j, k-1]
51
+ end
52
+ sig[k] = sig[k-1] * (1-phi[k, k] ** 2)
53
+
54
+ end
55
+ sigma_v = sig[-1]
56
+ arcoefs_delta = phi.column(phi.column_size - 1)
57
+ arcoefs = arcoefs_delta[1..arcoefs_delta.size]
58
+ pacf = diag(phi)
59
+ pacf[0] = 1.0
60
+ return [sigma_v, arcoefs, pacf, sig, phi]
61
+ end
62
+
63
+ #Returns diagonal elements of matrices
64
+ # Will later abstract it to utilities
65
+ def self.diag(mat)
66
+ return mat.each_with_index(:diagonal).map { |x, r, c| x }
67
+ end
68
+
69
+
70
+ #=Yule Walker Algorithm
71
+ #From the series, estimates AR(p)(autoregressive) parameter using Yule-Waler equation. See -
72
+ #http://en.wikipedia.org/wiki/Autoregressive_moving_average_model
73
+ #
74
+ #==Parameters
75
+ #* *ts*: timeseries
76
+ #* *k*: order, default = 1
77
+ #* *method*: can be 'yw' or 'mle'. If 'yw' then it is unbiased, denominator is (n - k)
78
+ #
79
+ #==Returns
80
+ #* *rho*: autoregressive coefficients
81
+ #* *sigma*: sigma parameter
82
+ def self.yule_walker(ts, k = 1, method='yw')
83
+ ts = ts - ts.mean
84
+ n = ts.size
85
+ if method.downcase.eql? 'yw'
86
+ #unbiased => denominator = (n - k)
87
+ denom =->(k) { n - k }
88
+ else
89
+ #mle
90
+ #denominator => (n)
91
+ denom =->(k) { n }
92
+ end
93
+ r = Array.new(k + 1) { 0.0 }
94
+ r[0] = ts.map { |x| x**2 }.inject(:+).to_f / denom.call(0).to_f
95
+
96
+ 1.upto(k) do |l|
97
+ r[l] = (ts[0...-l].zip(ts[l...ts.size])).map do |x|
98
+ x.inject(:*)
99
+ end.inject(:+).to_f / denom.call(l).to_f
100
+ end
101
+
102
+ r_R = toeplitz(r[0...-1])
103
+
104
+ mat = Matrix.columns(r_R).inverse()
105
+ phi = solve_matrix(mat, r[1..r.size])
106
+ phi_vector = Statsample::Vector.new(phi, :scale)
107
+ r_vector = Statsample::Vector.new(r[1..r.size], :scale)
108
+ sigma = r[0] - (r_vector * phi_vector).sum
109
+ return [phi, sigma]
110
+ end
111
+
112
+ #=ToEplitz
113
+ # Generates teoeplitz matrix from an array
114
+ #http://en.wikipedia.org/wiki/Toeplitz_matrix
115
+ #Toeplitz matrix are equal when they are stored in row & column major
116
+ #==Parameters
117
+ #* *arr*: array of integers;
118
+ #==Usage
119
+ # arr = [0,1,2,3]
120
+ # Pacf.toeplitz(arr)
121
+ #==Returns
122
+ # [[0, 1, 2, 3],
123
+ # [1, 0, 1, 2],
124
+ # [2, 1, 0, 1],
125
+ # [3, 2, 1, 0]]
126
+ def self.toeplitz(arr)
127
+ eplitz_matrix = Array.new(arr.size) { Array.new(arr.size) }
128
+
129
+ 0.upto(arr.size - 1) do |i|
130
+ j = 0
131
+ index = i
132
+ while i >= 0 do
133
+ eplitz_matrix[index][j] = arr[i]
134
+ j += 1
135
+ i -= 1
136
+ end
137
+ i = index + 1; k = 1
138
+ while i < arr.size do
139
+ eplitz_matrix[index][j] = arr[k]
140
+ i += 1; j += 1; k += 1
141
+ end
142
+ end
143
+ eplitz_matrix
144
+ end
145
+
146
+ #===Solves matrix equations
147
+ #Solves for X in AX = B
148
+ def self.solve_matrix(matrix, out_vector)
149
+ solution_vector = Array.new(out_vector.size, 0)
150
+ matrix = matrix.to_a
151
+ k = 0
152
+ matrix.each do |row|
153
+ row.each_with_index do |element, i|
154
+ solution_vector[k] += element * 1.0 * out_vector[i]
155
+ end
156
+ k += 1
157
+ end
158
+ solution_vector
159
+ end
160
+
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,154 @@
1
+ module Statsample
2
+ class Vector
3
+ include Enumerable
4
+ include Writable
5
+ include Summarizable
6
+
7
+ #=Squares of sum
8
+ #==Parameter
9
+ #* *demean*: boolean - optional. __default__: false
10
+ #==Returns
11
+ #Sums the timeseries and then returns the square
12
+ def squares_of_sum(demean = false)
13
+ if demean
14
+ m = self.mean
15
+ self.map { |x| (x-m) }.sum**2
16
+ else
17
+ return self.sum.to_f**2
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ class ::Matrix
24
+ #==Squares of sum
25
+ #Does squares of sum in column order.
26
+ #Necessary for computations in various processes
27
+ def squares_of_sum
28
+ (0...column_size).map do |j|
29
+ self.column(j).sum**2
30
+ end
31
+ end
32
+
33
+ #==Symmetric?
34
+ #`symmetric?` is present in Ruby Matrix 1.9.3+, but not in 1.8.*
35
+ #===Returns
36
+ # bool
37
+ def symmetric?
38
+ return false unless square?
39
+
40
+ (0...row_size).each do |i|
41
+ 0.upto(i).each do |j|
42
+ return false if self[i, j] != self[j, i]
43
+ end
44
+ end
45
+ true
46
+ end
47
+
48
+ #==Cholesky decomposition
49
+ #Reference: http://en.wikipedia.org/wiki/Cholesky_decomposition
50
+ #===Description
51
+ #Cholesky decomposition is reprsented by `M = L X L*`, where
52
+ #M is the symmetric matrix and `L` is the lower half of cholesky matrix,
53
+ #and `L*` is the conjugate form of `L`.
54
+ #===Returns
55
+ # Cholesky decomposition for a given matrix(if symmetric)
56
+ #===Utility
57
+ # Essential matrix function, requisite in kalman filter, least squares
58
+ def cholesky
59
+ raise ArgumentError, "Given matrix should be symmetric" unless symmetric?
60
+ c = Matrix.zero(row_size)
61
+ 0.upto(row_size - 1).each do |k|
62
+ 0.upto(row_size - 1).each do |i|
63
+ if i == k
64
+ sum = (0..(k-1)).inject(0.0){ |sum, j| sum + c[k, j] ** 2 }
65
+ value = Math.sqrt(self[k,k] - sum)
66
+ c[k, k] = value
67
+ elsif i > k
68
+ sum = (0..(k-1)).inject(0.0){ |sum, j| sum + c[i, j] * c[k, j] }
69
+ value = (self[k,i] - sum) / c[k, k]
70
+ c[i, k] = value
71
+ end
72
+ end
73
+ end
74
+ c
75
+ end
76
+
77
+ #==Chain Product
78
+ #Class method
79
+ #Returns the chain product of two matrices
80
+ #===Usage:
81
+ #Let `a` be 4 * 3 matrix,
82
+ #Let `b` be 3 * 3 matrix,
83
+ #Let `c` be 3 * 1 matrix,
84
+ #then `Matrix.chain_dot(a, b, c)`
85
+ #===NOTE:
86
+ # Send the matrices in multiplicative order with proper dimensions
87
+ def self.chain_dot(*args)
88
+ #inspired by Statsmodels
89
+ begin
90
+ args.reduce { |x, y| x * y } #perform matrix multiplication in order
91
+ rescue ExceptionForMatrix::ErrDimensionMismatch
92
+ puts "ExceptionForMatrix: Please provide matrices with proper multiplicative dimensions"
93
+ end
94
+ end
95
+
96
+
97
+ #==Adds a column of constants.
98
+ #Appends a column of ones to the matrix/array if first argument is false
99
+ #If an n-array, first checks if one column of ones is already present
100
+ #if present, then original(self) is returned, else, prepends with a vector of ones
101
+ def add_constant(prepend = true)
102
+ #for Matrix
103
+ (0...column_size).each do |i|
104
+ if self.column(i).map(&:to_f) == Object::Vector.elements(Array.new(row_size, 1.0))
105
+ return self
106
+ end
107
+ end
108
+ #append/prepend a column of one's
109
+ vectors = (0...row_size).map do |r|
110
+ if prepend
111
+ [1.0].concat(self.row(r).to_a)
112
+ else
113
+ self.row(r).to_a.push(1.0)
114
+ end
115
+ end
116
+ return Matrix.rows(vectors)
117
+ end
118
+
119
+ #populates column i of given matrix with arr
120
+ def set_column(i, arr)
121
+ columns = self.column_vectors
122
+ column = columns[i].to_a
123
+ column[0...arr.size] = arr
124
+ columns[i] = column
125
+ return Matrix.columns(columns)
126
+ end
127
+
128
+ #populates row i of given matrix with arr
129
+ def set_row(i, arr)
130
+ #similar implementation as set_column
131
+ #writing and commenting metaprogrammed version
132
+ #Please to give opinion :)
133
+ rows = self.row_vectors
134
+ row = rows[i].to_a
135
+ row[0...arr.size] = arr
136
+ rows[i] = row
137
+ return Matrix.rows(rows)
138
+ end
139
+
140
+ #Metaprogrammed version of set_column, set_row
141
+ # self.class_eval do
142
+ # ["row", "column"].each do |dimension|
143
+ # define_method("set_#{dimension}s") do |i, arr|
144
+ # dims = send("#{dimension}_vectors")
145
+ # dim = dims[i].to_a
146
+ # dim[0...arr.size] = arr
147
+ # dims[i] = dim
148
+ # return Matrix.send("#{dimension}s", dims)
149
+ # end
150
+ # end
151
+ # end
152
+ end
153
+
154
+ end
@@ -0,0 +1,500 @@
1
+ 17.66
2
+ 17.65
3
+ 17.68
4
+ 17.66
5
+ 17.68
6
+ 17.67
7
+ 17.68
8
+ 17.68
9
+ 17.67
10
+ 17.67
11
+ 17.68
12
+ 17.71
13
+ 17.74
14
+ 17.72
15
+ 17.73
16
+ 17.76
17
+ 17.74
18
+ 17.69
19
+ 17.69
20
+ 17.67
21
+ 17.66
22
+ 17.67
23
+ 17.69
24
+ 17.69
25
+ 17.68
26
+ 17.65
27
+ 17.65
28
+ 17.64
29
+ 17.63
30
+ 17.64
31
+ 17.67
32
+ 17.68
33
+ 17.7
34
+ 17.68
35
+ 17.69
36
+ 17.69
37
+ 17.72
38
+ 17.71
39
+ 17.71
40
+ 17.71
41
+ 17.69
42
+ 17.69
43
+ 17.71
44
+ 17.72
45
+ 17.71
46
+ 17.68
47
+ 17.68
48
+ 17.68
49
+ 17.69
50
+ 17.68
51
+ 17.68
52
+ 17.69
53
+ 17.67
54
+ 17.69
55
+ 17.71
56
+ 17.7
57
+ 17.7
58
+ 17.71
59
+ 17.73
60
+ 17.74
61
+ 17.74
62
+ 17.74
63
+ 17.76
64
+ 17.77
65
+ 17.55
66
+ 17.55
67
+ 17.5
68
+ 17.46
69
+ 17.49
70
+ 17.54
71
+ 17.51
72
+ 17.54
73
+ 17.57
74
+ 17.54
75
+ 17.52
76
+ 17.53
77
+ 17.56
78
+ 17.55
79
+ 17.55
80
+ 17.54
81
+ 17.55
82
+ 17.55
83
+ 17.55
84
+ 17.54
85
+ 17.52
86
+ 17.53
87
+ 17.51
88
+ 17.52
89
+ 17.5
90
+ 17.5
91
+ 17.5
92
+ 17.49
93
+ 17.46
94
+ 17.47
95
+ 17.48
96
+ 17.45
97
+ 17.41
98
+ 17.39
99
+ 17.38
100
+ 17.43
101
+ 17.44
102
+ 17.43
103
+ 17.43
104
+ 17.46
105
+ 17.46
106
+ 17.47
107
+ 17.47
108
+ 17.45
109
+ 17.48
110
+ 17.49
111
+ 17.5
112
+ 17.49
113
+ 17.48
114
+ 17.49
115
+ 17.47
116
+ 17.47
117
+ 17.44
118
+ 17.44
119
+ 17.43
120
+ 17.45
121
+ 17.42
122
+ 17.43
123
+ 17.43
124
+ 17.44
125
+ 17.44
126
+ 17.43
127
+ 17.41
128
+ 17.41
129
+ 17.38
130
+ 17.38
131
+ 17.37
132
+ 17.37
133
+ 17.37
134
+ 17.3
135
+ 17.28
136
+ 17.27
137
+ 17.19
138
+ 16.41
139
+ 16.44
140
+ 16.48
141
+ 16.53
142
+ 16.51
143
+ 16.57
144
+ 16.54
145
+ 16.59
146
+ 16.64
147
+ 16.6
148
+ 16.65
149
+ 16.69
150
+ 16.69
151
+ 16.68
152
+ 16.64
153
+ 16.65
154
+ 16.66
155
+ 16.64
156
+ 16.61
157
+ 16.65
158
+ 16.67
159
+ 16.66
160
+ 16.65
161
+ 16.61
162
+ 16.59
163
+ 16.57
164
+ 16.55
165
+ 16.55
166
+ 16.57
167
+ 16.54
168
+ 16.6
169
+ 16.62
170
+ 16.6
171
+ 16.59
172
+ 16.61
173
+ 16.66
174
+ 16.69
175
+ 16.67
176
+ 16.65
177
+ 16.66
178
+ 16.65
179
+ 16.65
180
+ 16.68
181
+ 16.68
182
+ 16.67
183
+ 16.64
184
+ 16.73
185
+ 16.76
186
+ 16.75
187
+ 16.79
188
+ 16.8
189
+ 16.77
190
+ 16.74
191
+ 16.76
192
+ 16.83
193
+ 16.84
194
+ 16.82
195
+ 16.89
196
+ 16.93
197
+ 16.94
198
+ 16.9
199
+ 16.92
200
+ 16.88
201
+ 16.85
202
+ 16.87
203
+ 16.8
204
+ 16.79
205
+ 16.85
206
+ 16.85
207
+ 16.8
208
+ 16.82
209
+ 16.85
210
+ 16.9
211
+ 16.86
212
+ 16.79
213
+ 16.75
214
+ 16.78
215
+ 17.06
216
+ 17.05
217
+ 17.04
218
+ 17.02
219
+ 17.01
220
+ 17.02
221
+ 17.05
222
+ 17.07
223
+ 17.08
224
+ 17.09
225
+ 17.1
226
+ 17.11
227
+ 17.09
228
+ 17.1
229
+ 17.1
230
+ 17.12
231
+ 17.17
232
+ 17.16
233
+ 17.17
234
+ 17.18
235
+ 17.18
236
+ 17.18
237
+ 17.17
238
+ 17.15
239
+ 17.14
240
+ 17.13
241
+ 17.14
242
+ 17.13
243
+ 17.12
244
+ 17.12
245
+ 17.09
246
+ 17.09
247
+ 17.11
248
+ 17.06
249
+ 17.07
250
+ 17.06
251
+ 17.07
252
+ 17.06
253
+ 17.09
254
+ 17.05
255
+ 17.04
256
+ 17.04
257
+ 16.99
258
+ 17
259
+ 17.03
260
+ 17
261
+ 16.97
262
+ 16.96
263
+ 16.98
264
+ 16.98
265
+ 16.98
266
+ 17.03
267
+ 17
268
+ 17
269
+ 17
270
+ 17.02
271
+ 17
272
+ 17.02
273
+ 17.01
274
+ 17.02
275
+ 17.03
276
+ 17.03
277
+ 17.01
278
+ 17.03
279
+ 17.03
280
+ 17.03
281
+ 17.01
282
+ 17.03
283
+ 17.05
284
+ 17.05
285
+ 17.08
286
+ 17.04
287
+ 17.01
288
+ 17.03
289
+ 17.02
290
+ 17.03
291
+ 17.04
292
+ 17.05
293
+ 17.37
294
+ 17.35
295
+ 17.34
296
+ 17.32
297
+ 17.29
298
+ 17.29
299
+ 17.22
300
+ 17.26
301
+ 17.3
302
+ 17.34
303
+ 17.33
304
+ 17.39
305
+ 17.4
306
+ 17.39
307
+ 17.48
308
+ 17.5
309
+ 17.47
310
+ 17.43
311
+ 17.4
312
+ 17.42
313
+ 17.46
314
+ 17.48
315
+ 17.48
316
+ 17.46
317
+ 17.46
318
+ 17.45
319
+ 17.43
320
+ 17.44
321
+ 17.48
322
+ 17.43
323
+ 17.45
324
+ 17.47
325
+ 17.46
326
+ 17.46
327
+ 17.48
328
+ 17.48
329
+ 17.48
330
+ 17.46
331
+ 17.5
332
+ 17.55
333
+ 17.58
334
+ 17.57
335
+ 17.56
336
+ 17.59
337
+ 17.61
338
+ 17.62
339
+ 17.63
340
+ 17.62
341
+ 17.61
342
+ 17.61
343
+ 17.62
344
+ 17.64
345
+ 17.65
346
+ 17.61
347
+ 17.62
348
+ 17.66
349
+ 17.65
350
+ 17.64
351
+ 17.63
352
+ 17.64
353
+ 17.64
354
+ 17.64
355
+ 17.63
356
+ 17.61
357
+ 17.61
358
+ 17.62
359
+ 17.63
360
+ 17.64
361
+ 17.65
362
+ 17.66
363
+ 17.68
364
+ 17.69
365
+ 17.69
366
+ 17.69
367
+ 17.66
368
+ 17.69
369
+ 17.69
370
+ 17.62
371
+ 17.68
372
+ 17.64
373
+ 17.65
374
+ 17.61
375
+ 17.52
376
+ 17.56
377
+ 17.55
378
+ 17.55
379
+ 17.48
380
+ 17.45
381
+ 17.46
382
+ 17.46
383
+ 17.44
384
+ 17.47
385
+ 17.5
386
+ 17.49
387
+ 17.5
388
+ 17.53
389
+ 17.53
390
+ 17.54
391
+ 17.51
392
+ 17.51
393
+ 17.53
394
+ 17.53
395
+ 17.53
396
+ 17.55
397
+ 17.55
398
+ 17.54
399
+ 17.56
400
+ 17.59
401
+ 17.57
402
+ 17.58
403
+ 17.58
404
+ 17.57
405
+ 17.59
406
+ 17.57
407
+ 17.55
408
+ 17.51
409
+ 17.51
410
+ 17.52
411
+ 17.52
412
+ 17.53
413
+ 17.55
414
+ 17.59
415
+ 17.61
416
+ 17.61
417
+ 17.6
418
+ 17.6
419
+ 17.62
420
+ 17.65
421
+ 17.62
422
+ 17.6
423
+ 17.6
424
+ 17.62
425
+ 17.61
426
+ 17.62
427
+ 17.63
428
+ 17.64
429
+ 17.65
430
+ 17.61
431
+ 17.62
432
+ 17.64
433
+ 17.63
434
+ 17.62
435
+ 17.6
436
+ 17.57
437
+ 17.57
438
+ 17.6
439
+ 17.59
440
+ 17.6
441
+ 17.61
442
+ 17.61
443
+ 17.63
444
+ 17.63
445
+ 17.59
446
+ 17.58
447
+ 17.76
448
+ 17.79
449
+ 17.76
450
+ 17.73
451
+ 17.74
452
+ 17.73
453
+ 17.67
454
+ 17.66
455
+ 17.66
456
+ 17.64
457
+ 17.63
458
+ 17.62
459
+ 17.61
460
+ 17.6
461
+ 17.61
462
+ 17.61
463
+ 17.6
464
+ 17.6
465
+ 17.64
466
+ 17.65
467
+ 17.65
468
+ 17.63
469
+ 17.61
470
+ 17.6
471
+ 17.63
472
+ 17.63
473
+ 17.62
474
+ 17.63
475
+ 17.64
476
+ 17.62
477
+ 17.63
478
+ 17.65
479
+ 17.64
480
+ 17.6
481
+ 17.59
482
+ 17.59
483
+ 17.58
484
+ 17.58
485
+ 17.6
486
+ 17.6
487
+ 17.6
488
+ 17.6
489
+ 17.6
490
+ 17.58
491
+ 17.59
492
+ 17.6
493
+ 17.6
494
+ 17.6
495
+ 17.59
496
+ 17.59
497
+ 17.58
498
+ 17.58
499
+ 17.65
500
+ 17.65