daru 0.1.3.1 → 0.1.4
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/.rspec +2 -1
- data/.rspec_formatter.rb +33 -0
- data/.rubocop.yml +26 -2
- data/History.md +38 -0
- data/README.md +22 -13
- data/Rakefile +50 -2
- data/benchmarks/csv_reading.rb +22 -0
- data/daru.gemspec +9 -2
- data/lib/daru.rb +36 -4
- data/lib/daru/accessors/array_wrapper.rb +6 -1
- data/lib/daru/accessors/dataframe_by_row.rb +10 -2
- data/lib/daru/accessors/gsl_wrapper.rb +1 -3
- data/lib/daru/accessors/nmatrix_wrapper.rb +9 -0
- data/lib/daru/category.rb +935 -0
- data/lib/daru/core/group_by.rb +29 -38
- data/lib/daru/core/merge.rb +186 -145
- data/lib/daru/core/query.rb +22 -11
- data/lib/daru/dataframe.rb +976 -885
- data/lib/daru/date_time/index.rb +166 -166
- data/lib/daru/date_time/offsets.rb +66 -77
- data/lib/daru/formatters/table.rb +54 -0
- data/lib/daru/helpers/array.rb +40 -0
- data/lib/daru/index.rb +476 -73
- data/lib/daru/io/io.rb +66 -45
- data/lib/daru/io/sql_data_source.rb +33 -62
- data/lib/daru/iruby/helpers.rb +38 -0
- data/lib/daru/iruby/templates/dataframe.html.erb +52 -0
- data/lib/daru/iruby/templates/dataframe_mi.html.erb +58 -0
- data/lib/daru/iruby/templates/multi_index.html.erb +12 -0
- data/lib/daru/iruby/templates/vector.html.erb +27 -0
- data/lib/daru/iruby/templates/vector_mi.html.erb +36 -0
- data/lib/daru/maths/arithmetic/dataframe.rb +16 -18
- data/lib/daru/maths/arithmetic/vector.rb +4 -6
- data/lib/daru/maths/statistics/dataframe.rb +8 -15
- data/lib/daru/maths/statistics/vector.rb +120 -98
- data/lib/daru/monkeys.rb +12 -40
- data/lib/daru/plotting/gruff.rb +3 -0
- data/lib/daru/plotting/gruff/category.rb +49 -0
- data/lib/daru/plotting/gruff/dataframe.rb +91 -0
- data/lib/daru/plotting/gruff/vector.rb +57 -0
- data/lib/daru/plotting/nyaplot.rb +3 -0
- data/lib/daru/plotting/nyaplot/category.rb +34 -0
- data/lib/daru/plotting/nyaplot/dataframe.rb +187 -0
- data/lib/daru/plotting/nyaplot/vector.rb +46 -0
- data/lib/daru/vector.rb +694 -421
- data/lib/daru/version.rb +1 -1
- data/profile/_base.rb +23 -0
- data/profile/df_to_a.rb +10 -0
- data/profile/filter.rb +13 -0
- data/profile/joining.rb +13 -0
- data/profile/sorting.rb +12 -0
- data/profile/vector_each_with_index.rb +9 -0
- data/spec/accessors/wrappers_spec.rb +2 -4
- data/spec/categorical_spec.rb +1734 -0
- data/spec/core/group_by_spec.rb +52 -2
- data/spec/core/merge_spec.rb +63 -2
- data/spec/core/query_spec.rb +236 -80
- data/spec/dataframe_spec.rb +1373 -79
- data/spec/date_time/data_spec.rb +3 -5
- data/spec/date_time/index_spec.rb +154 -17
- data/spec/date_time/offsets_spec.rb +3 -4
- data/spec/fixtures/empties.dat +2 -0
- data/spec/fixtures/strings.dat +2 -0
- data/spec/formatters/table_formatter_spec.rb +99 -0
- data/spec/helpers_spec.rb +8 -0
- data/spec/index/categorical_index_spec.rb +168 -0
- data/spec/index/index_spec.rb +283 -0
- data/spec/index/multi_index_spec.rb +570 -0
- data/spec/io/io_spec.rb +31 -4
- data/spec/io/sql_data_source_spec.rb +0 -1
- data/spec/iruby/dataframe_spec.rb +172 -0
- data/spec/iruby/helpers_spec.rb +49 -0
- data/spec/iruby/multi_index_spec.rb +37 -0
- data/spec/iruby/vector_spec.rb +107 -0
- data/spec/math/arithmetic/dataframe_spec.rb +71 -13
- data/spec/math/arithmetic/vector_spec.rb +8 -10
- data/spec/math/statistics/dataframe_spec.rb +3 -5
- data/spec/math/statistics/vector_spec.rb +45 -55
- data/spec/monkeys_spec.rb +32 -9
- data/spec/plotting/dataframe_spec.rb +386 -0
- data/spec/plotting/vector_spec.rb +230 -0
- data/spec/shared/vector_display_spec.rb +215 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/vector_spec.rb +905 -138
- metadata +143 -11
- data/.rubocop_todo.yml +0 -44
- data/lib/daru/plotting/dataframe.rb +0 -104
- data/lib/daru/plotting/vector.rb +0 -38
- data/spec/daru_spec.rb +0 -58
- data/spec/index_spec.rb +0 -375
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe Daru::Vector do
|
4
2
|
before :each do
|
5
3
|
@dv1 = Daru::Vector.new [1,2,3,4], name: :boozy, index: [:bud, :kf, :henie, :corona]
|
@@ -30,7 +28,7 @@ describe Daru::Vector do
|
|
30
28
|
v1 = Daru::Vector.new([1,2,3])
|
31
29
|
v2 = Daru::Vector.new([1,2,3], index: [:a,:b,:c])
|
32
30
|
|
33
|
-
expect(v1 + v2).to eq(Daru::Vector.new([nil]*6, index: [0,1,2,:a,:b,:c]))
|
31
|
+
expect(v1 + v2).to eq(Daru::Vector.new([nil]*6, index: [0,1,2,:a,:b,:c]))
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
@@ -50,7 +48,7 @@ describe Daru::Vector do
|
|
50
48
|
end
|
51
49
|
|
52
50
|
it "multiplies number to each element of the entire vector" do
|
53
|
-
|
51
|
+
|
54
52
|
end
|
55
53
|
end
|
56
54
|
|
@@ -60,7 +58,7 @@ describe Daru::Vector do
|
|
60
58
|
end
|
61
59
|
|
62
60
|
it "divides number from each element of the entire vector" do
|
63
|
-
|
61
|
+
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
@@ -69,13 +67,13 @@ describe Daru::Vector do
|
|
69
67
|
end
|
70
68
|
|
71
69
|
context "#**" do
|
72
|
-
|
70
|
+
|
73
71
|
end
|
74
72
|
|
75
73
|
context "#exp" do
|
76
74
|
it "calculates exp of all numbers" do
|
77
|
-
expect(@with_md1.exp.round(3)).to eq(Daru::Vector.new([2.718281828459045,
|
78
|
-
7.38905609893065, 20.085536923187668, nil, 148.4131591025766, nil], index:
|
75
|
+
expect(@with_md1.exp.round(3)).to eq(Daru::Vector.new([2.718281828459045,
|
76
|
+
7.38905609893065, 20.085536923187668, nil, 148.4131591025766, nil], index:
|
79
77
|
[:a, :b, :c, :obi, :wan, :corona], name: :missing).round(3))
|
80
78
|
end
|
81
79
|
end
|
@@ -95,6 +93,6 @@ describe Daru::Vector do
|
|
95
93
|
context "#round" do
|
96
94
|
it "rounds to given precision" do
|
97
95
|
@with_md1.round(2)
|
98
|
-
end
|
96
|
+
end
|
99
97
|
end
|
100
|
-
end
|
98
|
+
end
|
@@ -1,9 +1,7 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe Daru::DataFrame do
|
4
2
|
before do
|
5
3
|
@df = Daru::DataFrame.new({
|
6
|
-
a: ['foo' , 'foo', 'foo', 'foo', 'foo', 'bar', 'bar', 'bar', 'bar'],
|
4
|
+
a: ['foo' , 'foo', 'foo', 'foo', 'foo', 'bar', 'bar', 'bar', 'bar'],
|
7
5
|
b: ['one' , 'one', 'one', 'two', 'two', 'one', 'one', 'two', 'two'],
|
8
6
|
c: ['small','large','large','small','small','large','small','large','small'],
|
9
7
|
d: [1,2,2,3,3,4,5,6,7],
|
@@ -14,7 +12,7 @@ describe Daru::DataFrame do
|
|
14
12
|
|
15
13
|
context "#mean" do
|
16
14
|
it "calculates mean of single level numeric only vectors and returns values in a Vector" do
|
17
|
-
expect(@df.mean.round(2)).to eq(Daru::Vector.new([3.67, 7.33, 36.67],
|
15
|
+
expect(@df.mean.round(2)).to eq(Daru::Vector.new([3.67, 7.33, 36.67],
|
18
16
|
index: [:d, :e, :f]
|
19
17
|
))
|
20
18
|
end
|
@@ -130,7 +128,7 @@ describe Daru::DataFrame do
|
|
130
128
|
b: [-0.0071019, 0.0020747, 0.0056071],
|
131
129
|
c: [-0.0153640, 0.0056071, 0.0230777]
|
132
130
|
})
|
133
|
-
|
131
|
+
|
134
132
|
test.cov.each_vector_with_index do |v, i|
|
135
133
|
expect_correct_vector_in_delta v, ans[i], 0.01
|
136
134
|
end
|
@@ -1,20 +1,14 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe Daru::Vector do
|
4
2
|
[:array, :gsl].each do |dtype| #nmatrix still unstable
|
5
3
|
describe dtype do
|
6
4
|
before do
|
7
5
|
@dv = Daru::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2], dtype: dtype
|
8
6
|
@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
|
11
7
|
end
|
12
8
|
|
13
9
|
context "#mean" do
|
14
10
|
it "calculates mean" do
|
15
11
|
expect(@dv.mean).to eq(282.2)
|
16
|
-
expect(@dv_with_missing.mean).to eq(1.5)
|
17
|
-
expect(@dv_with_all_missing.mean).to eq(nil)
|
18
12
|
end
|
19
13
|
end
|
20
14
|
|
@@ -81,42 +75,18 @@ describe Daru::Vector do
|
|
81
75
|
it "returns the max value" do
|
82
76
|
expect(@dv.max).to eq(666)
|
83
77
|
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
|
92
78
|
end
|
93
79
|
|
94
80
|
context "#min" do
|
95
81
|
it "returns the min value" do
|
96
82
|
expect(@dv.min).to eq(1)
|
97
83
|
end
|
98
|
-
|
99
|
-
it "returns the min value without considering values set as missing" do
|
100
|
-
expect(@dv_with_missing.min).to eq(1)
|
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
|
106
|
-
end
|
84
|
+
end
|
107
85
|
|
108
86
|
context "#sum" do
|
109
87
|
it "returns the sum" do
|
110
88
|
expect(@dv.sum).to eq(2822)
|
111
89
|
end
|
112
|
-
|
113
|
-
it "returns the sum without considering values set as missing" do
|
114
|
-
expect(@dv_with_missing.sum).to eq(3)
|
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
|
120
90
|
end
|
121
91
|
|
122
92
|
context "#product" do
|
@@ -124,14 +94,6 @@ describe Daru::Vector do
|
|
124
94
|
v = Daru::Vector.new [1, 2, 3, 4, 5], dtype: dtype
|
125
95
|
expect(v.product).to eq(120)
|
126
96
|
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
|
135
97
|
end
|
136
98
|
|
137
99
|
context "#median" do
|
@@ -146,11 +108,11 @@ describe Daru::Vector do
|
|
146
108
|
expect(mode_test_example.mode).to eq(4)
|
147
109
|
end
|
148
110
|
end
|
149
|
-
|
111
|
+
|
150
112
|
context "#describe" do
|
151
113
|
it "generates count, mean, std, min and max of vectors in one shot" do
|
152
114
|
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],
|
115
|
+
index: [:count, :mean, :std, :min, :max],
|
154
116
|
name: :statistics
|
155
117
|
))
|
156
118
|
end
|
@@ -164,18 +126,22 @@ describe Daru::Vector do
|
|
164
126
|
|
165
127
|
context "#count" do
|
166
128
|
it "counts specified element" do
|
167
|
-
@dv.count(323)
|
129
|
+
expect(@dv.count(323)).to eq(1)
|
168
130
|
end
|
169
131
|
|
170
132
|
it "counts total number of elements" do
|
171
133
|
expect(@dv.count).to eq(10)
|
172
134
|
end
|
135
|
+
|
136
|
+
it "counts by block provided" do
|
137
|
+
expect(@dv.count{|e| e.to_i.even? }).to eq(4)
|
138
|
+
end
|
173
139
|
end
|
174
140
|
|
175
141
|
context "#value_counts" do
|
176
142
|
it "counts number of unique values in the Vector" do
|
177
143
|
vector = Daru::Vector.new(
|
178
|
-
["America","America","America","America","America",
|
144
|
+
["America","America","America","America","America",
|
179
145
|
"India","India", "China", "India", "China"])
|
180
146
|
expect(vector.value_counts).to eq(
|
181
147
|
Daru::Vector.new([5,3,2], index: ["America", "India", "China"]))
|
@@ -192,6 +158,15 @@ describe Daru::Vector do
|
|
192
158
|
it "calculates mid point percentile" do
|
193
159
|
expect(@dv.percentile(50)).to eq(278.5)
|
194
160
|
end
|
161
|
+
|
162
|
+
it "calculates linear percentile" do
|
163
|
+
# FIXME: Not enough testing?..
|
164
|
+
expect(@dv.percentile(50, :linear)).to eq(278.5)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "fails on unknown strategy" do
|
168
|
+
expect { @dv.percentile(50, :killemall) }.to raise_error(ArgumentError, /strategy/)
|
169
|
+
end
|
195
170
|
end
|
196
171
|
|
197
172
|
context "#average_deviation_population" do
|
@@ -235,7 +210,7 @@ describe Daru::Vector do
|
|
235
210
|
end
|
236
211
|
end # ALL DTYPE tests
|
237
212
|
|
238
|
-
# Only Array tests
|
213
|
+
# Only Array tests
|
239
214
|
context "#percentile" do
|
240
215
|
it "tests linear percentile strategy" do
|
241
216
|
values = Daru::Vector.new [102, 104, 105, 107, 108, 109, 110, 112, 115, 116].shuffle
|
@@ -257,13 +232,22 @@ describe Daru::Vector do
|
|
257
232
|
context "#frequencies" do
|
258
233
|
it "calculates frequencies" do
|
259
234
|
vector = Daru::Vector.new([5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99])
|
260
|
-
expect(vector.frequencies).to eq({
|
261
|
-
1=>1, 2=>1, 3=>1, 4=>1, 5=>5,
|
235
|
+
expect(vector.frequencies).to eq({
|
236
|
+
1=>1, 2=>1, 3=>1, 4=>1, 5=>5,
|
262
237
|
6=>2, 7=>1, 8=>1, 9=>1,10=>1, -99=>2
|
263
238
|
})
|
264
239
|
end
|
265
240
|
end
|
266
241
|
|
242
|
+
context "#freqs" do
|
243
|
+
let(:vector) { Daru::Vector.new([5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99]) }
|
244
|
+
subject { vector.freqs }
|
245
|
+
it { is_expected.to eq Daru::Vector.new(
|
246
|
+
[5,2,1,1,1,1,1,1,1,1,2],
|
247
|
+
index: [5,6,7,8,9,10,1,2,3,4,-99]
|
248
|
+
)}
|
249
|
+
end
|
250
|
+
|
267
251
|
context "#ranked" do
|
268
252
|
it "curates by rank" do
|
269
253
|
vector = Daru::Vector.new([nil, 0.8, 1.2, 1.2, 2.3, 18, nil])
|
@@ -350,11 +334,11 @@ describe Daru::Vector do
|
|
350
334
|
)
|
351
335
|
end
|
352
336
|
end
|
353
|
-
|
337
|
+
|
354
338
|
context "#sample_with_replacement" do
|
355
339
|
it "calculates sample_with_replacement" do
|
356
340
|
vec = Daru::Vector.new(
|
357
|
-
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
341
|
+
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
358
342
|
name: :common_all_dtypes)
|
359
343
|
srand(1)
|
360
344
|
expect(vec.sample_with_replacement(100).size).to eq(100)
|
@@ -367,19 +351,19 @@ describe Daru::Vector do
|
|
367
351
|
context "#sample_without_replacement" do
|
368
352
|
it "calculates sample_without_replacement" do
|
369
353
|
vec = Daru::Vector.new(
|
370
|
-
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
354
|
+
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
371
355
|
name: :common_all_dtypes)
|
372
356
|
|
373
357
|
srand(1)
|
374
358
|
expect(vec.sample_without_replacement(17).sort).to eq(
|
375
|
-
vec.
|
359
|
+
vec.reject_values(*Daru::MISSING_VALUES).to_a.sort)
|
376
360
|
expect {
|
377
361
|
vec.sample_without_replacement(20)
|
378
362
|
}.to raise_error(ArgumentError)
|
379
363
|
|
380
364
|
srand(1)
|
381
365
|
expect(vec.sample_without_replacement(17).sort).to eq(
|
382
|
-
vec.
|
366
|
+
vec.reject_values(*Daru::MISSING_VALUES).to_a.sort)
|
383
367
|
end
|
384
368
|
end
|
385
369
|
|
@@ -408,7 +392,7 @@ describe Daru::Vector do
|
|
408
392
|
it "jack knife correctly with k > 1" do
|
409
393
|
rng = Distribution::Normal.rng(0,1)
|
410
394
|
a = Daru::Vector.new_with_size(6) { rng.call}
|
411
|
-
|
395
|
+
|
412
396
|
ds = a.jackknife(:mean, 2)
|
413
397
|
mean = a.mean
|
414
398
|
exp = Daru::Vector.new [3 * mean - 2 * (a[2] + a[3] + a[4] + a[5]) / 4, 3 * mean - 2 * (a[0] + a[1] + a[4] + a[5]) / 4, 3 * mean - 2 * (a[0] + a[1] + a[2] + a[3]) / 4]
|
@@ -434,7 +418,7 @@ describe Daru::Vector do
|
|
434
418
|
expect(acf[3]).to be_within(0.001) .of(0.486)
|
435
419
|
end
|
436
420
|
end
|
437
|
-
|
421
|
+
|
438
422
|
context "#percent_change" do
|
439
423
|
it "calculates percent change" do
|
440
424
|
vector = Daru::Vector.new([4,6,6,8,10],index: ['a','f','t','i','k'])
|
@@ -473,7 +457,7 @@ describe Daru::Vector do
|
|
473
457
|
|
474
458
|
expect(ma5[-1]).to be_within(0.001).of(16.642)
|
475
459
|
expect(ma5[-10]).to be_within(0.001).of(17.434)
|
476
|
-
expect(ma5[-15]).to be_within(0.001).of(17.74)
|
460
|
+
expect(ma5[-15]).to be_within(0.001).of(17.74)
|
477
461
|
end
|
478
462
|
|
479
463
|
it "calculates rolling median" do
|
@@ -630,5 +614,11 @@ describe Daru::Vector do
|
|
630
614
|
expect(vector.cumsum).to eq(
|
631
615
|
Daru::Vector.new([1,3,6,10,15,21,28,36,45,55]))
|
632
616
|
end
|
617
|
+
|
618
|
+
it "works with missing values" do
|
619
|
+
vector = Daru::Vector.new([1,2,nil,3,nil,4,5])
|
620
|
+
expect(vector.cumsum).to eq(
|
621
|
+
Daru::Vector.new([1,3,nil,6,nil,10,15]))
|
622
|
+
end
|
633
623
|
end
|
634
|
-
end
|
624
|
+
end
|
data/spec/monkeys_spec.rb
CHANGED
@@ -1,13 +1,4 @@
|
|
1
|
-
require 'spec_helper.rb'
|
2
|
-
|
3
1
|
describe "Monkeys" do
|
4
|
-
context Array do
|
5
|
-
it "#recode_repeated" do
|
6
|
-
expect([1,'a',1,'a','b',:c,2].recode_repeated).to eq(
|
7
|
-
['1_1','a_1', '1_2','a_2','b',:c,2])
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
2
|
context Matrix do
|
12
3
|
it "performs elementwise division" do
|
13
4
|
left = Matrix[[3,6,9],[4,8,12],[2,4,6]]
|
@@ -16,4 +7,36 @@ describe "Monkeys" do
|
|
16
7
|
expect(left.elementwise_division(right)).to eq(Matrix[[1,1,1],[1,1,1],[1,1,1]])
|
17
8
|
end
|
18
9
|
end
|
10
|
+
|
11
|
+
describe '#daru_vector' do
|
12
|
+
it 'converts Array' do
|
13
|
+
expect([1,2,3].daru_vector).to eq Daru::Vector.new [1,2,3]
|
14
|
+
expect([1,2,3].daru_vector('test', [:a, :b, :c])).to eq \
|
15
|
+
Daru::Vector.new [1,2,3], name: 'test', index: [:a, :b, :c]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'converts Range' do
|
19
|
+
expect((1..3).daru_vector).to eq Daru::Vector.new [1,2,3]
|
20
|
+
expect((1..3).daru_vector('test', [:a, :b, :c])).to eq \
|
21
|
+
Daru::Vector.new [1,2,3], name: 'test', index: [:a, :b, :c]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'converts Hash' do
|
25
|
+
# FIXME: is it most useful way of converting hashes?..
|
26
|
+
# I'd prefer something like
|
27
|
+
# expect({a: 1, b: 2, c: 3}.daru_vector('test')).to eq Daru::Vector.new [1,2,3], name: 'test', index: [:a, :b, :c]
|
28
|
+
#
|
29
|
+
expect({test: [1, 2, 3]}.daru_vector).to eq Daru::Vector.new [1,2,3], name: :test
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#to_index' do
|
34
|
+
it 'converts Array' do
|
35
|
+
expect([1,2,3].to_index).to eq Daru::Index.new [1,2,3]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'converts Range' do
|
39
|
+
expect((1..3).to_index).to eq Daru::Index.new [1,2,3]
|
40
|
+
end
|
41
|
+
end
|
19
42
|
end
|
@@ -0,0 +1,386 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
class Nyaplot::DataFrame
|
4
|
+
# Because it does not allow to any equality testing
|
5
|
+
def == other
|
6
|
+
other.is_a?(Nyaplot::DataFrame) && rows == other.rows
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# FIXME: just guessed specs logic from code. As far as I can understand,
|
11
|
+
# it can be broken in number of ways with incorrect arguments.
|
12
|
+
#
|
13
|
+
describe Daru::DataFrame, 'plotting' do
|
14
|
+
let(:data_frame) {
|
15
|
+
described_class.new({
|
16
|
+
x: [1, 2, 3, 4],
|
17
|
+
y1: [5, 7, 9, 11],
|
18
|
+
y2: [-3, -7, -11, -15],
|
19
|
+
cat: [:a, :b, :c, :d]
|
20
|
+
},
|
21
|
+
index: [:one, :two, :three, :four]
|
22
|
+
)
|
23
|
+
}
|
24
|
+
let(:plot) { instance_double('Nyaplot::Plot') }
|
25
|
+
let(:diagram) { instance_double('Nyaplot::Diagram') }
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow(Nyaplot::Plot).to receive(:new).and_return(plot)
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'box' do
|
32
|
+
let(:numerics) { data_frame.only_numerics }
|
33
|
+
it 'plots numeric vectors' do
|
34
|
+
expect(plot).to receive(:add_with_df)
|
35
|
+
.with(numerics.to_nyaplotdf, :box, :x, :y1, :y2)
|
36
|
+
.ordered
|
37
|
+
|
38
|
+
expect(plot).to receive(:show).ordered
|
39
|
+
data_frame.plot(type: :box)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'other types' do
|
44
|
+
context 'single chart' do
|
45
|
+
it 'works with :y provided' do
|
46
|
+
expect(plot).to receive(:add_with_df)
|
47
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x, :y1)
|
48
|
+
.ordered
|
49
|
+
|
50
|
+
expect(plot).to receive(:show).ordered
|
51
|
+
data_frame.plot(type: :scatter, x: :x, y: :y1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'works without :y provided' do
|
55
|
+
expect(plot).to receive(:add_with_df)
|
56
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x)
|
57
|
+
.ordered
|
58
|
+
|
59
|
+
expect(plot).to receive(:show).ordered
|
60
|
+
data_frame.plot(type: :scatter, x: :x)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'multiple charts' do
|
65
|
+
it 'works with single type provided' do
|
66
|
+
expect(plot).to receive(:add_with_df)
|
67
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x, :y1)
|
68
|
+
.ordered
|
69
|
+
expect(plot).to receive(:add_with_df)
|
70
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x, :y2)
|
71
|
+
.ordered
|
72
|
+
expect(plot).to receive(:show).ordered
|
73
|
+
|
74
|
+
data_frame.plot(type: :scatter, x: [:x, :x], y: [:y1, :y2])
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'works with multiple types provided' do
|
78
|
+
expect(plot).to receive(:add_with_df)
|
79
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x, :y1)
|
80
|
+
.ordered
|
81
|
+
expect(plot).to receive(:add_with_df)
|
82
|
+
.with(data_frame.to_nyaplotdf, :line, :x, :y2)
|
83
|
+
.ordered
|
84
|
+
expect(plot).to receive(:show).ordered
|
85
|
+
|
86
|
+
data_frame.plot(type: [:scatter, :line], x: [:x, :x], y: [:y1, :y2])
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'works with numeric var names' do
|
90
|
+
expect(plot).to receive(:add_with_df)
|
91
|
+
.with(data_frame.to_nyaplotdf, :scatter, :x, :y1)
|
92
|
+
.ordered
|
93
|
+
expect(plot).to receive(:add_with_df)
|
94
|
+
.with(data_frame.to_nyaplotdf, :line, :x, :y2)
|
95
|
+
.ordered
|
96
|
+
expect(plot).to receive(:show).ordered
|
97
|
+
|
98
|
+
data_frame.plot(
|
99
|
+
type: [:scatter, :line],
|
100
|
+
# FIXME: this didn't work due to default type: :scatter opts
|
101
|
+
#type1: :scatter,
|
102
|
+
#type2: :line,
|
103
|
+
x1: :x,
|
104
|
+
x2: :x,
|
105
|
+
y1: :y1,
|
106
|
+
y2: :y2
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe Daru::DataFrame, 'category plotting' do
|
114
|
+
context 'scatter' do
|
115
|
+
let(:df) do
|
116
|
+
Daru::DataFrame.new({
|
117
|
+
a: [1, 2, 4, -2, 5, 23, 0],
|
118
|
+
b: [3, 1, 3, -6, 2, 1, 0],
|
119
|
+
c: ['I', 'II', 'I', 'III', 'I', 'III', 'II']
|
120
|
+
})
|
121
|
+
end
|
122
|
+
let(:plot) { instance_double('Nyaplot::Plot') }
|
123
|
+
let(:diagram) { instance_double('Nyaplot::Diagram::Scatter') }
|
124
|
+
|
125
|
+
before do
|
126
|
+
df.to_category :c
|
127
|
+
allow(Nyaplot::Plot).to receive(:new).and_return(plot)
|
128
|
+
allow(plot).to receive(:add_with_df).and_return(diagram)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'plots scatter plot categoried by color with a block' do
|
132
|
+
expect(plot).to receive :add_with_df
|
133
|
+
expect(diagram).to receive(:title).exactly(3).times
|
134
|
+
expect(diagram).to receive(:color).exactly(3).times
|
135
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
136
|
+
expect(plot).to receive :legend
|
137
|
+
expect(plot).to receive :xrange
|
138
|
+
expect(plot).to receive :yrange
|
139
|
+
expect(plot).to receive :show
|
140
|
+
df.plot(type: :scatter, x: :a, y: :b, categorized: {by: :c, method: :color}) do |p, d|
|
141
|
+
p.xrange [-10, 10]
|
142
|
+
p.yrange [-10, 10]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'plots scatter plot categoried by color' do
|
147
|
+
expect(plot).to receive :add_with_df
|
148
|
+
expect(diagram).to receive(:title).exactly(3).times
|
149
|
+
expect(diagram).to receive(:color).exactly(3).times
|
150
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
151
|
+
expect(plot).to receive :legend
|
152
|
+
expect(plot).to receive :show
|
153
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
154
|
+
categorized: {by: :c, method: :color})
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'plots scatter plot categoried by custom colors' do
|
158
|
+
expect(plot).to receive :add_with_df
|
159
|
+
expect(diagram).to receive(:title).exactly(3).times
|
160
|
+
expect(diagram).to receive(:color).with :red
|
161
|
+
expect(diagram).to receive(:color).with :blue
|
162
|
+
expect(diagram).to receive(:color).with :green
|
163
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
164
|
+
expect(plot).to receive :legend
|
165
|
+
expect(plot).to receive :show
|
166
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
167
|
+
categorized: {by: :c, method: :color, color: [:red, :blue, :green]})
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'plots scatter plot categoried by shape' do
|
171
|
+
expect(plot).to receive :add_with_df
|
172
|
+
expect(diagram).to receive(:title).exactly(3).times
|
173
|
+
expect(diagram).to receive(:shape).exactly(3).times
|
174
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
175
|
+
expect(plot).to receive :legend
|
176
|
+
expect(plot).to receive :show
|
177
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
178
|
+
categorized: {by: :c, method: :shape})
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'plots scatter plot categoried by custom shapes' do
|
182
|
+
expect(plot).to receive :add_with_df
|
183
|
+
expect(diagram).to receive(:title).exactly(3).times
|
184
|
+
expect(diagram).to receive(:shape).with 'circle'
|
185
|
+
expect(diagram).to receive(:shape).with 'triangle-up'
|
186
|
+
expect(diagram).to receive(:shape).with 'diamond'
|
187
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
188
|
+
expect(plot).to receive :legend
|
189
|
+
expect(plot).to receive :show
|
190
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
191
|
+
categorized: {by: :c, method: :shape, shape: %w(circle triangle-up diamond)})
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'plots scatter plot categoried by size' do
|
195
|
+
expect(plot).to receive :add_with_df
|
196
|
+
expect(diagram).to receive(:title).exactly(3).times
|
197
|
+
expect(diagram).to receive(:size).exactly(3).times
|
198
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
199
|
+
expect(plot).to receive :legend
|
200
|
+
expect(plot).to receive :show
|
201
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
202
|
+
categorized: {by: :c, method: :size})
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'plots scatter plot categoried by cusom sizes' do
|
206
|
+
expect(plot).to receive :add_with_df
|
207
|
+
expect(diagram).to receive(:title).exactly(3).times
|
208
|
+
expect(diagram).to receive(:size).with 100
|
209
|
+
expect(diagram).to receive(:size).with 200
|
210
|
+
expect(diagram).to receive(:size).with 300
|
211
|
+
expect(diagram).to receive(:tooltip_contents).exactly(3).times
|
212
|
+
expect(plot).to receive :legend
|
213
|
+
expect(plot).to receive :show
|
214
|
+
df.plot(type: :scatter, x: :a, y: :b,
|
215
|
+
categorized: {by: :c, method: :size, size: [100, 200, 300]})
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'line' do
|
220
|
+
let(:df) do
|
221
|
+
Daru::DataFrame.new({
|
222
|
+
a: [1, 2, 4, -2, 5, 23, 0],
|
223
|
+
b: [3, 1, 3, -6, 2, 1, 0],
|
224
|
+
c: ['I', 'II', 'I', 'III', 'I', 'III', 'II']
|
225
|
+
})
|
226
|
+
end
|
227
|
+
let(:plot) { instance_double('Nyaplot::Plot') }
|
228
|
+
let(:diagram) { instance_double('Nyaplot::Diagram::Scatter') }
|
229
|
+
|
230
|
+
before do
|
231
|
+
df.to_category :c
|
232
|
+
allow(Nyaplot::Plot).to receive(:new).and_return(plot)
|
233
|
+
allow(plot).to receive(:add_with_df).and_return(diagram)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'plots line plot categoried by color with a block' do
|
237
|
+
expect(plot).to receive :add_with_df
|
238
|
+
expect(diagram).to receive(:title).exactly(3).times
|
239
|
+
expect(diagram).to receive(:color).exactly(3).times
|
240
|
+
expect(plot).to receive :legend
|
241
|
+
expect(plot).to receive :xrange
|
242
|
+
expect(plot).to receive :yrange
|
243
|
+
expect(plot).to receive :show
|
244
|
+
df.plot(type: :line, x: :a, y: :b, categorized: {by: :c, method: :color}) do |p, d|
|
245
|
+
p.xrange [-10, 10]
|
246
|
+
p.yrange [-10, 10]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'plots line plot categoried by color' do
|
251
|
+
expect(plot).to receive :add_with_df
|
252
|
+
expect(diagram).to receive(:title).exactly(3).times
|
253
|
+
expect(diagram).to receive(:color).exactly(3).times
|
254
|
+
expect(plot).to receive :legend
|
255
|
+
expect(plot).to receive :show
|
256
|
+
df.plot(type: :line, x: :a, y: :b, categorized: {by: :c, method: :color})
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'plots line plot categoried by custom colors' do
|
260
|
+
expect(plot).to receive :add_with_df
|
261
|
+
expect(diagram).to receive(:title).exactly(3).times
|
262
|
+
expect(diagram).to receive(:color).with :red
|
263
|
+
expect(diagram).to receive(:color).with :blue
|
264
|
+
expect(diagram).to receive(:color).with :green
|
265
|
+
expect(plot).to receive :legend
|
266
|
+
expect(plot).to receive :show
|
267
|
+
df.plot(type: :line, x: :a, y: :b,
|
268
|
+
categorized: {by: :c, method: :color, color: [:red, :blue, :green]})
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'plots line plot categoried by stroke width' do
|
272
|
+
expect(plot).to receive :add_with_df
|
273
|
+
expect(diagram).to receive(:title).exactly(3).times
|
274
|
+
expect(diagram).to receive(:stroke_width).exactly(3).times
|
275
|
+
expect(plot).to receive :legend
|
276
|
+
expect(plot).to receive :show
|
277
|
+
df.plot(type: :line, x: :a, y: :b, categorized: {by: :c, method: :stroke_width})
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'plots line plot categoried by custom stroke widths' do
|
281
|
+
expect(plot).to receive :add_with_df
|
282
|
+
expect(diagram).to receive(:title).exactly(3).times
|
283
|
+
expect(diagram).to receive(:stroke_width).with 100
|
284
|
+
expect(diagram).to receive(:stroke_width).with 200
|
285
|
+
expect(diagram).to receive(:stroke_width).with 300
|
286
|
+
expect(plot).to receive :legend
|
287
|
+
expect(plot).to receive :show
|
288
|
+
df.plot(type: :line, x: :a, y: :b,
|
289
|
+
categorized: {by: :c, method: :stroke_width, stroke_width: [100, 200, 300]})
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "invalid type" do
|
294
|
+
let(:df) do
|
295
|
+
Daru::DataFrame.new({
|
296
|
+
a: [1, 2, 4, -2, 5, 23, 0],
|
297
|
+
b: [3, 1, 3, -6, 2, 1, 0],
|
298
|
+
c: ['I', 'II', 'I', 'III', 'I', 'III', 'II']
|
299
|
+
})
|
300
|
+
end
|
301
|
+
it { expect { df.plot(type: :box, categorized: {by: :c, method: :color}) }.to raise_error ArgumentError }
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe Daru::DataFrame, 'plotting dataframe using gruff' do
|
306
|
+
before { Daru.plotting_library = :gruff }
|
307
|
+
let(:df) do
|
308
|
+
Daru::DataFrame.new({
|
309
|
+
a: [1, 3, 5, 2, 5, 0],
|
310
|
+
b: [1, 5, 2, 5, 1, 0],
|
311
|
+
c: [1, 6, 7, 2, 6, 0]
|
312
|
+
}, index: 'a'..'f')
|
313
|
+
end
|
314
|
+
|
315
|
+
context 'bar' do
|
316
|
+
let(:plot) { instance_double 'Gruff::Bar' }
|
317
|
+
before { allow(Gruff::Bar).to receive(:new).and_return(plot) }
|
318
|
+
it 'plots bar graph' do
|
319
|
+
expect(plot).to receive :labels=
|
320
|
+
expect(plot).to receive(:data).exactly(3).times
|
321
|
+
df.plot type: :bar
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'plots bar graph with block' do
|
325
|
+
expect(plot).to receive :labels=
|
326
|
+
expect(plot).to receive(:data).exactly(3).times
|
327
|
+
expect(plot).to receive :title=
|
328
|
+
df.plot(type: :bar) { |p| p.title = 'hello' }
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'plots with specified columns' do
|
332
|
+
expect(plot).to receive :labels=
|
333
|
+
expect(plot).to receive(:data).exactly(2).times
|
334
|
+
df.plot type: :bar, y: [:a, :b]
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
context 'line' do
|
339
|
+
let(:plot) { instance_double 'Gruff::Line' }
|
340
|
+
before { allow(Gruff::Line).to receive(:new).and_return(plot) }
|
341
|
+
it 'plots line graph' do
|
342
|
+
expect(plot).to receive :labels=
|
343
|
+
expect(plot).to receive(:data).exactly(3).times
|
344
|
+
df.plot type: :line
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context 'scatter' do
|
349
|
+
let(:plot) { instance_double 'Gruff::Scatter' }
|
350
|
+
before { allow(Gruff::Scatter).to receive(:new).and_return(plot) }
|
351
|
+
it 'plots scatter graph' do
|
352
|
+
expect(plot).to receive(:data).exactly(3).times
|
353
|
+
df.plot type: :scatter
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'plots with specified columns' do
|
357
|
+
expect(plot).to receive(:data).exactly(1).times
|
358
|
+
df.plot type: :scatter, x: :c, y: :a
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context 'invalid type' do
|
363
|
+
it { expect { df.plot type: :lol }.to raise_error ArgumentError }
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe Daru::DataFrame, 'dataframe category plotting with gruff' do
|
368
|
+
before { Daru.plotting_library = :gruff }
|
369
|
+
let(:df) do
|
370
|
+
Daru::DataFrame.new({
|
371
|
+
a: [1, 3, 5, 2, 5, 0],
|
372
|
+
b: [1, 5, 2, 5, 1, 0],
|
373
|
+
c: [:a, :b, :a, :a, :b, :a]
|
374
|
+
}, index: 'a'..'f')
|
375
|
+
end
|
376
|
+
before { df.to_category :c }
|
377
|
+
|
378
|
+
context 'scatter' do
|
379
|
+
let(:plot) { instance_double 'Gruff::Scatter' }
|
380
|
+
before { allow(Gruff::Scatter).to receive(:new).and_return(plot) }
|
381
|
+
it 'plots scatter plot categorized by category vector' do
|
382
|
+
expect(plot).to receive(:data).exactly(2).times
|
383
|
+
df.plot type: :scatter, x: :a, y: :b, categorized: { by: :c }
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|