daru_lite 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +35 -33
  3. data/lib/daru_lite/data_frame/aggregatable.rb +165 -0
  4. data/lib/daru_lite/data_frame/calculatable.rb +140 -0
  5. data/lib/daru_lite/data_frame/convertible.rb +107 -0
  6. data/lib/daru_lite/data_frame/duplicatable.rb +64 -0
  7. data/lib/daru_lite/data_frame/fetchable.rb +301 -0
  8. data/lib/daru_lite/data_frame/filterable.rb +144 -0
  9. data/lib/daru_lite/data_frame/i_o_able.rb +179 -0
  10. data/lib/daru_lite/data_frame/indexable.rb +168 -0
  11. data/lib/daru_lite/data_frame/iterable.rb +339 -0
  12. data/lib/daru_lite/data_frame/joinable.rb +152 -0
  13. data/lib/daru_lite/data_frame/missable.rb +75 -0
  14. data/lib/daru_lite/data_frame/pivotable.rb +108 -0
  15. data/lib/daru_lite/data_frame/queryable.rb +67 -0
  16. data/lib/daru_lite/data_frame/setable.rb +109 -0
  17. data/lib/daru_lite/data_frame/sortable.rb +241 -0
  18. data/lib/daru_lite/dataframe.rb +138 -2353
  19. data/lib/daru_lite/index/index.rb +14 -1
  20. data/lib/daru_lite/index/multi_index.rb +9 -0
  21. data/lib/daru_lite/maths/statistics/vector.rb +1 -1
  22. data/lib/daru_lite/vector/aggregatable.rb +9 -0
  23. data/lib/daru_lite/vector/calculatable.rb +78 -0
  24. data/lib/daru_lite/vector/convertible.rb +77 -0
  25. data/lib/daru_lite/vector/duplicatable.rb +17 -0
  26. data/lib/daru_lite/vector/fetchable.rb +175 -0
  27. data/lib/daru_lite/vector/filterable.rb +128 -0
  28. data/lib/daru_lite/vector/indexable.rb +77 -0
  29. data/lib/daru_lite/vector/iterable.rb +95 -0
  30. data/lib/daru_lite/vector/joinable.rb +17 -0
  31. data/lib/daru_lite/vector/missable.rb +124 -0
  32. data/lib/daru_lite/vector/queryable.rb +45 -0
  33. data/lib/daru_lite/vector/setable.rb +47 -0
  34. data/lib/daru_lite/vector/sortable.rb +113 -0
  35. data/lib/daru_lite/vector.rb +36 -932
  36. data/lib/daru_lite/version.rb +1 -1
  37. data/spec/data_frame/aggregatable_example.rb +65 -0
  38. data/spec/data_frame/buildable_example.rb +109 -0
  39. data/spec/data_frame/calculatable_example.rb +135 -0
  40. data/spec/data_frame/convertible_example.rb +180 -0
  41. data/spec/data_frame/duplicatable_example.rb +111 -0
  42. data/spec/data_frame/fetchable_example.rb +476 -0
  43. data/spec/data_frame/filterable_example.rb +409 -0
  44. data/spec/data_frame/indexable_example.rb +221 -0
  45. data/spec/data_frame/iterable_example.rb +465 -0
  46. data/spec/data_frame/joinable_example.rb +106 -0
  47. data/spec/data_frame/missable_example.rb +47 -0
  48. data/spec/data_frame/pivotable_example.rb +297 -0
  49. data/spec/data_frame/queryable_example.rb +92 -0
  50. data/spec/data_frame/setable_example.rb +482 -0
  51. data/spec/data_frame/sortable_example.rb +350 -0
  52. data/spec/dataframe_spec.rb +181 -3289
  53. data/spec/index/categorical_index_spec.rb +27 -8
  54. data/spec/index/index_spec.rb +21 -0
  55. data/spec/index/multi_index_spec.rb +85 -76
  56. data/spec/vector/aggregatable_example.rb +27 -0
  57. data/spec/vector/calculatable_example.rb +82 -0
  58. data/spec/vector/convertible_example.rb +126 -0
  59. data/spec/vector/duplicatable_example.rb +48 -0
  60. data/spec/vector/fetchable_example.rb +463 -0
  61. data/spec/vector/filterable_example.rb +165 -0
  62. data/spec/vector/indexable_example.rb +201 -0
  63. data/spec/vector/iterable_example.rb +111 -0
  64. data/spec/vector/joinable_example.rb +25 -0
  65. data/spec/vector/missable_example.rb +88 -0
  66. data/spec/vector/queryable_example.rb +91 -0
  67. data/spec/vector/setable_example.rb +300 -0
  68. data/spec/vector/sortable_example.rb +242 -0
  69. data/spec/vector_spec.rb +111 -1805
  70. metadata +86 -2
