daru 0.1.2 → 0.1.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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +99 -0
- data/.rubocop_todo.yml +44 -0
- data/.travis.yml +3 -1
- data/CONTRIBUTING.md +5 -1
- data/History.md +43 -0
- data/README.md +3 -4
- data/benchmarks/duplicating.rb +45 -0
- data/benchmarks/group_by.rb +7 -7
- data/benchmarks/joining.rb +52 -0
- data/benchmarks/sorting.rb +9 -2
- data/benchmarks/statistics.rb +39 -0
- data/daru.gemspec +4 -4
- data/lib/daru.rb +9 -9
- data/lib/daru/accessors/array_wrapper.rb +15 -11
- data/lib/daru/accessors/dataframe_by_row.rb +1 -1
- data/lib/daru/accessors/gsl_wrapper.rb +30 -19
- data/lib/daru/accessors/mdarray_wrapper.rb +1 -3
- data/lib/daru/accessors/nmatrix_wrapper.rb +15 -15
- data/lib/daru/core/group_by.rb +69 -16
- data/lib/daru/core/merge.rb +135 -151
- data/lib/daru/core/query.rb +9 -30
- data/lib/daru/dataframe.rb +476 -439
- data/lib/daru/date_time/index.rb +150 -137
- data/lib/daru/date_time/offsets.rb +45 -41
- data/lib/daru/extensions/rserve.rb +4 -4
- data/lib/daru/index.rb +88 -64
- data/lib/daru/io/io.rb +33 -34
- data/lib/daru/io/sql_data_source.rb +11 -11
- data/lib/daru/maths/arithmetic/dataframe.rb +19 -19
- data/lib/daru/maths/arithmetic/vector.rb +9 -14
- data/lib/daru/maths/statistics/dataframe.rb +89 -61
- data/lib/daru/maths/statistics/vector.rb +226 -97
- data/lib/daru/monkeys.rb +23 -30
- data/lib/daru/plotting/dataframe.rb +27 -28
- data/lib/daru/plotting/vector.rb +12 -13
- data/lib/daru/vector.rb +221 -330
- data/lib/daru/version.rb +2 -2
- data/spec/core/group_by_spec.rb +16 -0
- data/spec/core/merge_spec.rb +30 -14
- data/spec/dataframe_spec.rb +268 -14
- data/spec/index_spec.rb +23 -5
- data/spec/io/io_spec.rb +37 -16
- data/spec/math/statistics/dataframe_spec.rb +40 -8
- data/spec/math/statistics/vector_spec.rb +135 -10
- data/spec/monkeys_spec.rb +3 -3
- data/spec/vector_spec.rb +157 -25
- metadata +41 -21
data/spec/index_spec.rb
CHANGED
@@ -37,6 +37,16 @@ describe Daru::Index do
|
|
37
37
|
expect(idx.to_a).to eq(['speaker', 'mic', 'guitar', 'amp'])
|
38
38
|
end
|
39
39
|
|
40
|
+
it "creates an Index from Range" do
|
41
|
+
idx = Daru::Index.new 1..5
|
42
|
+
|
43
|
+
expect(idx).to eq(Daru::Index.new [1, 2, 3, 4, 5])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "raises ArgumentError on invalid input type" do
|
47
|
+
expect { Daru::Index.new 'foo' }.to raise_error ArgumentError
|
48
|
+
end
|
49
|
+
|
40
50
|
it "accepts all sorts of objects for Indexing" do
|
41
51
|
idx = Daru::Index.new [:a, 'a', :hello, '23', 23]
|
42
52
|
|
@@ -76,7 +86,7 @@ describe Daru::Index do
|
|
76
86
|
context "#[]" do
|
77
87
|
before do
|
78
88
|
@id = Daru::Index.new [:one, :two, :three, :four, :five, :six, :seven]
|
79
|
-
@mixed_id = Daru::Index.new ['a','b','c',:d,:a,
|
89
|
+
@mixed_id = Daru::Index.new ['a','b','c',:d,:a,8,3,5]
|
80
90
|
end
|
81
91
|
|
82
92
|
it "works with ranges" do
|
@@ -88,12 +98,12 @@ describe Daru::Index do
|
|
88
98
|
expect(@mixed_id[0..2]).to eq(Daru::Index.new(['a','b','c']))
|
89
99
|
|
90
100
|
# If atleast one is a number then refer to actual indexing
|
91
|
-
expect(@mixed_id.slice('b',
|
101
|
+
expect(@mixed_id.slice('b',8)).to eq(Daru::Index.new(['b','c',:d,:a,8]))
|
92
102
|
end
|
93
103
|
|
94
104
|
it "returns multiple keys if specified multiple indices" do
|
95
|
-
expect(@id[0,1,3,4]).to eq(Daru::Index.new([
|
96
|
-
expect(@mixed_id[0,5,3,2]).to eq(Daru::Index.new([
|
105
|
+
expect(@id[0,1,3,4]).to eq(Daru::Index.new([:one, :two, :four, :five]))
|
106
|
+
expect(@mixed_id[0,5,3,2]).to eq(Daru::Index.new(['a', 8, :d, 'c']))
|
97
107
|
end
|
98
108
|
|
99
109
|
it "returns correct index position for non-numeric index" do
|
@@ -102,7 +112,7 @@ describe Daru::Index do
|
|
102
112
|
end
|
103
113
|
|
104
114
|
it "returns correct index position for mixed index" do
|
105
|
-
expect(@mixed_id[
|
115
|
+
expect(@mixed_id[8]).to eq(5)
|
106
116
|
expect(@mixed_id['c']).to eq(2)
|
107
117
|
end
|
108
118
|
end
|
@@ -204,6 +214,14 @@ describe Daru::MultiIndex do
|
|
204
214
|
]))
|
205
215
|
end
|
206
216
|
|
217
|
+
it "raises error when specifying invalid index" do
|
218
|
+
expect { @multi_mi[:a, :three] }.to raise_error IndexError
|
219
|
+
expect { @multi_mi[:a, :one, :xyz] }.to raise_error IndexError
|
220
|
+
expect { @multi_mi[:x] }.to raise_error IndexError
|
221
|
+
expect { @multi_mi[:x, :one] }.to raise_error IndexError
|
222
|
+
expect { @multi_mi[:x, :one, :bar] }.to raise_error IndexError
|
223
|
+
end
|
224
|
+
|
207
225
|
it "works with numerical first levels" do
|
208
226
|
mi = Daru::MultiIndex.from_tuples([
|
209
227
|
[2000, 'M'],
|
data/spec/io/io_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Daru::IO do
|
|
4
4
|
describe Daru::DataFrame do
|
5
5
|
context ".from_csv" do
|
6
6
|
it "loads from a CSV file" do
|
7
|
-
df = Daru::DataFrame.from_csv('spec/fixtures/matrix_test.csv',
|
7
|
+
df = Daru::DataFrame.from_csv('spec/fixtures/matrix_test.csv',
|
8
8
|
col_sep: ' ', headers: true)
|
9
9
|
|
10
10
|
df.vectors = [:image_resolution, :mls, :true_transform].to_index
|
@@ -15,7 +15,7 @@ describe Daru::IO do
|
|
15
15
|
|
16
16
|
it "works properly for repeated headers" do
|
17
17
|
df = Daru::DataFrame.from_csv('spec/fixtures/repeated_fields.csv',header_converters: :symbol)
|
18
|
-
expect(df.vectors.to_a).to eq([
|
18
|
+
expect(df.vectors.to_a).to eq(["id", "name_1", "age_1", "city", "a1", "name_2", "age_2"])
|
19
19
|
|
20
20
|
age = Daru::Vector.new([3, 4, 5, 6, nil, 8])
|
21
21
|
expect(df['age_2']).to eq(age)
|
@@ -29,20 +29,41 @@ describe Daru::IO do
|
|
29
29
|
expect(y_ds).to be_within(0.001).of(y_expected)
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
it "follows the order of columns given in CSV" do
|
34
|
+
df = Daru::DataFrame.from_csv 'spec/fixtures/sales-funnel.csv'
|
35
|
+
expect(df.vectors.to_a).to eq(%W[Account Name Rep Manager Product Quantity Price Status])
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
context "#write_csv" do
|
35
|
-
|
36
|
-
df = Daru::DataFrame.new({
|
37
|
-
'a' => [1,2,3,4,5],
|
40
|
+
before do
|
41
|
+
@df = Daru::DataFrame.new({
|
42
|
+
'a' => [1,2,3,4,5],
|
38
43
|
'b' => [11,22,33,44,55],
|
39
44
|
'c' => ['a', 'g', 4, 5,'addadf'],
|
40
45
|
'd' => [nil, 23, 4,'a','ff']})
|
41
|
-
|
42
|
-
df.write_csv t.path
|
46
|
+
@tempfile = Tempfile.new('data.csv')
|
43
47
|
|
44
|
-
expect(Daru::DataFrame.from_csv(t.path)).to eq(df)
|
45
48
|
end
|
49
|
+
|
50
|
+
it "writes DataFrame to a CSV file" do
|
51
|
+
@df.write_csv @tempfile.path
|
52
|
+
expect(Daru::DataFrame.from_csv(@tempfile.path)).to eq(@df)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "will write headers unless headers=false" do
|
56
|
+
@df.write_csv @tempfile.path
|
57
|
+
first_line = File.open(@tempfile.path, &:readline).chomp.split(',', -1)
|
58
|
+
expect(first_line).to eq @df.vectors.to_a
|
59
|
+
end
|
60
|
+
|
61
|
+
it "will not write headers when headers=false" do
|
62
|
+
@df.write_csv @tempfile.path, { headers: false }
|
63
|
+
first_line = File.open(@tempfile.path, &:readline).chomp.split(',', -1)
|
64
|
+
expect(first_line).to eq @df.head(1).map { |v| (v.first || '').to_s }
|
65
|
+
end
|
66
|
+
|
46
67
|
end
|
47
68
|
|
48
69
|
context ".from_excel" do
|
@@ -52,8 +73,8 @@ describe Daru::IO do
|
|
52
73
|
age = Daru::Vector.new( [20, 23, 25, nil, 5.5, nil])
|
53
74
|
city = Daru::Vector.new(['New York', 'London', 'London', 'Paris', 'Tome', nil])
|
54
75
|
a1 = Daru::Vector.new(['a,b', 'b,c', 'a', nil, 'a,b,c', nil])
|
55
|
-
@expected = Daru::DataFrame.new({
|
56
|
-
:id => id, :name => name, :age => age, :city => city, :a1 => a1
|
76
|
+
@expected = Daru::DataFrame.new({
|
77
|
+
:id => id, :name => name, :age => age, :city => city, :a1 => a1
|
57
78
|
}, order: [:id, :name, :age, :city, :a1])
|
58
79
|
end
|
59
80
|
|
@@ -190,8 +211,8 @@ describe Daru::IO do
|
|
190
211
|
df = Daru::DataFrame.new JSON.parse(json)
|
191
212
|
|
192
213
|
expect(df.vectors).to eq([
|
193
|
-
'name', 'nativeName', 'tld', 'cca2', 'ccn3', 'cca3', 'currency', 'callingCode',
|
194
|
-
'capital', 'altSpellings', 'relevance', 'region', 'subregion', 'language',
|
214
|
+
'name', 'nativeName', 'tld', 'cca2', 'ccn3', 'cca3', 'currency', 'callingCode',
|
215
|
+
'capital', 'altSpellings', 'relevance', 'region', 'subregion', 'language',
|
195
216
|
'languageCodes', 'translations', 'latlng', 'demonym', 'borders', 'area'].to_index)
|
196
217
|
|
197
218
|
expect(df.row[0]['name']).to eq("Afghanistan")
|
@@ -208,9 +229,9 @@ describe Daru::IO do
|
|
208
229
|
|
209
230
|
context "#save" do
|
210
231
|
before do
|
211
|
-
@data_frame = Daru::DataFrame.new({b: [11,12,13,14,15], a: [1,2,3,4,5],
|
212
|
-
c: [11,22,33,44,55]},
|
213
|
-
order: [:a, :b, :c],
|
232
|
+
@data_frame = Daru::DataFrame.new({b: [11,12,13,14,15], a: [1,2,3,4,5],
|
233
|
+
c: [11,22,33,44,55]},
|
234
|
+
order: [:a, :b, :c],
|
214
235
|
index: [:one, :two, :three, :four, :five])
|
215
236
|
end
|
216
237
|
|
@@ -235,7 +256,7 @@ describe Daru::IO do
|
|
235
256
|
ALL_DTYPES.each do |dtype|
|
236
257
|
it "saves to a file and returns the same Vector of type #{dtype}" do
|
237
258
|
vector = Daru::Vector.new(
|
238
|
-
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
|
259
|
+
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
|
239
260
|
dtype: dtype)
|
240
261
|
outfile = Tempfile.new('vector.vec')
|
241
262
|
vector.save(outfile.path)
|
@@ -24,28 +24,40 @@ describe Daru::DataFrame do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
context "#variance_sample" do
|
28
|
+
it "calculates variance of single level numeric only vectors and returns values in a Vector" do
|
29
|
+
expect(@df.variance_sample).to eq(Daru::Vector.new([4.0, 16.0, 400.0], index: [:d, :e, :f]))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
27
33
|
context "#std" do
|
28
|
-
it "calculates standard deviation of single
|
34
|
+
it "calculates standard deviation of single level numeric only vectors and returns values in a Vector" do
|
29
35
|
expect(@df.std).to eq(Daru::Vector.new([2, 4, 20], index: [:d, :e, :f]))
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
39
|
context "#sum" do
|
34
40
|
it "calculates sum of single level numeric only vectors and returns values in a Vector" do
|
35
|
-
|
41
|
+
expect(@df.sum).to eq(Daru::Vector.new([33, 66, 330], index: [:d, :e, :f]))
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
39
45
|
context "#count" do
|
40
|
-
|
46
|
+
it "counts number of non-nil single level numeric only vectors and returns values in a Vector" do
|
47
|
+
expect(@df.count).to eq(Daru::Vector.new([9, 9, 9], index: [:d, :e, :f]))
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
context "#mode" do
|
44
|
-
|
52
|
+
it "calculates mode of single level numeric only vectors and returns values in a Vector" do
|
53
|
+
expect(@df.mode).to eq(Daru::Vector.new([2, 4, 20], index: [:d, :e, :f]))
|
54
|
+
end
|
45
55
|
end
|
46
56
|
|
47
57
|
context "#median" do
|
48
|
-
|
58
|
+
it "calculates median of single level numeric only vectors and returns values in a Vector" do
|
59
|
+
expect(@df.median).to eq(Daru::Vector.new([3, 6, 30], index: [:d, :e, :f]))
|
60
|
+
end
|
49
61
|
end
|
50
62
|
|
51
63
|
context "#max" do
|
@@ -61,11 +73,21 @@ describe Daru::DataFrame do
|
|
61
73
|
end
|
62
74
|
|
63
75
|
context "#min" do
|
64
|
-
|
76
|
+
it "calculates mininum of single level numeric only vectors and returns values in a Vector" do
|
77
|
+
expect(@df.min).to eq(Daru::Vector.new([1, 2, 10], index: [:d, :e, :f]))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "#range" do
|
82
|
+
it "calculates range of single level numeric only vectors and returns values in a Vector" do
|
83
|
+
expect(@df.range).to eq(Daru::Vector.new([6, 12, 60], index: [:d, :e, :f]))
|
84
|
+
end
|
65
85
|
end
|
66
86
|
|
67
87
|
context "#product" do
|
68
|
-
|
88
|
+
it "calculates product of single level numeric only vectors and returns values in a Vector" do
|
89
|
+
expect(@df.product).to eq(Daru::Vector.new([30240, 15482880, 30240000000000], index: [:d, :e, :f]))
|
90
|
+
end
|
69
91
|
end
|
70
92
|
|
71
93
|
context "#describe" do
|
@@ -79,6 +101,16 @@ describe Daru::DataFrame do
|
|
79
101
|
end
|
80
102
|
end
|
81
103
|
|
104
|
+
context "percent_change" do
|
105
|
+
it "calculates percent change of numeric vectors" do
|
106
|
+
expect(@df.percent_change.round(2)).to eq(Daru::DataFrame.new({
|
107
|
+
d: [nil, 1.0, 0.0, 0.5, 0.0, 0.33, 0.25, 0.2, 0.17],
|
108
|
+
e: [nil, 1.0, 0.0, 0.5, 0.0, 0.33, 0.25, 0.2, 0.17],
|
109
|
+
f: [nil, 1.0, 0.0, 0.5, 0.0, 0.33, 0.25, 0.2, 0.17] }
|
110
|
+
))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
82
114
|
context "#cov" do
|
83
115
|
it "calculates the variance covariance of the numeric vectors of DataFrame" do
|
84
116
|
expect(@df.cov).to eq(Daru::DataFrame.new({
|
@@ -145,4 +177,4 @@ describe Daru::DataFrame do
|
|
145
177
|
@df.standardize
|
146
178
|
end
|
147
179
|
end
|
148
|
-
end
|
180
|
+
end
|
@@ -6,12 +6,15 @@ describe Daru::Vector do
|
|
6
6
|
before do
|
7
7
|
@dv = Daru::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2], dtype: dtype
|
8
8
|
@dv_with_nils = Daru::Vector.new [323, 11, 555, nil, 666, 234, 21, 666, 343, nil, 1, 2]
|
9
|
+
@dv_with_missing = Daru::Vector.new [1, 2, 3, 3], missing_values: [3], dtype: dtype
|
10
|
+
@dv_with_all_missing = Daru::Vector.new [3, 3], missing_values: [3], dtype: dtype
|
9
11
|
end
|
10
12
|
|
11
13
|
context "#mean" do
|
12
14
|
it "calculates mean" do
|
13
15
|
expect(@dv.mean).to eq(282.2)
|
14
|
-
expect(@
|
16
|
+
expect(@dv_with_missing.mean).to eq(1.5)
|
17
|
+
expect(@dv_with_all_missing.mean).to eq(nil)
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
@@ -46,6 +49,22 @@ describe Daru::Vector do
|
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
52
|
+
context "#covariance_sample" do
|
53
|
+
it "calculates sample covariance" do
|
54
|
+
@dv_1 = Daru::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2]
|
55
|
+
@dv_2 = Daru::Vector.new [123, 22, 444, 555, 324, 21, 666, 434, 5, 8]
|
56
|
+
expect(@dv_1.covariance @dv_2).to be_within(0.00001).of(65603.62222)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "#covariance_population" do
|
61
|
+
it "calculates population covariance" do
|
62
|
+
@dv_1 = Daru::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2]
|
63
|
+
@dv_2 = Daru::Vector.new [123, 22, 444, 555, 324, 21, 666, 434, 5, 8]
|
64
|
+
expect(@dv_1.covariance_population @dv_2).to be_within(0.01).of(59043.26)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
49
68
|
context "#sum_of_squared_deviation" do
|
50
69
|
it "calculates sum of squared deviation" do
|
51
70
|
expect(@dv.sum_of_squared_deviation).to eq(676069.6)
|
@@ -60,20 +79,44 @@ describe Daru::Vector do
|
|
60
79
|
|
61
80
|
context "#max" do
|
62
81
|
it "returns the max value" do
|
63
|
-
@dv.max
|
82
|
+
expect(@dv.max).to eq(666)
|
64
83
|
end
|
84
|
+
|
85
|
+
it "returns the max value without considering values set as missing" do
|
86
|
+
expect(@dv_with_missing.max).to eq(2)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns nil when all values are set missing" do
|
90
|
+
expect(@dv_with_all_missing.max).to eq(nil)
|
91
|
+
end
|
65
92
|
end
|
66
93
|
|
67
94
|
context "#min" do
|
68
95
|
it "returns the min value" do
|
69
|
-
@dv.min
|
96
|
+
expect(@dv.min).to eq(1)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "returns the min value without considering values set as missing" do
|
100
|
+
expect(@dv_with_missing.min).to eq(1)
|
70
101
|
end
|
102
|
+
|
103
|
+
it "returns nil when all values are set missing" do
|
104
|
+
expect(@dv_with_all_missing.min).to eq(nil)
|
105
|
+
end
|
71
106
|
end
|
72
107
|
|
73
108
|
context "#sum" do
|
74
109
|
it "returns the sum" do
|
75
|
-
@dv.sum
|
110
|
+
expect(@dv.sum).to eq(2822)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "returns the sum without considering values set as missing" do
|
114
|
+
expect(@dv_with_missing.sum).to eq(3)
|
76
115
|
end
|
116
|
+
|
117
|
+
it "returns nil when all values are set missing" do
|
118
|
+
expect(@dv_with_all_missing.sum).to eq(nil)
|
119
|
+
end
|
77
120
|
end
|
78
121
|
|
79
122
|
context "#product" do
|
@@ -81,6 +124,14 @@ describe Daru::Vector do
|
|
81
124
|
v = Daru::Vector.new [1, 2, 3, 4, 5], dtype: dtype
|
82
125
|
expect(v.product).to eq(120)
|
83
126
|
end
|
127
|
+
|
128
|
+
it "returns the product without considering values set as missing" do
|
129
|
+
expect(@dv_with_missing.product).to eq(2)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "returns nil when all values are set missing" do
|
133
|
+
expect(@dv_with_all_missing.product).to eq(nil)
|
134
|
+
end
|
84
135
|
end
|
85
136
|
|
86
137
|
context "#median" do
|
@@ -91,7 +142,17 @@ describe Daru::Vector do
|
|
91
142
|
|
92
143
|
context "#mode" do
|
93
144
|
it "returns the mode" do
|
94
|
-
|
145
|
+
mode_test_example = Daru::Vector.new [1,2,3,2,4,4,4,4], dtype: dtype
|
146
|
+
expect(mode_test_example.mode).to eq(4)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "#describe" do
|
151
|
+
it "generates count, mean, std, min and max of vectors in one shot" do
|
152
|
+
expect(@dv.describe.round(2)).to eq(Daru::Vector.new([10.00, 282.20, 274.08, 1.00, 666.00],
|
153
|
+
index: [:count, :mean, :std, :min, :max],
|
154
|
+
name: :statistics
|
155
|
+
))
|
95
156
|
end
|
96
157
|
end
|
97
158
|
|
@@ -373,6 +434,20 @@ describe Daru::Vector do
|
|
373
434
|
expect(acf[3]).to be_within(0.001) .of(0.486)
|
374
435
|
end
|
375
436
|
end
|
437
|
+
|
438
|
+
context "#percent_change" do
|
439
|
+
it "calculates percent change" do
|
440
|
+
vector = Daru::Vector.new([4,6,6,8,10],index: ['a','f','t','i','k'])
|
441
|
+
expect(vector.percent_change).to eq(
|
442
|
+
Daru::Vector.new([nil, 0.5, 0.0, 0.3333333333333333, 0.25], index: ['a','f','t','i','k']))
|
443
|
+
end
|
444
|
+
|
445
|
+
it "tests for numerical vectors with nils" do
|
446
|
+
vector2 = Daru::Vector.new([nil,6,nil,8,10],index: ['a','f','t','i','k'])
|
447
|
+
expect(vector2.percent_change).to eq(
|
448
|
+
Daru::Vector.new([nil, nil, nil, 0.3333333333333333, 0.25], index: ['a','f','t','i','k']))
|
449
|
+
end
|
450
|
+
end
|
376
451
|
|
377
452
|
context "#diff" do
|
378
453
|
it "performs the difference of the series" do
|
@@ -463,12 +538,12 @@ describe Daru::Vector do
|
|
463
538
|
expect(ema10[-5]) .to be_within(0.00001).of( 17.19187)
|
464
539
|
expect(ema10[-10]).to be_within(0.00001).of( 17.54918)
|
465
540
|
|
466
|
-
# test with a different
|
541
|
+
# test with a different loopback period
|
467
542
|
ema5 = @shares.ema 5
|
468
543
|
|
469
|
-
expect(ema5[-1]) .to be_within( 0.
|
470
|
-
expect(ema5[-10]).to be_within( 0.
|
471
|
-
expect(ema5[-15]).to be_within( 0.
|
544
|
+
expect(ema5[-1]) .to be_within( 0.00001).of(16.71299)
|
545
|
+
expect(ema5[-10]).to be_within( 0.00001).of(17.49079)
|
546
|
+
expect(ema5[-15]).to be_within( 0.00001).of(17.70067)
|
472
547
|
|
473
548
|
# test with a different smoother
|
474
549
|
ema_w = @shares.ema 10, true
|
@@ -479,6 +554,56 @@ describe Daru::Vector do
|
|
479
554
|
end
|
480
555
|
end
|
481
556
|
|
557
|
+
context "#emv" do
|
558
|
+
it "calculates exponential moving variance" do
|
559
|
+
# test default
|
560
|
+
emv10 = @shares.emv
|
561
|
+
|
562
|
+
expect(emv10[-1]) .to be_within(0.00001).of(0.14441)
|
563
|
+
expect(emv10[-5]) .to be_within(0.00001).of(0.10797)
|
564
|
+
expect(emv10[-10]).to be_within(0.00001).of(0.03979)
|
565
|
+
|
566
|
+
# test with a different loopback period
|
567
|
+
emv5 = @shares.emv 5
|
568
|
+
|
569
|
+
expect(emv5[-1]) .to be_within(0.00001).of(0.05172)
|
570
|
+
expect(emv5[-10]).to be_within(0.00001).of(0.01736)
|
571
|
+
expect(emv5[-15]).to be_within(0.00001).of(0.04410)
|
572
|
+
|
573
|
+
# test with a different smoother
|
574
|
+
emv_w = @shares.emv 10, true
|
575
|
+
|
576
|
+
expect(emv_w[-1]) .to be_within(0.00001).of(0.20318)
|
577
|
+
expect(emv_w[-5]) .to be_within(0.00001).of(0.11319)
|
578
|
+
expect(emv_w[-10]).to be_within(0.00001).of(0.04289)
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
context "#emsd" do
|
583
|
+
it "calculates exponential moving standard deviation" do
|
584
|
+
# test default
|
585
|
+
emsd10 = @shares.emsd
|
586
|
+
|
587
|
+
expect(emsd10[-1]) .to be_within(0.00001).of(0.38002)
|
588
|
+
expect(emsd10[-5]) .to be_within(0.00001).of(0.32859)
|
589
|
+
expect(emsd10[-10]).to be_within(0.00001).of(0.19947)
|
590
|
+
|
591
|
+
# test with a different loopback period
|
592
|
+
emsd5 = @shares.emsd 5
|
593
|
+
|
594
|
+
expect(emsd5[-1]) .to be_within(0.00001).of(0.22742)
|
595
|
+
expect(emsd5[-10]).to be_within(0.00001).of(0.13174)
|
596
|
+
expect(emsd5[-15]).to be_within(0.00001).of(0.21000)
|
597
|
+
|
598
|
+
# test with a different smoother
|
599
|
+
emsd_w = @shares.emsd 10, true
|
600
|
+
|
601
|
+
expect(emsd_w[-1]) .to be_within(0.00001).of(0.45076)
|
602
|
+
expect(emsd_w[-5]) .to be_within(0.00001).of(0.33644)
|
603
|
+
expect(emsd_w[-10]).to be_within(0.00001).of(0.20710)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
482
607
|
context "#macd" do
|
483
608
|
it "calculates moving average convergence divergence" do
|
484
609
|
# MACD uses a lot more data than the other ones, so we need a bigger vector
|
@@ -506,4 +631,4 @@ describe Daru::Vector do
|
|
506
631
|
Daru::Vector.new([1,3,6,10,15,21,28,36,45,55]))
|
507
632
|
end
|
508
633
|
end
|
509
|
-
end
|
634
|
+
end
|