tablestakes 0.8.3 → 0.8.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.
- 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 }
|