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.
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