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