statsample-timeseries 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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