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::Core::GroupBy do
4
2
  before do
5
3
  @df = Daru::DataFrame.new({
@@ -140,6 +138,44 @@ describe Daru::Core::GroupBy do
140
138
  end
141
139
  end
142
140
 
141
+ context '#each_group' do
142
+ it 'enumerates groups' do
143
+ ret = []
144
+ @dl_group.each_group { |g| ret << g }
145
+ expect(ret.count).to eq 6
146
+ expect(ret).to all be_a(Daru::DataFrame)
147
+ expect(ret.first).to eq(Daru::DataFrame.new({
148
+ a: ['bar'],
149
+ b: ['one'],
150
+ c: [2],
151
+ d: [22]
152
+ }, index: [1]
153
+ ))
154
+ end
155
+ end
156
+
157
+ context '#first' do
158
+ it 'gets the first row from each group' do
159
+ expect(@dl_group.first).to eq(Daru::DataFrame.new({
160
+ a: %w{bar bar bar foo foo foo },
161
+ b: %w{one three two one three two },
162
+ c: [2 ,1 ,6 ,1 ,8 ,3 ],
163
+ d: [22 ,44 ,66 ,11 ,88 ,33 ]
164
+ }, index: [1,3,5,0,7,2]))
165
+ end
166
+ end
167
+
168
+ context '#last' do
169
+ it 'gets the last row from each group' do
170
+ expect(@dl_group.last).to eq(Daru::DataFrame.new({
171
+ a: %w{bar bar bar foo foo foo },
172
+ b: %w{one three two one three two },
173
+ c: [2 ,1 ,6 ,3 ,8 ,3 ],
174
+ d: [22 ,44 ,66 ,77 ,88 ,55 ]
175
+ }, index: [1,3,5,6,7,4]))
176
+ end
177
+ end
178
+
143
179
  context "#aggregate" do
144
180
  pending
145
181
  end
@@ -191,6 +227,14 @@ describe Daru::Core::GroupBy do
191
227
  end
192
228
  end
193
229
 
230
+ [:median, :std, :max, :min].each do |numeric_method|
231
+ it "works somehow" do
232
+ expect(@sl_group.send(numeric_method).index).to eq @sl_index
233
+ expect(@dl_group.send(numeric_method).index).to eq @dl_multi_index
234
+ expect(@tl_group.send(numeric_method).index).to eq @tl_multi_index
235
+ end
236
+ end
237
+
194
238
  context "#product" do
195
239
  it "calculates product for single layer groups" do
196
240
  # TODO
@@ -351,5 +395,11 @@ describe Daru::Core::GroupBy do
351
395
  string_concat = lambda { |result, row| result += row[:b] }
352
396
  expect(@sl_group.reduce('', &string_concat)).to eq(Daru::Vector.new(['onethreetwo', 'onetwotwoonethree'], index: @sl_index))
353
397
  end
398
+
399
+ it "works with multi-indexes" do
400
+ string_concat = lambda { |result, row| result += row[:b] }
401
+ expect(@dl_group.reduce('', &string_concat)).to eq \
402
+ Daru::Vector.new(['one', 'three', 'two', 'oneone', 'three', 'twotwo'], index: @dl_multi_index)
403
+ end
354
404
  end
355
405
  end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Daru::DataFrame do
4
2
  context "#join" do
5
3
  before do
@@ -39,6 +37,16 @@ describe Daru::DataFrame do
39
37
  expect(@left.join(@right_many, how: :inner, on: [:id])).to eq(answer)
40
38
  end
41
39
 
40
+ it "performs an inner join of two dataframes that has many to many mapping" do
41
+ @left[:id].recode! { |v| v == 2 ? 1 : v }
42
+ answer = Daru::DataFrame.new({
43
+ :name_1 => ['Pirate', 'Pirate', 'Pirate', 'Pirate', 'Monkey', 'Monkey', 'Monkey', 'Monkey'],
44
+ :id => [1,1,1,1,1,1,1,1],
45
+ :name_2 => ['Rutabaga', 'Pirate', 'Darth Vader', 'Ninja', 'Rutabaga', 'Pirate', 'Darth Vader', 'Ninja']
46
+ }, order: [:name_1, :id, :name_2])
47
+ expect(@left.join(@right_many, how: :inner, on: [:id])).to eq(answer)
48
+ end
49
+
42
50
  it "performs a full outer join" do
43
51
  answer = Daru::DataFrame.new({
44
52
  :id_1 => [nil,2,3,1,nil,4],
@@ -48,6 +56,38 @@ describe Daru::DataFrame do
48
56
  expect(@left.join(@right, how: :outer, on: [:name])).to eq(answer)
49
57
  end
50
58
 
59
+ it "performs a full outer join when the right join keys have nils" do
60
+ @right[:name].recode! { |v| v == 'Rutabaga' ? nil : v }
61
+ answer = Daru::DataFrame.new({
62
+ :id_1 => [nil, nil,2,3,1,4],
63
+ :name => [nil, "Darth Vader", "Monkey", "Ninja", "Pirate", "Spaghetti"],
64
+ :id_2 => [1,3,nil,4,2,nil]
65
+ }, order: [:id_1, :name, :id_2])
66
+ expect(@left.join(@right, how: :outer, on: [:name])).to eq(answer)
67
+ end
68
+
69
+ it "performs a full outer join when the left join keys have nils" do
70
+ @left[:name].recode! { |v| v == 'Monkey' ? nil : v }
71
+ answer = Daru::DataFrame.new({
72
+ :id_1 => [2,nil,3,1,nil,4],
73
+ :name => [nil, "Darth Vader", "Ninja", "Pirate", "Rutabaga", "Spaghetti"],
74
+ :id_2 => [nil,3,4,2,1,nil]
75
+ }, order: [:id_1, :name, :id_2])
76
+ expect(@left.join(@right, how: :outer, on: [:name])).to eq(answer)
77
+ end
78
+
79
+ it "performs a full outer join when both left and right join keys have nils" do
80
+ @left[:name].recode! { |v| v == 'Monkey' ? nil : v }
81
+ @right[:name].recode! { |v| v == 'Rutabaga' ? nil : v }
82
+
83
+ answer = Daru::DataFrame.new({
84
+ :id_1 => [nil,2,nil,3,1,4],
85
+ :name => [nil, nil, "Darth Vader", "Ninja", "Pirate", "Spaghetti"],
86
+ :id_2 => [1,nil,3,4,2,nil]
87
+ }, order: [:id_1, :name, :id_2])
88
+ expect(@left.join(@right, how: :outer, on: [:name])).to eq(answer)
89
+ end
90
+
51
91
  it "performs a left outer join", focus: true do
52
92
  answer = Daru::DataFrame.new({
53
93
  :id_1 => [2,3,1,4],
@@ -77,5 +117,26 @@ describe Daru::DataFrame do
77
117
  expect(@left.join(@right, how: :right, on: [:name])).to eq(answer)
78
118
  end
79
119
 
120
+ it "raises if :on field are absent in one of dataframes" do
121
+ @right.vectors = [:id, :other_name]
122
+ expect { @left.join(@right, how: :right, on: [:name]) }.to \
123
+ raise_error(ArgumentError, /Both dataframes expected .* :name/)
124
+
125
+ expect { @left.join(@right, how: :right, on: [:other_name]) }.to \
126
+ raise_error(ArgumentError, /Both dataframes expected .* :other_name/)
127
+ end
128
+
129
+ it "is able to join by several :on fields" do
130
+ @left.gender = ['m', 'f', 'm', nil]
131
+ @right.gender = ['m', 'm', nil, 'f']
132
+
133
+ answer = Daru::DataFrame.new({
134
+ id_1: [1],
135
+ name: ['Pirate'],
136
+ gender: ['m'],
137
+ id_2: [2]
138
+ }, order: [:id_1, :name, :gender, :id_2])
139
+ expect(@left.join(@right, how: :inner, on: [:name, :gender])).to eq(answer)
140
+ end
80
141
  end
81
142
  end
@@ -1,8 +1,6 @@
1
- require 'spec_helper'
2
-
3
1
  describe Daru::Core::Query::BoolArray do
4
2
  before do
5
- @klass = Daru::Core::Query::BoolArray
3
+ @klass = Daru::Core::Query::BoolArray
6
4
  @left = @klass.new([true, true, true, false, false, true])
7
5
  @right = @klass.new([false, false, false, false, true, false])
8
6
  end
@@ -28,94 +26,212 @@ describe Daru::Core::Query::BoolArray do
28
26
  )
29
27
  end
30
28
  end
29
+
30
+ context '#inspect' do
31
+ it 'is reasonable' do
32
+ expect(@left.inspect).to eq "#<Daru::Core::Query::BoolArray:#{@left.object_id} bool_arry=[true, true, true, false, false, true]>"
33
+ end
34
+ end
31
35
  end
32
36
 
33
37
  describe "Arel-like syntax" do
34
38
  describe "comparison operators" do
35
39
  describe Daru::Vector do
36
- before do
37
- @vector = Daru::Vector.new([23,51,1214,352,32,11])
38
- @comparator = Daru::Vector.new([45,22,1214,55,32,9])
39
- @klass = Daru::Core::Query::BoolArray
40
- end
41
-
42
- context "#eq" do
43
- it "accepts scalar value" do
44
- expect(@vector.eq(352)).to eq(
45
- @klass.new([false,false,false,true,false,false]))
40
+ describe "non-categorical type" do
41
+ before do
42
+ @vector = Daru::Vector.new([23,51,1214,352,32,11])
43
+ @comparator = Daru::Vector.new([45,22,1214,55,32,9])
44
+ @klass = Daru::Core::Query::BoolArray
46
45
  end
47
-
48
- it "accepts vector and compares corrensponding elements" do
49
- expect(@vector.eq(@comparator)).to eq(
50
- @klass.new([false,false,true,false,true,false]))
46
+
47
+ context "#eq" do
48
+ it "accepts scalar value" do
49
+ expect(@vector.eq(352)).to eq(
50
+ @klass.new([false,false,false,true,false,false]))
51
+ end
52
+
53
+ it "accepts vector and compares corrensponding elements" do
54
+ expect(@vector.eq(@comparator)).to eq(
55
+ @klass.new([false,false,true,false,true,false]))
56
+ end
51
57
  end
52
- end
53
-
54
- context "#not_eq" do
55
- it "accepts scalar value" do
56
- expect(@vector.not_eq(51)).to eq(
57
- @klass.new([true, false, true, true, true, true]))
58
+
59
+ context "#not_eq" do
60
+ it "accepts scalar value" do
61
+ expect(@vector.not_eq(51)).to eq(
62
+ @klass.new([true, false, true, true, true, true]))
63
+ end
64
+
65
+ it "accepts vector and compares corrensponding elements" do
66
+ expect(@vector.not_eq(@comparator)).to eq(
67
+ @klass.new([true, true, false, true, false, true]))
68
+ end
58
69
  end
59
-
60
- it "accepts vector and compares corrensponding elements" do
61
- expect(@vector.not_eq(@comparator)).to eq(
62
- @klass.new([true, true, false, true, false, true]))
70
+
71
+ context "#lt" do
72
+ it "accepts scalar value" do
73
+ expect(@vector.lt(51)).to eq(
74
+ @klass.new([true, false, false, false, true, true]))
75
+ end
76
+
77
+ it "accepts vector and compares corrensponding elements" do
78
+ expect(@vector.lt(@comparator)).to eq(
79
+ @klass.new([true,false,false,false,false,false]))
80
+ end
63
81
  end
64
- end
65
-
66
- context "#lt" do
67
- it "accepts scalar value" do
68
- expect(@vector.lt(51)).to eq(
69
- @klass.new([true, false, false, false, true, true]))
82
+
83
+ context "#lteq" do
84
+ it "accepts scalar value" do
85
+ expect(@vector.lteq(51)).to eq(
86
+ @klass.new([true, true, false, false, true, true]))
87
+ end
88
+
89
+ it "accepts vector and compares corrensponding elements" do
90
+ expect(@vector.lteq(@comparator)).to eq(
91
+ @klass.new([true,false,true,false,true,false]))
92
+ end
70
93
  end
71
-
72
- it "accepts vector and compares corrensponding elements" do
73
- expect(@vector.lt(@comparator)).to eq(
74
- @klass.new([true,false,false,false,false,false]))
94
+
95
+ context "#mt" do
96
+ it "accepts scalar value" do
97
+ expect(@vector.mt(51)).to eq(
98
+ @klass.new([false, false, true, true, false, false]))
99
+ end
100
+
101
+ it "accepts vector and compares corrensponding elements" do
102
+ expect(@vector.mt(@comparator)).to eq(
103
+ @klass.new([false,true,false,true,false,true]))
104
+ end
75
105
  end
76
- end
77
-
78
- context "#lteq" do
79
- it "accepts scalar value" do
80
- expect(@vector.lteq(51)).to eq(
81
- @klass.new([true, true, false, false, true, true]))
106
+
107
+ context "#mteq" do
108
+ it "accepts scalar value" do
109
+ expect(@vector.mteq(51)).to eq(
110
+ @klass.new([false, true, true, true, false, false]))
111
+ end
112
+
113
+ it "accepts vector and compares corrensponding elements" do
114
+ expect(@vector.mteq(@comparator)).to eq(
115
+ @klass.new([false,true,true,true,true,true]))
116
+ end
82
117
  end
83
-
84
- it "accepts vector and compares corrensponding elements" do
85
- expect(@vector.lteq(@comparator)).to eq(
86
- @klass.new([true,false,true,false,true,false]))
118
+
119
+ context "#in" do
120
+ it "checks if any of elements in the arg are present in the vector" do
121
+ expect(@vector.in([23,55,1,33,32])).to eq(
122
+ @klass.new([true, false, false, false, true, false]))
123
+ end
87
124
  end
88
125
  end
126
+
127
+ describe "categorical type" do
128
+ let(:dv) { Daru::Vector.new ['e', 'd', 'd', 'x', 'x'],
129
+ categories: ['a', 'x', 'c', 'd', 'e'], type: :category }
130
+ let(:comp) { Daru::Vector.new ['a', 'd', 'x', 'e', 'x'],
131
+ categories: ['a', 'x', 'c', 'd', 'e'], type: :category }
132
+ let(:query_bool_class) { Daru::Core::Query::BoolArray }
89
133
 
90
- context "#mt" do
91
- it "accepts scalar value" do
92
- expect(@vector.mt(51)).to eq(
93
- @klass.new([false, false, true, true, false, false]))
94
- end
134
+ context "#eq" do
135
+ context "scalar" do
136
+ subject { dv.eq 'd' }
137
+
138
+ it { is_expected.to be_a query_bool_class }
139
+ its(:to_a) { is_expected.to eq [false, true, true, false, false] }
140
+ end
95
141
 
96
- it "accepts vector and compares corrensponding elements" do
97
- expect(@vector.mt(@comparator)).to eq(
98
- @klass.new([false,true,false,true,false,true]))
142
+ context "vector" do
143
+ subject { dv.eq comp }
144
+
145
+ it { is_expected.to be_a query_bool_class }
146
+ its(:to_a) { is_expected.to eq [false, true, false, false, true] }
147
+ end
99
148
  end
100
- end
101
-
102
- context "#mteq" do
103
- it "accepts scalar value" do
104
- expect(@vector.mteq(51)).to eq(
105
- @klass.new([false, true, true, true, false, false]))
149
+
150
+ context "#not_eq" do
151
+ context "scalar" do
152
+ subject { dv.not_eq 'd' }
153
+
154
+ it { is_expected.to be_a query_bool_class }
155
+ its(:to_a) { is_expected.to eq [true, false, false, true, true] }
156
+ end
157
+
158
+ context "vector" do
159
+ subject { dv.not_eq comp }
160
+
161
+ it { is_expected.to be_a query_bool_class }
162
+ its(:to_a) { is_expected.to eq [true, false, true, true, false] }
163
+ end
106
164
  end
107
-
108
- it "accepts vector and compares corrensponding elements" do
109
- expect(@vector.mteq(@comparator)).to eq(
110
- @klass.new([false,true,true,true,true,true]))
165
+
166
+ context "#lt" do
167
+ context "scalar" do
168
+ subject { dv.lt 'd' }
169
+
170
+ it { is_expected.to be_a query_bool_class }
171
+ its(:to_a) { is_expected.to eq [false, false, false, true, true] }
172
+ end
173
+
174
+ context "vector" do
175
+ subject { dv.lt comp }
176
+
177
+ it { is_expected.to be_a query_bool_class }
178
+ its(:to_a) { is_expected.to eq [false, false, false, true, false] }
179
+ end
111
180
  end
112
- end
113
-
114
- context "#in" do
115
- it "checks if any of elements in the arg are present in the vector" do
116
- expect(@vector.in([23,55,1,33,32])).to eq(
117
- @klass.new([true, false, false, false, true, false]))
181
+
182
+ context "#lteq" do
183
+ context "scalar" do
184
+ subject { dv.lteq 'd' }
185
+
186
+ it { is_expected.to be_a query_bool_class }
187
+ its(:to_a) { is_expected.to eq [false, true, true, true, true] }
188
+ end
189
+
190
+ context "vector" do
191
+ subject { dv.lteq comp }
192
+
193
+ it { is_expected.to be_a query_bool_class }
194
+ its(:to_a) { is_expected.to eq [false, true, false, true, true] }
195
+ end
196
+ end
197
+
198
+ context "#mt" do
199
+ context "scalar" do
200
+ subject { dv.mt 'd' }
201
+
202
+ it { is_expected.to be_a query_bool_class }
203
+ its(:to_a) { is_expected.to eq [true, false, false, false, false] }
204
+ end
205
+
206
+ context "vector" do
207
+ subject { dv.mt comp }
208
+
209
+ it { is_expected.to be_a query_bool_class }
210
+ its(:to_a) { is_expected.to eq [true, false, true, false, false] }
211
+ end
212
+ end
213
+
214
+ context "#mteq" do
215
+ context "scalar" do
216
+ subject { dv.mteq 'd' }
217
+
218
+ it { is_expected.to be_a query_bool_class }
219
+ its(:to_a) { is_expected.to eq [true, true, true, false, false] }
220
+ end
221
+
222
+ context "vector" do
223
+ subject { dv.mteq comp }
224
+
225
+ it { is_expected.to be_a query_bool_class }
226
+ its(:to_a) { is_expected.to eq [true, true, true, false, true] }
227
+ end
118
228
  end
229
+
230
+ # context "#in" do
231
+ # subject { dv.in ['b', 'd'] }
232
+ # it { is_expected.to be_a query_bool_class }
233
+ # its(:to_a) { is_expected.to eq [false, true, true, true, true] }
234
+ # end
119
235
  end
120
236
  end
121
237
  end
@@ -153,18 +269,58 @@ describe "Arel-like syntax" do
153
269
  end
154
270
 
155
271
  context Daru::Vector do
156
- before do
157
- @vector = Daru::Vector.new([2,5,1,22,51,4])
272
+ context "non-categorical type" do
273
+ before do
274
+ @vector = Daru::Vector.new([2,5,1,22,51,4])
275
+ end
276
+
277
+ it "accepts a simple single statement" do
278
+ expect(@vector.where(@vector.lt(10))).to eq(
279
+ Daru::Vector.new([2,5,1,4], index: Daru::Index.new([0,1,2,5])))
280
+ end
281
+
282
+ it "accepts somewhat complex operator chaining" do
283
+ expect(@vector.where((@vector.lt(6) | @vector.eq(51)))).to eq(
284
+ Daru::Vector.new([2,5,1,51,4], index: Daru::Index.new([0,1,2,4,5])))
285
+ end
158
286
  end
159
-
160
- it "accepts a simple single statement" do
161
- expect(@vector.where(@vector.lt(10))).to eq(
162
- Daru::Vector.new([2,5,1,4], index: Daru::Index.new([0,1,2,5])))
287
+
288
+ context "categorical type" do
289
+ let(:dv) { Daru::Vector.new ['a', 'c', 'x', 'x', 'c'],
290
+ categories: ['a', 'x', 'c'], type: :category }
291
+
292
+ context "simple single statement" do
293
+ subject { dv.where(dv.lt('x')) }
294
+
295
+ it { is_expected.to be_a Daru::Vector }
296
+ its(:type) { is_expected.to eq :category }
297
+ its(:to_a) { is_expected.to eq ['a'] }
298
+ its(:'index.to_a') { is_expected.to eq [0] }
299
+ end
300
+
301
+ context "complex operator chaining" do
302
+ subject { dv.where((dv.lt('x') | dv.eq('c'))) }
303
+
304
+ it { is_expected.to be_a Daru::Vector }
305
+ its(:type) { is_expected.to eq :category }
306
+ its(:to_a) { is_expected.to eq ['a', 'c', 'c'] }
307
+ its(:'index.to_a') { is_expected.to eq [0, 1, 4] }
308
+ end
309
+
310
+ context "preserve categories" do
311
+ subject { dv.where((dv.lt('x') | dv.eq('c'))) }
312
+
313
+ it { is_expected.to be_a Daru::Vector }
314
+ its(:type) { is_expected.to eq :category }
315
+ its(:to_a) { is_expected.to eq ['a', 'c', 'c'] }
316
+ its(:'index.to_a') { is_expected.to eq [0, 1, 4] }
317
+ its(:categories) { is_expected.to eq ['a', 'x', 'c'] }
318
+ end
163
319
  end
164
320
 
165
- it "accepts somewhat complex operator chaining" do
166
- expect(@vector.where((@vector.lt(6) | @vector.eq(51)))).to eq(
167
- Daru::Vector.new([2,5,1,51,4], index: Daru::Index.new([0,1,2,4,5])))
321
+ it "preserves name" do
322
+ named_vector = Daru::Vector.new([1,2,3], name: 'named')
323
+ expect(named_vector.where(named_vector.lteq(2)).name).to eq('named')
168
324
  end
169
325
  end
170
326
  end