davidrichards-data_frame 0.0.15 → 0.0.17
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.
- data/README.rdoc +15 -0
- data/VERSION.yml +1 -1
- data/lib/data_frame.rb +3 -302
- data/lib/data_frame/data_frame.rb +301 -0
- data/lib/data_frame/model.rb +22 -0
- data/lib/data_frame/parameter_capture.rb +50 -0
- data/spec/data_frame/data_frame_spec.rb +341 -0
- data/spec/data_frame/model_spec.rb +36 -0
- data/spec/data_frame/parameter_capture_spec.rb +32 -0
- data/spec/data_frame_spec.rb +14 -326
- metadata +9 -4
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "/../spec_helper")
|
2
|
+
|
3
|
+
describe ParameterCapture do
|
4
|
+
|
5
|
+
it "should take a block for a column list" do
|
6
|
+
pc = ParameterCapture.new do |p|
|
7
|
+
p.a 1
|
8
|
+
p.b 2
|
9
|
+
end
|
10
|
+
pc.parameters.table.should == {:a => 1, :b => 2}
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to capture an array as a parameter, meaning an or-condition" do
|
14
|
+
pc = ParameterCapture.new do |p|
|
15
|
+
p.or_condition [1,2]
|
16
|
+
end
|
17
|
+
pc.parameters.or_condition.should eql([1,2])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be able to capture a range as a parameter, meaning a continuous-or-condition" do
|
21
|
+
pc = ParameterCapture.new do |p|
|
22
|
+
p.a (1..2)
|
23
|
+
end
|
24
|
+
pc.parameters.a.should eql((1..2))
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should play setter/getter schizophrenia" do
|
28
|
+
pc = ParameterCapture.new {}
|
29
|
+
pc.show 1
|
30
|
+
pc.show.should eql(1)
|
31
|
+
end
|
32
|
+
end
|
data/spec/data_frame_spec.rb
CHANGED
@@ -1,341 +1,29 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "/spec_helper")
|
2
2
|
|
3
|
-
describe DataFrame do
|
3
|
+
describe DataFrame, "gem dependencies" do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
@df = DataFrame.new(*@labels)
|
5
|
+
it "should use RubyGems" do
|
6
|
+
defined?(Gem).should eql('constant')
|
8
7
|
end
|
9
8
|
|
10
|
-
it "should
|
11
|
-
|
12
|
-
df.labels.should eql(@labels)
|
9
|
+
it "should use ActiveSupport" do
|
10
|
+
defined?(ActiveSupport).should eql('constant')
|
13
11
|
end
|
14
12
|
|
15
|
-
it "should
|
16
|
-
|
17
|
-
@df.items.should be_empty
|
13
|
+
it "should use JustEnumerableStats" do
|
14
|
+
[1]._jes_average.should eql(1)
|
18
15
|
end
|
19
16
|
|
20
|
-
it "should
|
21
|
-
|
22
|
-
@df.add_item(item)
|
23
|
-
@df.items.should eql([item])
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should use just_enumerable_stats" do
|
27
|
-
[1,2,3].std.should eql(1)
|
28
|
-
lambda{[1,2,3].cor([2,3,5])}.should_not raise_error
|
29
|
-
end
|
30
|
-
|
31
|
-
context "column and row operations" do
|
32
|
-
before do
|
33
|
-
@df.add_item([1,2,3,4])
|
34
|
-
@df.add_item([5,6,7,8])
|
35
|
-
@df.add_item([9,10,11,12])
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should have a method for every label, the column in the data frame" do
|
39
|
-
@df.these.should eql([1,5,9])
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should make columns easily computable" do
|
43
|
-
@df.these.std.should eql([1,5,9].std)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should defer unknown methods to the items in the data frame" do
|
47
|
-
@df[0].should eql([1,2,3,4])
|
48
|
-
@df << [13,14,15,16]
|
49
|
-
@df.last.should eql([13,14,15,16])
|
50
|
-
@df.map { |e| e.sum }.should eql([10,26,42,58])
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should allow optional row labels" do
|
54
|
-
@df.row_labels.should eql([])
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should have a setter for row labels" do
|
58
|
-
@df.row_labels = [:other, :things, :here]
|
59
|
-
@df.row_labels.should eql([:other, :things, :here])
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should be able to access rows by their labels" do
|
63
|
-
@df.row_labels = [:other, :things, :here]
|
64
|
-
@df.here.should eql([9,10,11,12])
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should make rows easily computable" do
|
68
|
-
@df.row_labels = [:other, :things, :here]
|
69
|
-
@df.here.sum.should eql(42)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should be able to import more than one row at a time" do
|
74
|
-
@df.import([[2,2,2,2],[3,3,3,3],[4,4,4,4]])
|
75
|
-
@df.row_labels = [:twos, :threes, :fours]
|
76
|
-
@df.twos.should eql([2,2,2,2])
|
77
|
-
@df.threes.should eql([3,3,3,3])
|
78
|
-
@df.fours.should eql([4,4,4,4])
|
79
|
-
end
|
80
|
-
|
81
|
-
context "csv" do
|
82
|
-
it "should compute easily from csv" do
|
83
|
-
contents = %{X,Y,month,day,FFMC,DMC,DC,ISI,temp,RH,wind,rain,area
|
84
|
-
7,5,mar,fri,86.2,26.2,94.3,5.1,8.2,51,6.7,0,0
|
85
|
-
7,4,oct,tue,90.6,35.4,669.1,6.7,18,33,0.9,0,0
|
86
|
-
}
|
87
|
-
labels = [:x, :y, :month, :day, :ffmc, :dmc, :dc, :isi, :temp, :rh, :wind, :rain, :area]
|
88
|
-
|
89
|
-
@df = DataFrame.from_csv(contents)
|
90
|
-
@df.labels.should eql(labels)
|
91
|
-
@df.x.should eql([7,7])
|
92
|
-
@df.area.should eql([0,0])
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should be able to remove a column" do
|
97
|
-
@df = DataFrame.new :twos, :threes, :fours
|
98
|
-
@df.import([[2,3,4], [2,3,4], [2,3,4], [2,3,4]])
|
99
|
-
@df.drop!(:twos)
|
100
|
-
@df.items.all? {|i| i.should eql([3,4])}
|
101
|
-
@df.labels.should eql([:threes, :fours])
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should be able to remove more than one column at a time" do
|
105
|
-
@df = DataFrame.new :twos, :threes, :fours
|
106
|
-
@df.import([[2,3,4], [2,3,4], [2,3,4], [2,3,4]])
|
107
|
-
@df.drop!(:twos, :fours)
|
108
|
-
@df.items.all? {|i| i.should eql([3])}
|
109
|
-
@df.labels.should eql([:threes])
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should offer a hash-like structure of columns" do
|
113
|
-
@df.add [1,2,3,4]
|
114
|
-
@df.add [5, 6, 7, 8]
|
115
|
-
@df.columns[:these].should eql([1, 5])
|
116
|
-
@df.columns[:are].should eql([2, 6])
|
117
|
-
@df.columns[:the].should eql([3, 7])
|
118
|
-
@df.columns[:labels].should eql([4, 8])
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should alias items with rows" do
|
122
|
-
@df.add [1,2,3,4]
|
123
|
-
@df.add [5, 6, 7, 8]
|
124
|
-
@df.rows.should eql(@df.items)
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should be able to export a hash" do
|
128
|
-
@df.add [1,2,3,4]
|
129
|
-
@df.add [5, 6, 7, 8]
|
130
|
-
hash = @df.to_hash
|
131
|
-
values = [[1,5],[2,6],[3,7],[4,8]]
|
132
|
-
hash.keys.size.should eql(@labels.size)
|
133
|
-
hash.keys.all? {|e| @labels.should be_include(e)}
|
134
|
-
hash.values.size.should eql(@labels.size)
|
135
|
-
hash.values.all? {|e| values.should be_include(e)}
|
136
|
-
end
|
137
|
-
|
138
|
-
it "should use variables like labels" do
|
139
|
-
@df.labels.should eql(@labels)
|
140
|
-
@df.variables.should eql(@labels)
|
141
|
-
end
|
142
|
-
|
143
|
-
context "replace!" do
|
144
|
-
before do
|
145
|
-
@df.add [1,2,3,4]
|
146
|
-
@df.add [5, 6, 7, 8]
|
147
|
-
@doubler = lambda{|e| e * 2}
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should only replace columns that actually exist" do
|
151
|
-
lambda{@df.replace!(:not_a_column, &@doubler)}.should raise_error(
|
152
|
-
ArgumentError, /Must provide the name of an existing column./)
|
153
|
-
lambda{@df.replace!(:these, &@doubler)}.should_not raise_error
|
154
|
-
end
|
155
|
-
|
156
|
-
it "should be able to replace a column with a block" do
|
157
|
-
@df.replace!(:these) {|e| e * 2}
|
158
|
-
@df.these.should eql([2,10])
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should be able to replace a column with an array" do
|
162
|
-
@a = [5,9]
|
163
|
-
@df.replace!(:these, @a)
|
164
|
-
@df.these.should eql(@a)
|
165
|
-
end
|
17
|
+
it "should use OpenURI" do
|
18
|
+
defined?(OpenURI).should eql('constant')
|
166
19
|
end
|
167
20
|
|
168
|
-
|
169
|
-
|
170
|
-
@df.add [1,2,3,4]
|
171
|
-
@df.add [5, 6, 7, 8]
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should be able to filter a data frame with a block using an OpenStruct for each row" do
|
175
|
-
@df.filter!(:open_struct) {|row| row.these == 5}
|
176
|
-
@df.items.should eql([[5, 6, 7, 8]])
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should be able to filter a data frame with a block using a Hash for each row" do
|
180
|
-
@df.filter!(:hash) {|row| row[:these] == 5}
|
181
|
-
@df.items.should eql([[5, 6, 7, 8]])
|
182
|
-
end
|
183
|
-
|
184
|
-
S4 = Struct.new(:one, :two, :three, :four)
|
185
|
-
it "should be able to filter a data frame with a block using another class that uses the row as input" do
|
186
|
-
@df.filter!(S4) {|row| row.one == 5}
|
187
|
-
@df.items.should eql([[5, 6, 7, 8]])
|
188
|
-
end
|
189
|
-
|
190
|
-
it "should be able to filter a data frame with a block using an array for each row" do
|
191
|
-
@df.filter! {|row| row.first == 5}
|
192
|
-
@df.items.should eql([[5, 6, 7, 8]])
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should be able to do fancy things with the row as the filter" do
|
196
|
-
@df.filter! {|row| row.sum > 10}
|
197
|
-
@df.items.should eql([[5, 6, 7, 8]])
|
198
|
-
end
|
199
|
-
|
200
|
-
it "should be able to generate a new data frame with filter" do
|
201
|
-
new_df = @df.filter(:open_struct) {|row| row.these == 5}
|
202
|
-
new_df.items.should eql([[5, 6, 7, 8]])
|
203
|
-
@df.items.should eql([[1, 2, 3, 4], [5, 6, 7, 8]])
|
204
|
-
end
|
205
|
-
|
21
|
+
it "should use FasterCSV" do
|
22
|
+
defined?(FasterCSV).should eql('constant')
|
206
23
|
end
|
207
24
|
|
208
|
-
|
209
|
-
|
210
|
-
before do
|
211
|
-
@df = DataFrame.new(:weather, :date)
|
212
|
-
|
213
|
-
(1..31).each do |i|
|
214
|
-
@df.add [(i % 3 == 1) ? :fair : :good, Date.parse("07/#{i}/2009")]
|
215
|
-
end
|
216
|
-
|
217
|
-
@d1 = Date.parse("07/15/2009")
|
218
|
-
@d2 = Date.parse("07/31/2009")
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
it "should be able to filter by category" do
|
223
|
-
filtered = @df.filter_by_category(:weather => :good)
|
224
|
-
filtered.weather.uniq.should eql([:good])
|
225
|
-
@df.weather.uniq.should be_include(:fair)
|
226
|
-
end
|
227
|
-
|
228
|
-
it "should be able to manage ranges for filter values" do
|
229
|
-
filtered = @df.filter_by_category(:date => (@d1..@d2))
|
230
|
-
filtered.date.should_not be_include(Date.parse("07/01/2009"))
|
231
|
-
filtered.date.should_not be_include(Date.parse("07/14/2009"))
|
232
|
-
filtered.date.should be_include(Date.parse("07/15/2009"))
|
233
|
-
filtered.date.should be_include(Date.parse("07/31/2009"))
|
234
|
-
@df.date.should be_include(Date.parse("07/01/2009"))
|
235
|
-
end
|
236
|
-
|
237
|
-
it "should be able to take an array of values to filter with" do
|
238
|
-
filtered = @df.filter_by_category(:date => [@d1, @d2])
|
239
|
-
filtered.date.should_not be_include(Date.parse("07/01/2009"))
|
240
|
-
filtered.date.should be_include(Date.parse("07/15/2009"))
|
241
|
-
filtered.date.should be_include(Date.parse("07/31/2009"))
|
242
|
-
end
|
243
|
-
|
244
|
-
it "should have a destructive version" do
|
245
|
-
@df.filter_by_category!(:date => [@d1, @d2])
|
246
|
-
@df.date.should_not be_include(Date.parse("07/01/2009"))
|
247
|
-
@df.date.should be_include(Date.parse("07/15/2009"))
|
248
|
-
@df.date.should be_include(Date.parse("07/31/2009"))
|
249
|
-
end
|
250
|
-
|
25
|
+
it "should use OpenStruct" do
|
26
|
+
defined?(OpenStruct).should eql('constant')
|
251
27
|
end
|
252
|
-
|
253
|
-
context "subset_from_columns" do
|
254
|
-
before do
|
255
|
-
@df.add [1,2,3,4]
|
256
|
-
@df.add [5, 6, 7, 8]
|
257
|
-
end
|
258
28
|
|
259
|
-
|
260
|
-
new_data_frame = @df.subset_from_columns(:these, :labels)
|
261
|
-
new_data_frame.should_not eql(@df)
|
262
|
-
new_data_frame.labels.should eql([:these, :labels])
|
263
|
-
new_data_frame.items.should eql([[1,4],[5,8]])
|
264
|
-
new_data_frame.these.should eql([1,5])
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
it "should be able to j_binary_ize! a column, taking its categories and creating a column for each" do
|
269
|
-
df = DataFrame.new(:observations)
|
270
|
-
df.add [:many]
|
271
|
-
df.add [:fine]
|
272
|
-
df.add [:things]
|
273
|
-
df.add [:are]
|
274
|
-
df.add [:available]
|
275
|
-
df.j_binary_ize!(:observations)
|
276
|
-
df.observations_many.should eql([true, false, false, false, false])
|
277
|
-
df.observations_fine.should eql([false, true, false, false, false])
|
278
|
-
df.observations_things.should eql([false, false, true, false, false])
|
279
|
-
df.observations_are.should eql([false, false, false, true, false])
|
280
|
-
df.observations_available.should eql([false, false, false, false, true])
|
281
|
-
df.observations.should eql([:many, :fine, :things, :are, :available])
|
282
|
-
end
|
283
|
-
|
284
|
-
it "should be able to j_binary_ize! a more normal column" do
|
285
|
-
df = DataFrame.new(:observations)
|
286
|
-
df.import([1,2,3,4,5,4,3,2,1].map{|e| Array(e)})
|
287
|
-
df.observations.add_category(:small) {|e| e <= 3}
|
288
|
-
df.observations.add_category(:large) {|e| e >= 3}
|
289
|
-
df.j_binary_ize!(:observations)
|
290
|
-
df.observations_small.should eql([true, true, true, false, false, false, true, true, true])
|
291
|
-
df.observations_large.should eql([false, false, false, true, true, true, false, false, false])
|
292
|
-
end
|
293
|
-
|
294
|
-
it "should be able to j_binary_ize with non-adjacent sets (sets that allow a value to have more than one category)" do
|
295
|
-
df = DataFrame.new(:observations)
|
296
|
-
df.import([1,2,3,4,5,4,3,2,1].map{|e| Array(e)})
|
297
|
-
df.observations.add_category(:small) {|e| e <= 3}
|
298
|
-
df.observations.add_category(:large) {|e| e >= 3}
|
299
|
-
df.j_binary_ize!(:observations, :allow_overlap => true)
|
300
|
-
df.observations_small.should eql([true, true, true, false, false, false, true, true, true])
|
301
|
-
df.observations_large.should eql([false, false, true, true, true, true, true, false, false])
|
302
|
-
end
|
303
|
-
|
304
|
-
it "should be able to hold multiple ideas of a columns categories by resetting the category and re-running j_binary_ize" do
|
305
|
-
df = DataFrame.new(:observations)
|
306
|
-
df.import([1,2,3,4,5,4,3,2,1].map{|e| Array(e)})
|
307
|
-
df.observations.add_category(:small) {|e| e <= 3}
|
308
|
-
df.observations.add_category(:large) {|e| e >= 3}
|
309
|
-
df.j_binary_ize!(:observations, :allow_overlap => true)
|
310
|
-
df.observations.set_categories(:odd => lambda{|e| e.odd?}, :even => lambda{|e| e.even?})
|
311
|
-
df.j_binary_ize!(:observations)
|
312
|
-
df.observations_small.should eql([true, true, true, false, false, false, true, true, true])
|
313
|
-
df.observations_large.should eql([false, false, true, true, true, true, true, false, false])
|
314
|
-
df.observations.should eql([1,2,3,4,5,4,3,2,1])
|
315
|
-
df.observations_even.should eql([false, true, false, true, false, true, false, true, false])
|
316
|
-
df.observations_odd.should eql([true, false, true, false, true, false, true, false, true])
|
317
|
-
end
|
318
|
-
|
319
|
-
context "append!" do
|
320
|
-
|
321
|
-
before do
|
322
|
-
@df.add [1,2,3,4]
|
323
|
-
@df.add [5, 6, 7, 8]
|
324
|
-
end
|
325
|
-
|
326
|
-
it "should be able to append an array of values to the data frame" do
|
327
|
-
@df.append!(:new_column, [5,5])
|
328
|
-
@df.new_column.should eql([5,5])
|
329
|
-
end
|
330
|
-
|
331
|
-
it "should be able to append a default value to the data frame" do
|
332
|
-
@df.append!(:new_column, :value)
|
333
|
-
@df.new_column.should eql([:value, :value])
|
334
|
-
end
|
335
|
-
|
336
|
-
it "should use nil as the default value" do
|
337
|
-
@df.append!(:new_column)
|
338
|
-
@df.new_column.should eql([nil, nil])
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: davidrichards-data_frame
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Richards
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-29 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -55,6 +55,9 @@ files:
|
|
55
55
|
- VERSION.yml
|
56
56
|
- lib/data_frame
|
57
57
|
- lib/data_frame/callback_array.rb
|
58
|
+
- lib/data_frame/data_frame.rb
|
59
|
+
- lib/data_frame/model.rb
|
60
|
+
- lib/data_frame/parameter_capture.rb
|
58
61
|
- lib/data_frame/transposable_array.rb
|
59
62
|
- lib/data_frame.rb
|
60
63
|
- lib/ext
|
@@ -63,12 +66,14 @@ files:
|
|
63
66
|
- lib/ext/symbol.rb
|
64
67
|
- spec/data_frame
|
65
68
|
- spec/data_frame/callback_array_spec.rb
|
69
|
+
- spec/data_frame/data_frame_spec.rb
|
70
|
+
- spec/data_frame/model_spec.rb
|
71
|
+
- spec/data_frame/parameter_capture_spec.rb
|
66
72
|
- spec/data_frame/transposable_array_spec.rb
|
67
73
|
- spec/data_frame_spec.rb
|
68
74
|
- spec/spec_helper.rb
|
69
75
|
has_rdoc: true
|
70
76
|
homepage: http://github.com/davidrichards/data_frame
|
71
|
-
licenses:
|
72
77
|
post_install_message:
|
73
78
|
rdoc_options:
|
74
79
|
- --inline-source
|
@@ -90,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
95
|
requirements: []
|
91
96
|
|
92
97
|
rubyforge_project:
|
93
|
-
rubygems_version: 1.
|
98
|
+
rubygems_version: 1.2.0
|
94
99
|
signing_key:
|
95
100
|
specification_version: 2
|
96
101
|
summary: Data Frames with memoized transpose
|