tablestakes 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -7
- data/lib/tablestakes.rb +54 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c4827f9fe7583ab475c276cb8930937e51e7c42
|
4
|
+
data.tar.gz: f27a3196f816a096c8d311e3288d4ab3126005dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3539e569ca9534174250d0f0a697443e3bbc2e8fa3baf19d6d4ea4787f06504b4150b8bdaf0145daf33d1ce77e5b34b0e1b4de25c312852a0b4d22e94e88206
|
7
|
+
data.tar.gz: 6513f7ef2d5ef1dbb3a696b57dae6915ce018f0a6d274b4b1572cd51192df67fd0e92e5cea0e3519339a8e97dccce068207a448d2402283d1f8890af69328990
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ Tablestakes
|
|
7
7
|
Tablestakes is a gem for processing tabular data. It is for people who would rather not meddle with
|
8
8
|
a spreadsheet, or load their data into a SQL database. You get the instant gratification of being
|
9
9
|
able to read a tab-delimited file, with header values, and then do field counts, field modifications,
|
10
|
-
selections, joins
|
10
|
+
selections, joins to your heart's content. Tablestakes operates only in memory, so it
|
11
11
|
is fast. Of course that also means that there are some size limitations -- very large tables
|
12
12
|
should be processed with another library.
|
13
13
|
|
@@ -25,8 +25,6 @@ Contents
|
|
25
25
|
How to Install
|
26
26
|
--------------
|
27
27
|
|
28
|
-
Tablestakes also does well in the IRB interactive shell, you can make use of:
|
29
|
-
|
30
28
|
1. Install the gem
|
31
29
|
|
32
30
|
```shell
|
@@ -45,14 +43,13 @@ Now you're ready to start slicing and dicing your data tables!
|
|
45
43
|
Philosophy and Conventions
|
46
44
|
--------------------------
|
47
45
|
|
48
|
-
Tablestakes is meant to be fast and easy for manipulating your data. It maintains
|
49
|
-
conventions, like
|
46
|
+
Tablestakes is meant to be fast and easy for manipulating your data. It maintains Ruby
|
47
|
+
conventions, like method chaining and mostly non-destructive methods.
|
50
48
|
|
51
49
|
Tablestakes tables also maintain some conventions for simplicity:
|
52
50
|
|
53
51
|
* Table column names are always the values in the first row of your data file.
|
54
|
-
* Fields in the table are always strings (
|
55
|
-
when needed).
|
52
|
+
* Fields in the table are always strings (conversion to numbers or dates is a potential enhancement).
|
56
53
|
* Methods only modify one dimension at a time. So, for instance, `Table#select` only selects
|
57
54
|
columns and `Table#where` only selects rows. Chain them together for the desired effect.
|
58
55
|
* Tables are ordered, both columns and rows, until modified.
|
@@ -216,3 +213,13 @@ file.
|
|
216
213
|
Some methods, such as `Table#row` and `Table#column` return Arrays, and of course these are
|
217
214
|
readily modified using their own native methods.
|
218
215
|
|
216
|
+
Future Enhancements
|
217
|
+
-------------------
|
218
|
+
|
219
|
+
Some future enhancements that would make this gem better include:
|
220
|
+
|
221
|
+
1. Implement Ruby Enumerators
|
222
|
+
|
223
|
+
2. Include some concept of data type ... at least FixedNum and Date.
|
224
|
+
|
225
|
+
3. `Table#sort` method -- probably requires enumerators and data types to be effective.
|
data/lib/tablestakes.rb
CHANGED
@@ -67,6 +67,54 @@ class Table
|
|
67
67
|
Array(get_row(index))
|
68
68
|
end
|
69
69
|
|
70
|
+
# Add a column to the Table. Returns nil if the column name is already taken
|
71
|
+
# or there are not the correct number of values.
|
72
|
+
#
|
73
|
+
# +colname+:: +String+ to identify the name of the column
|
74
|
+
# +column_vals+:: +Array+ to hold the column values
|
75
|
+
def add_column(colname, column_vals)
|
76
|
+
# check arguments
|
77
|
+
return nil if @table.has_key?(colname)
|
78
|
+
return nil unless column_vals.length == @table[@headers.first].length
|
79
|
+
|
80
|
+
@headers << colname
|
81
|
+
@table[colname] = Array.new(column_vals)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Add a row to the Table, appending it to the end. Returns nil if
|
85
|
+
# there are not the correct number of values.
|
86
|
+
#
|
87
|
+
# +row_vals+:: +Array+ to hold the row values
|
88
|
+
def add_row(row_vals)
|
89
|
+
add_rows([row_vals])
|
90
|
+
end
|
91
|
+
|
92
|
+
# Delete a column from the Table. Returns nil if the column name does not exist.
|
93
|
+
#
|
94
|
+
# +colname+:: +String+ to identify the name of the column
|
95
|
+
def del_column(colname)
|
96
|
+
# check arguments
|
97
|
+
return nil unless @table.has_key?(colname)
|
98
|
+
|
99
|
+
@headers.delete(colname)
|
100
|
+
@table.delete(colname)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Delete a row from the Table. Returns nil if
|
104
|
+
# the row number is not found.
|
105
|
+
#
|
106
|
+
# +rownum+:: +FixNum+ to hold the row number
|
107
|
+
def del_row(rownum)
|
108
|
+
# check arguments
|
109
|
+
return nil unless rownum <= @table[@headers.first].length
|
110
|
+
|
111
|
+
@headers.each do |col|
|
112
|
+
@table[col].delete_at(rownum)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
70
118
|
# Converts a +Table+ object to a tab-delimited string.
|
71
119
|
#
|
72
120
|
# none
|
@@ -139,7 +187,7 @@ class Table
|
|
139
187
|
# +num+:: OPTIONAL +String+ number of values to return
|
140
188
|
def top(colname, num=1)
|
141
189
|
freq = tally(colname).to_a[1..-1].sort_by {|k,v| v }.reverse
|
142
|
-
return Table.new(freq[0..num-1].unshift([
|
190
|
+
return Table.new(freq[0..num-1].unshift([colname,"Count"]))
|
143
191
|
end
|
144
192
|
|
145
193
|
|
@@ -151,7 +199,7 @@ class Table
|
|
151
199
|
# +num+:: OPTIONAL +String+ number of values to return
|
152
200
|
def bottom(colname, num=1)
|
153
201
|
freq = tally(colname).to_a[1..-1].sort_by {|k,v| v }
|
154
|
-
return Table.new(freq[0..num-1].unshift([
|
202
|
+
return Table.new(freq[0..num-1].unshift([colname,"Count"]))
|
155
203
|
end
|
156
204
|
|
157
205
|
|
@@ -216,7 +264,7 @@ class Table
|
|
216
264
|
result << @headers
|
217
265
|
@table[colname].each_index do |index|
|
218
266
|
if condition
|
219
|
-
eval("
|
267
|
+
eval(%q["#{@table[colname][index]}"] << "#{condition}") ? result << get_row(index) : nil
|
220
268
|
else
|
221
269
|
result << get_row(index)
|
222
270
|
end
|
@@ -343,7 +391,9 @@ class Table
|
|
343
391
|
@headers.each {|col| @table.store(col, []) }
|
344
392
|
file.each_line do |line|
|
345
393
|
fields = line.chomp.split("\t")
|
346
|
-
if fields.length
|
394
|
+
if fields.length < @headers.length
|
395
|
+
(@headers.length - fields.length).times { fields << "" }
|
396
|
+
elsif fields.length > @headers.length
|
347
397
|
$stderr.write "INVALID NUMBER OF FIELDS: #{fields.join(';')}\n"
|
348
398
|
else
|
349
399
|
@headers.each { |col| @table[col] << fields.shift }
|