daru_lite 0.1.1 → 0.1.2

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 (67) 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 +13 -0
  20. data/lib/daru_lite/maths/statistics/vector.rb +1 -1
  21. data/lib/daru_lite/vector/aggregatable.rb +9 -0
  22. data/lib/daru_lite/vector/calculatable.rb +78 -0
  23. data/lib/daru_lite/vector/convertible.rb +77 -0
  24. data/lib/daru_lite/vector/duplicatable.rb +17 -0
  25. data/lib/daru_lite/vector/fetchable.rb +175 -0
  26. data/lib/daru_lite/vector/filterable.rb +128 -0
  27. data/lib/daru_lite/vector/indexable.rb +77 -0
  28. data/lib/daru_lite/vector/iterable.rb +95 -0
  29. data/lib/daru_lite/vector/joinable.rb +17 -0
  30. data/lib/daru_lite/vector/missable.rb +124 -0
  31. data/lib/daru_lite/vector/queryable.rb +45 -0
  32. data/lib/daru_lite/vector/setable.rb +47 -0
  33. data/lib/daru_lite/vector/sortable.rb +113 -0
  34. data/lib/daru_lite/vector.rb +36 -932
  35. data/lib/daru_lite/version.rb +1 -1
  36. data/spec/data_frame/aggregatable_example.rb +65 -0
  37. data/spec/data_frame/buildable_example.rb +109 -0
  38. data/spec/data_frame/calculatable_example.rb +135 -0
  39. data/spec/data_frame/convertible_example.rb +180 -0
  40. data/spec/data_frame/duplicatable_example.rb +111 -0
  41. data/spec/data_frame/fetchable_example.rb +476 -0
  42. data/spec/data_frame/filterable_example.rb +250 -0
  43. data/spec/data_frame/indexable_example.rb +221 -0
  44. data/spec/data_frame/iterable_example.rb +465 -0
  45. data/spec/data_frame/joinable_example.rb +106 -0
  46. data/spec/data_frame/missable_example.rb +47 -0
  47. data/spec/data_frame/pivotable_example.rb +297 -0
  48. data/spec/data_frame/queryable_example.rb +92 -0
  49. data/spec/data_frame/setable_example.rb +482 -0
  50. data/spec/data_frame/sortable_example.rb +350 -0
  51. data/spec/dataframe_spec.rb +181 -3289
  52. data/spec/index/index_spec.rb +8 -0
  53. data/spec/vector/aggregatable_example.rb +27 -0
  54. data/spec/vector/calculatable_example.rb +82 -0
  55. data/spec/vector/convertible_example.rb +126 -0
  56. data/spec/vector/duplicatable_example.rb +48 -0
  57. data/spec/vector/fetchable_example.rb +463 -0
  58. data/spec/vector/filterable_example.rb +165 -0
  59. data/spec/vector/indexable_example.rb +201 -0
  60. data/spec/vector/iterable_example.rb +111 -0
  61. data/spec/vector/joinable_example.rb +25 -0
  62. data/spec/vector/missable_example.rb +88 -0
  63. data/spec/vector/queryable_example.rb +91 -0
  64. data/spec/vector/setable_example.rb +300 -0
  65. data/spec/vector/sortable_example.rb +242 -0
  66. data/spec/vector_spec.rb +111 -1805
  67. 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