daru 0.1.3.1 → 0.1.4
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/.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
|