@@ -0,0 +1,201 @@
1
+ shared_examples_for 'an indexable Vector' do |dtype|
2
+ describe "#index_of" do
3
+ context DaruLite::Index do
4
+ let(:vector) do
5
+ DaruLite::Vector.new(
6
+ [1,2,3,4,5],
7
+ name: :a,
8
+ index: [:one, :two, :three, :four, :five],
9
+ dtype:
10
+ )
11
+ end
12
+ it "returns index of specified value" do
13
+ expect(vector.index_of(1)).to eq(:one)
14
+ end
15
+ end
16
+
17
+ context DaruLite::MultiIndex do
18
+ let(:vector) { DaruLite::Vector.new([1,2,3,4], index: multi_index, dtype:) }
19
+ let(:multi_index) do
20
+ DaruLite::MultiIndex.from_tuples([
21
+ [:a,:two,:bar],
22
+ [:a,:two,:baz],
23
+ [:b,:one,:bar],
24
+ [:b,:two,:bar]
25
+ ])
26
+ end
27
+
28
+ it "returns tuple of specified value" do
29
+ expect(vector.index_of(3)).to eq([:b,:one,:bar])
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#index=" do
35
+ subject { vector.index = new_index }
36
+
37
+ let(:vector) { DaruLite::Vector.new([1,2,3,4,5]) }
38
+
39
+ context "new index is an Index" do
40
+ before { subject }
41
+
42
+ let(:new_index) { DaruLite::DateTimeIndex.date_range(start: '2012', periods: 5) }
43
+
44
+ it 'returns the new index' do
45
+ expect(subject).to eq(new_index)
46
+ end
47
+
48
+ it "simply reassigns index" do
49
+ expect(vector.index.class).to eq(DaruLite::DateTimeIndex)
50
+ expect(vector['2012-1-1']).to eq(1)
51
+ end
52
+ end
53
+
54
+ context "new index is an array" do
55
+ before { subject }
56
+
57
+ let(:new_index) { [5, 4, 3, 2, 1] }
58
+
59
+ it "accepts an array as index" do
60
+ expect(vector.index.class).to eq(DaruLite::Index)
61
+ expect(vector[5]).to eq(1)
62
+ end
63
+ end
64
+
65
+ context "new index is a range" do
66
+ before { subject }
67
+
68
+ let(:new_index) { 'a'..'e' }
69
+
70
+ it "accepts an range as index" do
71
+ expect(vector.index.class).to eq(DaruLite::Index)
72
+ expect(vector['a']).to eq(1)
73
+ end
74
+ end
75
+
76
+ context "new index has a different size" do
77
+ let(:new_index) { DaruLite::Index.new([4,2,6]) }
78
+
79
+ it "raises error for index size != vector size" do
80
+ expect { subject }.to raise_error(
81
+ ArgumentError, 'Size of supplied index 3 does not match size of Vector'
82
+ )
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#reindex!" do
88
+ subject { vector.reindex!(index) }
89
+
90
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, 4, 5]) }
91
+ let(:index) { DaruLite::Index.new([3, 4, 1, 0, 6]) }
92
+
93
+ before { subject }
94
+
95
+ it "intelligently reindexes" do
96
+ expect(vector).to eq(DaruLite::Vector.new([4, 5, 2, 1, nil], index:))
97
+ end
98
+ end
99
+
100
+ describe "#reindex" do
101
+ subject { vector.reindex(index) }
102
+
103
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, 4, 5]) }
104
+ let(:index) { DaruLite::Index.new([3, 4, 1, 0, 6]) }
105
+
106
+ it "intelligently reindexes" do
107
+ expect(subject).to eq(DaruLite::Vector.new([4, 5, 2, 1, nil], index:))
108
+ end
109
+ end
110
+
111
+ describe '#indexes' do
112
+ context DaruLite::Index do
113
+ subject { vector.indexes 1, 2, nil, Float::NAN }
114
+
115
+ let(:vector) do
116
+ DaruLite::Vector.new(
117
+ [1, 2, 1, 2, 3, nil, nil, Float::NAN],
118
+ index: 11..18
119
+ )
120
+ end
121
+
122
+ it { is_expected.to be_a Array }
123
+ it { is_expected.to eq [11, 12, 13, 14, 16, 17, 18] }
124
+ end
125
+
126
+ context DaruLite::MultiIndex do
127
+ subject { vector.indexes 1, 2, Float::NAN }
128
+
129
+ let(:mi) do
130
+ DaruLite::MultiIndex.from_tuples([
131
+ ['M', 2000],
132
+ ['M', 2001],
133
+ ['M', 2002],
134
+ ['M', 2003],
135
+ ['F', 2000],
136
+ ['F', 2001],
137
+ ['F', 2002],
138
+ ['F', 2003]
139
+ ])
140
+ end
141
+ let(:vector) { DaruLite::Vector.new([1, 2, 1, 2, 3, nil, nil, Float::NAN], index: mi) }
142
+
143
+ it { is_expected.to be_a Array }
144
+ it { is_expected.to eq(
145
+ [
146
+ ['M', 2000],
147
+ ['M', 2001],
148
+ ['M', 2002],
149
+ ['M', 2003],
150
+ ['F', 2003]
151
+ ]) }
152
+ end
153
+ end
154
+
155
+ describe "#reset_index!" do
156
+ subject { vector.reset_index! }
157
+
158
+ context 'after rejecting initial values' do
159
+ let(:vector) do
160
+ v = DaruLite::Vector.new([1, 2, 3, 4, 5, nil, nil, 4, nil])
161
+ v.reject_values(*DaruLite::MISSING_VALUES)
162
+ end
163
+
164
+ it "resets any index to a numerical serialized index" do
165
+ expect(subject).to eq(DaruLite::Vector.new([1, 2, 3, 4, 5, 4]))
166
+ expect(subject.index).to eq(DaruLite::Index.new([0, 1, 2, 3, 4, 5]))
167
+ end
168
+ end
169
+
170
+ context 'when vector is indexed' do
171
+ let(:vector) do
172
+ DaruLite::Vector.new([1, 2, 3, 4, 5], index: [:a, :b, :c, :d, :e])
173
+ end
174
+
175
+ it "resets any index to a numerical serialized index" do
176
+ expect(subject.index).to eq(DaruLite::Index.new([0, 1, 2, 3, 4]))
177
+ end
178
+ end
179
+ end
180
+
181
+ describe "#detach_index" do
182
+ subject { vector.detach_index }
183
+
184
+ let(:vector) do
185
+ DaruLite::Vector.new(
186
+ [1, 2, 3, 4, 5, 6],
187
+ index: ['a', 'b', 'c', 'd', 'e', 'f'],
188
+ name: :values
189
+ )
190
+ end
191
+
192
+ it "creates a DataFrame with first Vector as index and second as values of the Vector" do
193
+ expect(vector.detach_index).to eq(
194
+ DaruLite::DataFrame.new(
195
+ index: ['a', 'b', 'c', 'd', 'e', 'f'],
196
+ values: [1, 2, 3, 4, 5, 6]
197
+ )
198
+ )
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,111 @@
1
+ shared_examples_for 'an iterable Vector' do |dtype|
2
+ let(:vector) do
3
+ DaruLite::Vector.new(
4
+ [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
5
+ dtype:,
6
+ name: :common_all_dtypes
7
+ )
8
+ end
9
+
10
+ describe "#collect" do
11
+ subject { vector.collect { |v| v } }
12
+
13
+ it "returns an Array" do
14
+ expect(subject).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99])
15
+ end
16
+ end
17
+
18
+ describe "#map" do
19
+ subject { vector.map { |v| v } }
20
+
21
+ it "maps" do
22
+ expect(subject).to eq([5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99])
23
+ end
24
+ end
25
+
26
+ describe "#map!" do
27
+ subject { vector.map! { |v| v + 1 } }
28
+
29
+ it "destructively maps" do
30
+ subject
31
+ expect(vector).to eq(
32
+ DaruLite::Vector.new(
33
+ [6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 2, 3, 4, 5, 12, -98, -98],
34
+ dtype:
35
+ )
36
+ )
37
+ end
38
+ end
39
+
40
+ describe "#recode" do
41
+ subject { vector.recode { |v| v == -99 ? 1 : 0 } }
42
+
43
+ it "maps and returns a vector of dtype of self by default" do
44
+ expect(subject).to eq(
45
+ DaruLite::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
46
+ )
47
+ expect(subject.dtype).to eq(:array)
48
+ end
49
+ end
50
+
51
+ describe "#recode!" do
52
+ subject { vector.recode! { |v| v == -99 ? 1 : 0 } }
53
+
54
+ let(:vector) do
55
+ DaruLite::Vector.new(
56
+ [5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, 11, -99, -99],
57
+ name: :common_all_dtypes,
58
+ dtype:
59
+ )
60
+ end
61
+
62
+ it "destructively maps and returns a vector of dtype of self by default" do
63
+ subject
64
+ expect(vector).to eq(
65
+ DaruLite::Vector.new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
66
+ )
67
+ expect(vector.dtype).to eq(dtype)
68
+ end
69
+ end
70
+
71
+ describe "#verify" do
72
+ subject { vector.verify { |d| d > 0 } }
73
+
74
+ let(:vector) do
75
+ DaruLite::Vector.new([1,2,3,4,5,6,-99,35,-100], dtype:)
76
+ end
77
+
78
+ it "returns a hash of invalid data and index of data" do
79
+ expect(subject).to eq({ 6 => -99, 8 => -100 })
80
+ end
81
+ end
82
+
83
+ describe '#replace_values' do
84
+ subject do
85
+ DaruLite::Vector.new(
86
+ [1, 2, 1, 4, nil, Float::NAN, nil, Float::NAN],
87
+ index: 11..18
88
+ )
89
+ end
90
+
91
+ context 'replace nils and NaNs' do
92
+ before { subject.replace_values [nil, Float::NAN], 10 }
93
+
94
+ its(:to_a) { is_expected.to eq [1, 2, 1, 4, 10, 10, 10, 10] }
95
+ end
96
+
97
+ context 'replace arbitrary values' do
98
+ before { subject.replace_values [1, 2], 10 }
99
+
100
+ its(:to_a) { is_expected.to eq(
101
+ [10, 10, 10, 4, nil, Float::NAN, nil, Float::NAN]) }
102
+ end
103
+
104
+ context 'works for single value' do
105
+ before { subject.replace_values nil, 10 }
106
+
107
+ its(:to_a) { is_expected.to eq(
108
+ [1, 2, 1, 4, 10, Float::NAN, 10, Float::NAN]) }
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,25 @@
1
+ shared_examples_for 'a joinable Vector' do |dtype|
2
+ describe "#concat" do
3
+ let(:vector) do
4
+ DaruLite::Vector.new(
5
+ [1, 2, 3, 4, 5],
6
+ name: :yoga,
7
+ index: [:warwick, :thompson, :jackson, :fender, :esp],
8
+ dtype:
9
+ )
10
+ end
11
+
12
+ it "concatenates a new element at the end of vector with index" do
13
+ vector.concat(6, :ibanez)
14
+
15
+ expect(vector.index) .to eq(
16
+ DaruLite::Index.new([:warwick, :thompson, :jackson, :fender, :esp, :ibanez]))
17
+ expect(vector[:ibanez]).to eq(6)
18
+ expect(vector[5]) .to eq(6)
19
+ end
20
+
21
+ it "raises error if index not specified" do
22
+ expect { vector.concat(6) }.to raise_error
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,88 @@
1
+ shared_examples_for 'a missable Vector' do
2
+ describe "#replace_nils" do
3
+ subject { vector.replace_nils(2) }
4
+
5
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, nil, nil, 4]) }
6
+
7
+ it "replaces all nils with the specified value" do
8
+ expect(subject).to eq(DaruLite::Vector.new([1, 2, 3, 2, 2, 4]))
9
+ end
10
+
11
+ it "replaces all nils with the specified value (bang)" do
12
+ vec = DaruLite::Vector.new([1,2,3,nil,nil,4]).replace_nils!(2)
13
+ expect(vec).to eq(DaruLite::Vector.new([1,2,3,2,2,4]))
14
+ end
15
+ end
16
+
17
+ describe "#replace_nils" do
18
+ subject { vector.replace_nils!(2) }
19
+
20
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, nil, nil, 4]) }
21
+
22
+ it "replaces all nils with the specified value (bang)" do
23
+ subject
24
+ expect(vector).to eq(DaruLite::Vector.new([1, 2, 3, 2, 2, 4]))
25
+ end
26
+ end
27
+
28
+ describe '#rolling_fillna!' do
29
+ subject do
30
+ DaruLite::Vector.new(
31
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
32
+ )
33
+ end
34
+
35
+ context 'rolling_fillna! forwards' do
36
+ before { subject.rolling_fillna!(:forward) }
37
+
38
+ its(:to_a) { is_expected.to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
39
+ end
40
+
41
+ context 'rolling_fillna! backwards' do
42
+ before { subject.rolling_fillna!(direction: :backward) }
43
+
44
+ its(:to_a) { is_expected.to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
45
+ end
46
+
47
+ context 'all invalid vector' do
48
+ subject do
49
+ DaruLite::Vector.new(
50
+ [Float::NAN, Float::NAN, Float::NAN, Float::NAN, Float::NAN]
51
+ )
52
+ end
53
+
54
+ before { subject.rolling_fillna!(:forward) }
55
+
56
+ its(:to_a) { is_expected.to eq [0, 0, 0, 0, 0] }
57
+ end
58
+
59
+ context 'with non-default index' do
60
+ subject do
61
+ DaruLite::Vector.new(
62
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN],
63
+ index: %w[a b c d e f g h i]
64
+ )
65
+ end
66
+
67
+ before { subject.rolling_fillna!(direction: :backward) }
68
+
69
+ it { is_expected.to eq DaruLite::Vector.new([2, 2, 1, 4, 3, 3, 3, 0, 0], index: %w[a b c d e f g h i]) }
70
+ end
71
+ end
72
+
73
+ describe '#rolling_fillna' do
74
+ subject do
75
+ DaruLite::Vector.new(
76
+ [Float::NAN, 2, 1, 4, nil, Float::NAN, 3, nil, Float::NAN]
77
+ )
78
+ end
79
+
80
+ context 'rolling_fillna forwards' do
81
+ it { expect(subject.rolling_fillna(:forward).to_a).to eq [0, 2, 1, 4, 4, 4, 3, 3, 3] }
82
+ end
83
+
84
+ context 'rolling_fillna backwards' do
85
+ it { expect(subject.rolling_fillna(direction: :backward).to_a).to eq [2, 2, 1, 4, 3, 3, 3, 0, 0] }
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,91 @@
1
+ shared_examples_for 'a queryable Vector' do
2
+ describe '#include_values?' do
3
+ context 'only nils' do
4
+ context 'true' do
5
+ let(:vector) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown', nil] }
6
+ it { expect(vector.include_values? nil).to eq true }
7
+ end
8
+
9
+ context 'false' do
10
+ let(:vector) { DaruLite::Vector.new [1, 2, 3, :a, 'Unknown'] }
11
+ it { expect(vector.include_values? nil).to eq false }
12
+ end
13
+ end
14
+
15
+ context 'only Float::NAN' do
16
+ context 'true' do
17
+ let(:vector) { DaruLite::Vector.new [1, nil, 2, 3, Float::NAN] }
18
+ it { expect(vector.include_values? Float::NAN).to eq true }
19
+ end
20
+
21
+ context 'false' do
22
+ let(:vector) { DaruLite::Vector.new [1, nil, 2, 3] }
23
+ it { expect(vector.include_values? Float::NAN).to eq false }
24
+ end
25
+ end
26
+
27
+ context 'both nil and Float::NAN' do
28
+ context 'true with only nil' do
29
+ let(:vector) { DaruLite::Vector.new [1, Float::NAN, 2, 3] }
30
+ it { expect(vector.include_values? nil, Float::NAN).to eq true }
31
+ end
32
+
33
+ context 'true with only Float::NAN' do
34
+ let(:vector) { DaruLite::Vector.new [1, nil, 2, 3] }
35
+ it { expect(vector.include_values? nil, Float::NAN).to eq true }
36
+ end
37
+
38
+ context 'false' do
39
+ let(:vector) { DaruLite::Vector.new [1, 2, 3] }
40
+ it { expect(vector.include_values? nil, Float::NAN).to eq false }
41
+ end
42
+ end
43
+
44
+ context 'any other value' do
45
+ context 'true' do
46
+ let(:vector) { DaruLite::Vector.new [1, 2, 3, 4, nil] }
47
+ it { expect(vector.include_values? 1, 2, 3, 5).to eq true }
48
+ end
49
+
50
+ context 'false' do
51
+ let(:vector) { DaruLite::Vector.new [1, 2, 3, 4, nil] }
52
+ it { expect(vector.include_values? 5, 6).to eq false }
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#any?" do
58
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, 4, 5]) }
59
+
60
+ it "returns true if block returns true for any one of the elements" do
61
+ expect(vector.any?{ |e| e == 1 }).to eq(true)
62
+ end
63
+
64
+ it "returns false if block is false for all elements" do
65
+ expect(vector.any?{ |e| e > 10 }).to eq(false)
66
+ end
67
+ end
68
+
69
+ describe "#all?" do
70
+ let(:vector) { DaruLite::Vector.new([1, 2, 3, 4, 5]) }
71
+
72
+ it "returns true if block is true for all elements" do
73
+ expect(vector.all? { |e| e < 6 }).to eq(true)
74
+ end
75
+
76
+ it "returns false if block is false for any one element" do
77
+ expect(vector.all? { |e| e == 2 }).to eq(false)
78
+ end
79
+ end
80
+
81
+ describe '#match' do
82
+ subject { dv.match(regexp) }
83
+
84
+ context 'returns matching array for a given regexp' do
85
+ let(:dv) { DaruLite::Vector.new ['3 days', '5 weeks', '2 weeks'] }
86
+ let(:regexp) { /weeks/ }
87
+
88
+ it { is_expected.to eq([false, true, true]) }
89
+ end
90
+ end
91
+ end