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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -1
  4. data/.rspec_formatter.rb +33 -0
  5. data/.rubocop.yml +26 -2
  6. data/History.md +38 -0
  7. data/README.md +22 -13
  8. data/Rakefile +50 -2
  9. data/benchmarks/csv_reading.rb +22 -0
  10. data/daru.gemspec +9 -2
  11. data/lib/daru.rb +36 -4
  12. data/lib/daru/accessors/array_wrapper.rb +6 -1
  13. data/lib/daru/accessors/dataframe_by_row.rb +10 -2
  14. data/lib/daru/accessors/gsl_wrapper.rb +1 -3
  15. data/lib/daru/accessors/nmatrix_wrapper.rb +9 -0
  16. data/lib/daru/category.rb +935 -0
  17. data/lib/daru/core/group_by.rb +29 -38
  18. data/lib/daru/core/merge.rb +186 -145
  19. data/lib/daru/core/query.rb +22 -11
  20. data/lib/daru/dataframe.rb +976 -885
  21. data/lib/daru/date_time/index.rb +166 -166
  22. data/lib/daru/date_time/offsets.rb +66 -77
  23. data/lib/daru/formatters/table.rb +54 -0
  24. data/lib/daru/helpers/array.rb +40 -0
  25. data/lib/daru/index.rb +476 -73
  26. data/lib/daru/io/io.rb +66 -45
  27. data/lib/daru/io/sql_data_source.rb +33 -62
  28. data/lib/daru/iruby/helpers.rb +38 -0
  29. data/lib/daru/iruby/templates/dataframe.html.erb +52 -0
  30. data/lib/daru/iruby/templates/dataframe_mi.html.erb +58 -0
  31. data/lib/daru/iruby/templates/multi_index.html.erb +12 -0
  32. data/lib/daru/iruby/templates/vector.html.erb +27 -0
  33. data/lib/daru/iruby/templates/vector_mi.html.erb +36 -0
  34. data/lib/daru/maths/arithmetic/dataframe.rb +16 -18
  35. data/lib/daru/maths/arithmetic/vector.rb +4 -6
  36. data/lib/daru/maths/statistics/dataframe.rb +8 -15
  37. data/lib/daru/maths/statistics/vector.rb +120 -98
  38. data/lib/daru/monkeys.rb +12 -40
  39. data/lib/daru/plotting/gruff.rb +3 -0
  40. data/lib/daru/plotting/gruff/category.rb +49 -0
  41. data/lib/daru/plotting/gruff/dataframe.rb +91 -0
  42. data/lib/daru/plotting/gruff/vector.rb +57 -0
  43. data/lib/daru/plotting/nyaplot.rb +3 -0
  44. data/lib/daru/plotting/nyaplot/category.rb +34 -0
  45. data/lib/daru/plotting/nyaplot/dataframe.rb +187 -0
  46. data/lib/daru/plotting/nyaplot/vector.rb +46 -0
  47. data/lib/daru/vector.rb +694 -421
  48. data/lib/daru/version.rb +1 -1
  49. data/profile/_base.rb +23 -0
  50. data/profile/df_to_a.rb +10 -0
  51. data/profile/filter.rb +13 -0
  52. data/profile/joining.rb +13 -0
  53. data/profile/sorting.rb +12 -0
  54. data/profile/vector_each_with_index.rb +9 -0
  55. data/spec/accessors/wrappers_spec.rb +2 -4
  56. data/spec/categorical_spec.rb +1734 -0
  57. data/spec/core/group_by_spec.rb +52 -2
  58. data/spec/core/merge_spec.rb +63 -2
  59. data/spec/core/query_spec.rb +236 -80
  60. data/spec/dataframe_spec.rb +1373 -79
  61. data/spec/date_time/data_spec.rb +3 -5
  62. data/spec/date_time/index_spec.rb +154 -17
  63. data/spec/date_time/offsets_spec.rb +3 -4
  64. data/spec/fixtures/empties.dat +2 -0
  65. data/spec/fixtures/strings.dat +2 -0
  66. data/spec/formatters/table_formatter_spec.rb +99 -0
  67. data/spec/helpers_spec.rb +8 -0
  68. data/spec/index/categorical_index_spec.rb +168 -0
  69. data/spec/index/index_spec.rb +283 -0
  70. data/spec/index/multi_index_spec.rb +570 -0
  71. data/spec/io/io_spec.rb +31 -4
  72. data/spec/io/sql_data_source_spec.rb +0 -1
  73. data/spec/iruby/dataframe_spec.rb +172 -0
  74. data/spec/iruby/helpers_spec.rb +49 -0
  75. data/spec/iruby/multi_index_spec.rb +37 -0
  76. data/spec/iruby/vector_spec.rb +107 -0
  77. data/spec/math/arithmetic/dataframe_spec.rb +71 -13
  78. data/spec/math/arithmetic/vector_spec.rb +8 -10
  79. data/spec/math/statistics/dataframe_spec.rb +3 -5
  80. data/spec/math/statistics/vector_spec.rb +45 -55
  81. data/spec/monkeys_spec.rb +32 -9
  82. data/spec/plotting/dataframe_spec.rb +386 -0
  83. data/spec/plotting/vector_spec.rb +230 -0
  84. data/spec/shared/vector_display_spec.rb +215 -0
  85. data/spec/spec_helper.rb +23 -0
  86. data/spec/vector_spec.rb +905 -138
  87. metadata +143 -11
  88. data/.rubocop_todo.yml +0 -44
  89. data/lib/daru/plotting/dataframe.rb +0 -104
  90. data/lib/daru/plotting/vector.rb +0 -38
  91. data/spec/daru_spec.rb +0 -58
  92. 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.only_valid.to_a.sort)
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.only_valid.to_a.sort)
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
@@ -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