fat_table 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.org +95 -53
- data/lib/fat_table/footer.rb +72 -32
- data/lib/fat_table/formatters/formatter.rb +136 -20
- data/lib/fat_table/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f348d317c061becae08890ff02cc9c08789787d966f9ed88f3a4ef22b6eddb44
|
4
|
+
data.tar.gz: bf672b4f4f4ab07df465d06904ccebb9b48507177dc88a343eb09bfb0e98bc02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c721233a04cc1664e8d8acea3cf677190aa47da30b3db7e1b9f6c13ddd56028a8ecd8b0c71915d0a1703f46fc9a22a1c3a8a3f13d6c80fb07964a22fd864ab7e
|
7
|
+
data.tar.gz: 7877d4529d8a6f2a13ee0a1518730791b4e5ed7dbadd2030367593c95ccdbd5159e711f7ffe69b9b2fa9b4812a6f49d3d1a9fce46642e4454f54ff40d769a4cb
|
data/README.org
CHANGED
@@ -31,8 +31,9 @@ The following is for org.
|
|
31
31
|
"Current version is: #{FatTable::VERSION}"
|
32
32
|
#+end_src
|
33
33
|
|
34
|
+
#+RESULTS:
|
34
35
|
#+begin_EXAMPLE
|
35
|
-
Current version is: 0.
|
36
|
+
Current version is: 0.6.0
|
36
37
|
#+end_EXAMPLE
|
37
38
|
|
38
39
|
* Introduction
|
@@ -148,6 +149,7 @@ org-mode buffer as an org-table, ready for processing by other code blocks.
|
|
148
149
|
- [[#type-and-column-priority][Type and Column priority]]
|
149
150
|
- [[#footers][Footers]]
|
150
151
|
- [[#adding-footers][Adding Footers]]
|
152
|
+
- [[#dynamic-labels][Dynamic Labels]]
|
151
153
|
- [[#aggregators][Aggregators]]
|
152
154
|
- [[#footer-objects][Footer objects]]
|
153
155
|
- [[#footer-examples][Footer Examples]]
|
@@ -534,6 +536,7 @@ You can create an empty table with ~FatTable::Table.new~ or, the shorter form,
|
|
534
536
|
in the added rows determine the names of the headers:
|
535
537
|
|
536
538
|
#+BEGIN_SRC ruby :results silent
|
539
|
+
require 'fat_table'
|
537
540
|
tab = FatTable.new
|
538
541
|
tab << { a: 1, b: 2, c: "<2017-01-21>", d: 'f', e: '' }
|
539
542
|
tab << { a: 3.14, b: 2.17, c: '[2016-01-21 Thu]', d: 'Y', e: nil }
|
@@ -1754,8 +1757,6 @@ available in ~ft_console~ as ~@tab_a~ and ~@tab_b~:
|
|
1754
1757
|
| 2 | Engineering | 2 |
|
1755
1758
|
| 3 | Finance | 7 |
|
1756
1759
|
EOS
|
1757
|
-
|
1758
|
-
tab_b = FatTable.from_org_string(tab_b_str)
|
1759
1760
|
#+END_SRC
|
1760
1761
|
|
1761
1762
|
Here is ~tab_a~:
|
@@ -2465,7 +2466,6 @@ Finance&
|
|
2465
2466
|
{:id=>"3", :dept=>"Finance", :emp_id=>"7"}]
|
2466
2467
|
#+end_EXAMPLE
|
2467
2468
|
|
2468
|
-
|
2469
2469
|
*** Formatting Directives
|
2470
2470
|
The formatting methods explained in the next section all take formatting
|
2471
2471
|
directives as strings in which letters and other characters signify what
|
@@ -2706,12 +2706,27 @@ but not for other nils, such as in the last row of the ~:join_date~ column.
|
|
2706
2706
|
|
2707
2707
|
*** Footers
|
2708
2708
|
**** Adding Footers
|
2709
|
-
You can call the ~
|
2710
|
-
objects to add footers and group footers. Note that all of these
|
2711
|
-
return a ~Footer~ object that can be accessed to extract the computed
|
2712
|
-
All of these methods return the ~FatTable::Footer~ object so
|
2713
|
-
can be used to access the values and other attributes of the
|
2714
|
-
computed. Their signatures are:
|
2709
|
+
You can call the ~foot~, ~gfoot~, ~footer,~ or ~gfooter~, methods on
|
2710
|
+
~Formatter~ objects to add footers and group footers. Note that all of these
|
2711
|
+
methods return a ~Footer~ object that can be accessed to extract the computed
|
2712
|
+
values. All of these methods return the ~FatTable::Footer~ object so
|
2713
|
+
constructed. It can be used to access the values and other attributes of the
|
2714
|
+
footer computed. Their signatures are:
|
2715
|
+
|
2716
|
+
- ~foot(label: label, label_col: nil, **agg_cols)~ :: where ~label~ is a label
|
2717
|
+
to be placed in the column with header ~label_col~, or, if ommitted, in the
|
2718
|
+
first cell of the footer (unless that column is named as one of the
|
2719
|
+
~agg_cols~, in which case the label is ignored), and ~**agg_cols~ is zero or
|
2720
|
+
more hash-like parameters with a column symbol as a key and a valid
|
2721
|
+
aggregate as the value. This causes a table-wide header to be added at the
|
2722
|
+
bottom of the table applying ~agg~, to the ~agg_cols~. A table can have any
|
2723
|
+
number of footers attached, and they will appear at the bottom of the output
|
2724
|
+
table in the order they are given.
|
2725
|
+
|
2726
|
+
- ~gfoot(label: 'Group Total', label_col: nil, **agg_cols)~ :: where the
|
2727
|
+
parameters have the same meaning as for the ~foot~ method, but results in a
|
2728
|
+
footer for each group in the table rather than the table as a whole. These
|
2729
|
+
will appear in the output table just below each group.
|
2715
2730
|
|
2716
2731
|
- ~footer(label, *sum_cols, **agg_cols)~ :: where ~label~ is a label to be
|
2717
2732
|
placed in the first cell of the footer (unless that column is named as one
|
@@ -2724,26 +2739,11 @@ computed. Their signatures are:
|
|
2724
2739
|
number of footers attached, and they will appear at the bottom of the output
|
2725
2740
|
table in the order they are given.
|
2726
2741
|
|
2727
|
-
- ~foot(label, label_col, **agg_cols)~ :: where ~label~ is a label to be
|
2728
|
-
placed in the column with header ~label_col~, or, if ommitted, in the first
|
2729
|
-
cell of the footer (unless that column is named as one of the ~agg_cols~, in
|
2730
|
-
which case the label is ignored), and ~**agg_cols~ is zero or more hash-like
|
2731
|
-
parameters with a column symbol as a key and a valid aggregate as the
|
2732
|
-
value. This causes a table-wide header to be added at the bottom of the
|
2733
|
-
table applying ~agg~, to the ~agg_cols~. A table can have any number of
|
2734
|
-
footers attached, and they will appear at the bottom of the output table in
|
2735
|
-
the order they are given.
|
2736
|
-
|
2737
2742
|
- ~gfooter(label, *sum_cols, **agg_cols)~ :: where the parameters have the
|
2738
2743
|
same meaning as for the ~footer~ method, but results in a footer for each
|
2739
2744
|
group in the table rather than the table as a whole. These will appear in
|
2740
2745
|
the output table just below each group.
|
2741
2746
|
|
2742
|
-
- ~gfoot(label, label_col, **agg_cols)~ :: where the parameters have the same
|
2743
|
-
meaning as for the ~foot~ method, but results in a footer for each group in
|
2744
|
-
the table rather than the table as a whole. These will appear in the output
|
2745
|
-
table just below each group.
|
2746
|
-
|
2747
2747
|
There are also a number of convenience methods for adding common footers:
|
2748
2748
|
- ~sum_footer(*cols)~ :: Add a footer summing the given columns with the label
|
2749
2749
|
'Total'.
|
@@ -2762,6 +2762,39 @@ There are also a number of convenience methods for adding common footers:
|
|
2762
2762
|
- ~max_gfooter(*cols)~ :: Add a group footer showing the maximum for the given
|
2763
2763
|
columns with the label 'Group Maximum'.
|
2764
2764
|
|
2765
|
+
**** Dynamic Labels
|
2766
|
+
Most of the time, you will want a fixed string as the label. However,
|
2767
|
+
especially in the case of a group footer, you might want a dynamically
|
2768
|
+
contructed label. You can use a proc or lambda for a label, and it will be
|
2769
|
+
computed for you. In the case of non-group footers, the proc takes a single
|
2770
|
+
parameter, the footer object itself. This allows you to make the label a
|
2771
|
+
function of other footer values, for example, you could make the label
|
2772
|
+
include the most recent year from the date column:
|
2773
|
+
|
2774
|
+
#+begin_src ruby
|
2775
|
+
fmtr.foot(label: -> (f) { "Average (latest year #{f.column(:date).max.year})" },
|
2776
|
+
temp: :avg)
|
2777
|
+
#+end_src
|
2778
|
+
|
2779
|
+
In the case of a group footer, the lambda or proc may take either one or qtwo parameters.
|
2780
|
+
If it takes one, the parameter is simply the 0-based number of the group:
|
2781
|
+
|
2782
|
+
#+begin_src ruby
|
2783
|
+
fmtr.gfoot(label: -> (k) { "Group #{(k+1).to_roman} Average" }, temp: :avg)
|
2784
|
+
#+end_src
|
2785
|
+
This would format the label with a roman numeral (assuming you defined a
|
2786
|
+
method to do so) for the group number.
|
2787
|
+
|
2788
|
+
If it takes two arguments, the second argument is the footer itself, as with
|
2789
|
+
non-group footers:
|
2790
|
+
|
2791
|
+
#+begin_src ruby
|
2792
|
+
fmtr.gfoot(label: -> (k, f) { "Year #{f.column(:date, k).max.year} Group #{(k+1).to_roman} Average" },
|
2793
|
+
temp: :avg)
|
2794
|
+
#+end_src
|
2795
|
+
This would add the group's year to label, assuming the :date column of the
|
2796
|
+
footer's table had the same year for each item in the group.
|
2797
|
+
|
2765
2798
|
**** Aggregators
|
2766
2799
|
When adding a footer with the above methods, you can specify an aggregator for
|
2767
2800
|
each column named in the ~agg_cols~ parameter. There are several candidates
|
@@ -2778,6 +2811,9 @@ for what you can use for an aggregator:
|
|
2778
2811
|
In the case of datetime columns, these aggrgators convert the dates to
|
2779
2812
|
julian date numbers, perform the calculation, then convert the result back
|
2780
2813
|
to a datetime object.
|
2814
|
+
Apart from the built-in aggrgators, you could define your own by opening the
|
2815
|
+
FatTable::Column class and adding a suitable instance method. In that
|
2816
|
+
case, the symbol could also refer to the method you defined.
|
2781
2817
|
- String :: using a string as an aggrgegator can result in:
|
2782
2818
|
+ the string being converted to an object matching the type of the column
|
2783
2819
|
(for example, using '$1,888' in a numeric column puts the constant number
|
@@ -2792,11 +2828,16 @@ for what you can use for an aggregator:
|
|
2792
2828
|
- A Lambda :: finally, you can provide a lambda for performing arbitrary
|
2793
2829
|
calculations and placing the result in the footer field. The number of
|
2794
2830
|
arguments the lambda takes can vary:
|
2795
|
-
* If the lambda is used in
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2831
|
+
* If the lambda is used in an ordinary footer column, it can take 0, 1, or 2
|
2832
|
+
arguments: (1) the first argument, if given, will be set to the
|
2833
|
+
FatTable::Column object for that column and (2) the second argument, if
|
2834
|
+
given, will be set to the Footer object itself.
|
2835
|
+
* If the lambda is used in a group footer column, it can 0, 1, 2, or 3
|
2836
|
+
arguments: (1) the first argument, if given, will be set to the group's
|
2837
|
+
0-based index number, (2) the second argument, if given, will be set to a
|
2838
|
+
FatTable::Column object consisting of those items in the group's column,
|
2839
|
+
and (3) the third argument, if given, will be set to the Footer object
|
2840
|
+
itself.
|
2800
2841
|
|
2801
2842
|
**** Footer objects
|
2802
2843
|
Each of the methods for adding a footer to a ~Formatter~ returns a ~Footer~ object
|
@@ -2820,7 +2861,6 @@ their computed values. Here are the accessors available on a
|
|
2820
2861
|
to the footer value for that column, nil for unused columns. Use the index
|
2821
2862
|
~k~ to specify which group to access in the case of a group footer.
|
2822
2863
|
|
2823
|
-
|
2824
2864
|
**** Footer Examples
|
2825
2865
|
As a reminder, here is the table, ~tab_a~ defined earlier:
|
2826
2866
|
|
@@ -2981,18 +3021,20 @@ But it can be any type. Here we pick a lottery winner from the employee ids.
|
|
2981
3021
|
#+end_EXAMPLE
|
2982
3022
|
|
2983
3023
|
***** Lambdas
|
2984
|
-
Perhaps the most flexible form of aggregator is a lambda form. They
|
2985
|
-
or 3 parameters in non-group and group footers, respectively:
|
2986
|
-
|
2987
|
-
- ~->(
|
2988
|
-
paramters: the first, ~
|
2989
|
-
|
2990
|
-
lambda
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
3024
|
+
Perhaps the most flexible form of aggregator is a lambda form. They can take
|
3025
|
+
up to 2 or up to 3 parameters in non-group and group footers, respectively:
|
3026
|
+
|
3027
|
+
- ~->(c, f) {...}~ :: in a normal, non-group footer, you may provide for up to
|
3028
|
+
two paramters: the first, ~c~, if given, will be bound to the column header
|
3029
|
+
to which the lambda is attached and and the second, ~f~, if given will be
|
3030
|
+
bound to the footer in which the lambda appears. A lambda with no
|
3031
|
+
parameters can be provided as well if none are needed.
|
3032
|
+
- ~->(k, c, f)~ :: in a group footer, you may provide for up to three
|
3033
|
+
paramters: the the first, ~k~, if provided, will be bound to the group
|
3034
|
+
number of the group being evaluated, the second, ~c~, if provided, will be
|
3035
|
+
bound to the column header to which the lambda is attached, and the third,
|
3036
|
+
~f~, will be bound to the footer in which the lambda appears. A lambda with
|
3037
|
+
no parameters can be provided as well if none are needed.
|
2996
3038
|
|
2997
3039
|
With the first argument, the footer itself becomes available and with it all
|
2998
3040
|
the things accessible with the footers, including the items in the current
|
@@ -3003,7 +3045,7 @@ Compute the summ of the squares if the items in the ~:age~ column:
|
|
3003
3045
|
tab_a.to_text do |f|
|
3004
3046
|
f.format(numeric: '0.0R,', datetime: 'd[%v]D[%v]')
|
3005
3047
|
f.footer('Average', age: :avg, salary: :avg, join_date: :avg)
|
3006
|
-
f.footer('SSQ', age: ->(
|
3048
|
+
f.footer('SSQ', age: ->(c) { sa = c.items.map {|x| x * x}.sum; Math.sqrt(sa) })
|
3007
3049
|
end
|
3008
3050
|
#+END_SRC
|
3009
3051
|
|
@@ -3032,8 +3074,8 @@ summ of the squares if the ages in each group:
|
|
3032
3074
|
tab_a.order_with('join_date.year').to_text do |f|
|
3033
3075
|
f.format(numeric: '0.0R,', datetime: 'd[%v]D[%v]', sort_key: '0.0~,')
|
3034
3076
|
f.footer('Average', age: :avg, salary: :avg, join_date: :avg)
|
3035
|
-
f.gfooter('Group SSQ', age: ->(
|
3036
|
-
f.footer('Total SSQ', age: ->(
|
3077
|
+
f.gfooter('Group SSQ', age: ->(k, c, f) { sa = c.items.map {|x| x * x}.sum; Math.sqrt(sa) })
|
3078
|
+
f.footer('Total SSQ', age: ->(c, f) { sa = c.items.map {|x| x * x}.sum; Math.sqrt(sa) })
|
3037
3079
|
end
|
3038
3080
|
#+END_SRC
|
3039
3081
|
|
@@ -3045,19 +3087,19 @@ summ of the squares if the ages in each group:
|
|
3045
3087
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3046
3088
|
| Group SSQ | | 45 | | | | |
|
3047
3089
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3048
|
-
| 1 | Paul | 32 | California | 20,000 | 13-JUL-2001 |
|
3090
|
+
| 1 | Paul | 32 | California | 20,000 | 13-JUL-2001 | 2001 |
|
3049
3091
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3050
3092
|
| Group SSQ | | 32 | | | | |
|
3051
3093
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3052
|
-
| 2 | Allen | 25 | Texas | | 13-JUL-2005 |
|
3053
|
-
| 8 | Paul | 24 | Houston | 20,000 | 13-JUL-2005 |
|
3054
|
-
| 9 | James | 44 | Norway | 5,000 | 13-JUL-2005 |
|
3094
|
+
| 2 | Allen | 25 | Texas | | 13-JUL-2005 | 2005 |
|
3095
|
+
| 8 | Paul | 24 | Houston | 20,000 | 13-JUL-2005 | 2005 |
|
3096
|
+
| 9 | James | 44 | Norway | 5,000 | 13-JUL-2005 | 2005 |
|
3055
3097
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3056
3098
|
| Group SSQ | | 56 | | | | |
|
3057
3099
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3058
|
-
| 3 | Teddy | 23 | Norway | 20,000 | 13-DEC-2007 |
|
3059
|
-
| 4 | Mark | 25 | Rich-Mond | 65,000 | 13-DEC-2007 |
|
3060
|
-
| 5 | David | 27 | Texas | 85,000 | 13-DEC-2007 |
|
3100
|
+
| 3 | Teddy | 23 | Norway | 20,000 | 13-DEC-2007 | 2007 |
|
3101
|
+
| 4 | Mark | 25 | Rich-Mond | 65,000 | 13-DEC-2007 | 2007 |
|
3102
|
+
| 5 | David | 27 | Texas | 85,000 | 13-DEC-2007 | 2007 |
|
3061
3103
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
3062
3104
|
| Group SSQ | | 43 | | | | |
|
3063
3105
|
+-----------+-------+-----+------------+--------+-------------+----------+
|
data/lib/fat_table/footer.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module FatTable
|
4
4
|
class Footer
|
5
|
-
attr_reader :table, :
|
5
|
+
attr_reader :table, :label_col, :values, :group
|
6
6
|
|
7
7
|
###########################################################################
|
8
8
|
# Constructors
|
@@ -15,6 +15,7 @@ module FatTable
|
|
15
15
|
# for the footer are added later with the #add_value method.
|
16
16
|
def initialize(label = 'Total', table, label_col: nil, group: false)
|
17
17
|
@label = label
|
18
|
+
|
18
19
|
unless table.is_a?(Table)
|
19
20
|
raise ArgumentError, 'Footer.new needs a table argument'
|
20
21
|
end
|
@@ -30,14 +31,7 @@ module FatTable
|
|
30
31
|
@group = group
|
31
32
|
@group_cols = {}
|
32
33
|
@values = {}
|
33
|
-
|
34
|
-
@values[@label_col] = []
|
35
|
-
table.number_of_groups.times do
|
36
|
-
@values[@label_col] << @label
|
37
|
-
end
|
38
|
-
else
|
39
|
-
@values[@label_col] = [@label]
|
40
|
-
end
|
34
|
+
insert_labels_in_label_col
|
41
35
|
make_accessor_methods
|
42
36
|
end
|
43
37
|
|
@@ -71,6 +65,11 @@ module FatTable
|
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
68
|
+
# Return the value of the label, for the kth group if grouped.
|
69
|
+
def label(k = 0)
|
70
|
+
calc_label(k)
|
71
|
+
end
|
72
|
+
|
74
73
|
# :category: Accessors
|
75
74
|
|
76
75
|
# Return the value of under the +key+ header, or if this is a group
|
@@ -108,8 +107,10 @@ module FatTable
|
|
108
107
|
if group && k.nil?
|
109
108
|
raise ArgumentError, 'Footer#column(h, k) missing the group number argument k'
|
110
109
|
end
|
110
|
+
|
111
111
|
if group
|
112
|
-
|
112
|
+
@group_cols[h] ||= table.group_cols(h)
|
113
|
+
@group_cols[h][k]
|
113
114
|
else
|
114
115
|
table.column(h)
|
115
116
|
end
|
@@ -151,14 +152,13 @@ module FatTable
|
|
151
152
|
|
152
153
|
# Evaluate the given agg for the header col and, in the case of a group
|
153
154
|
# footer, the group k.
|
154
|
-
def calc_val(agg,
|
155
|
-
column =
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
155
|
+
def calc_val(agg, h, k = nil)
|
156
|
+
column = column(h, k)
|
157
|
+
|
158
|
+
# Convert Date and Time objects to DateTime
|
159
|
+
if [Date, Time].include?(agg.class)
|
160
|
+
agg = agg.to_datetime
|
161
|
+
end
|
162
162
|
|
163
163
|
case agg
|
164
164
|
when Symbol
|
@@ -179,29 +179,69 @@ module FatTable
|
|
179
179
|
when Proc
|
180
180
|
result =
|
181
181
|
if group
|
182
|
-
|
183
|
-
|
182
|
+
case agg.arity
|
183
|
+
when 0
|
184
|
+
agg.call
|
185
|
+
when 1
|
186
|
+
agg.call(k)
|
187
|
+
when 2
|
188
|
+
agg.call(k, column)
|
189
|
+
when 3
|
190
|
+
agg.call(k, column, self)
|
191
|
+
else
|
192
|
+
msg = 'a lambda used in a group footer may have 0 to 3 three arguments: (k, c, f)'
|
184
193
|
raise ArgumentError, msg
|
185
194
|
end
|
186
|
-
agg.call(self, col, k)
|
187
195
|
else
|
188
|
-
|
189
|
-
|
196
|
+
case agg.arity
|
197
|
+
when 0
|
198
|
+
agg.call
|
199
|
+
when 1
|
200
|
+
agg.call(column)
|
201
|
+
when 2
|
202
|
+
agg.call(column, self)
|
203
|
+
else
|
204
|
+
msg = 'a lambda used in a non-group footer may have 0 to 2 arguments: (c, f)'
|
190
205
|
raise ArgumentError, msg
|
191
206
|
end
|
192
|
-
agg.call(self, col)
|
193
207
|
end
|
194
|
-
#
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
208
|
+
# Pass the result back into this method as the new agg
|
209
|
+
calc_val(result, h, k)
|
210
|
+
else
|
211
|
+
agg.to_s
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Insert a possibly calculated value for the label in the appropriate
|
216
|
+
# @values column.
|
217
|
+
def insert_labels_in_label_col
|
218
|
+
if group
|
219
|
+
@values[@label_col] = []
|
220
|
+
table.number_of_groups.times do |k|
|
221
|
+
@values[@label_col] << calc_label(k)
|
222
|
+
end
|
223
|
+
else
|
224
|
+
@values[@label_col] = [calc_label(0)]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Calculate the label for the kth group, using k = 0 for non-group
|
229
|
+
# footers. If the label is a proc, call it with the group number.
|
230
|
+
def calc_label(k)
|
231
|
+
case @label
|
232
|
+
when Proc
|
233
|
+
case @label.arity
|
234
|
+
when 0
|
235
|
+
@label.call
|
236
|
+
when 1
|
237
|
+
@label.call(k)
|
238
|
+
when 2
|
239
|
+
@label.call(k, self)
|
200
240
|
else
|
201
|
-
raise ArgumentError, "
|
241
|
+
raise ArgumentError, "footer label proc may only have 1 argument for group number k"
|
202
242
|
end
|
203
243
|
else
|
204
|
-
|
244
|
+
@label.to_s
|
205
245
|
end
|
206
246
|
end
|
207
247
|
|
@@ -181,41 +181,74 @@ module FatTable
|
|
181
181
|
end
|
182
182
|
|
183
183
|
# :category: Add Footers
|
184
|
-
|
185
|
-
# A simpler method for adding a footer to the formatted output having the
|
186
|
-
# label +label+ placed in the column with the header +label_col+ or in the
|
187
|
-
# first column if +label_col+ is ommitted. The remaining hash arguments
|
188
|
-
# apply an aggregate to the values of the column, which can be:
|
189
|
-
#
|
190
|
-
# (1) a symbol representing one of the builtin aggregates, i.e., :first,
|
191
|
-
# :last, :range, :sum, :count, :min, :max, :avg, :var, :pvar, :dev, :pdev,
|
192
|
-
# :any?, :all?, :none?, and :one?,
|
193
184
|
#
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
185
|
+
# A keyword method for adding a footer to the formatted output having the
|
186
|
+
# label +label:+ (default 'Total') placed in the column with the header
|
187
|
+
# +label_col:+ or in the first column if +label_col+ is ommitted.
|
188
|
+
# This assigns a fixed group label to be placed in the :date column:
|
189
|
+
# #+begin_src ruby
|
190
|
+
# fmtr.foot(label: "Year's Average", label_col: :date, temp: avg)
|
191
|
+
# #+end_src
|
192
|
+
#
|
193
|
+
# Besides being a fixed string, the +label:+ can also be a proc or lambda
|
194
|
+
# taking one argument, the foooter itself.
|
195
|
+
# Thus, a label such as:
|
196
|
+
#
|
197
|
+
# #+begin_src ruby
|
198
|
+
# fmtr.foot(label: -> (f) { "Average (latest year #{f.column(:date).max.year})" },
|
199
|
+
# temp: :avg)
|
200
|
+
# #+end_src
|
201
|
+
# And this would add the highest number to label, assuming the :date column
|
202
|
+
# of the footer's table had the year for each item.
|
203
|
+
#
|
204
|
+
# The remaining hash arguments apply an aggregate to the values of the
|
205
|
+
# column, which can be:
|
206
|
+
#
|
207
|
+
# 1. a symbol representing one of the builtin aggregates, i.e., :first,
|
208
|
+
# :last, :range, :sum, :count, :min, :max, :avg, :var, :pvar, :dev,
|
209
|
+
# :pdev, :any?, :all?, :none?, and :one?, or a symbol for your own
|
210
|
+
# aggregate defined as an instance method on FatTable::Column.
|
211
|
+
# 2. a fixed string, but it the string can be converted into the Column's
|
212
|
+
# type, it will be converted, so the string '3.14159' will be converted
|
213
|
+
# to 3.14159 in a Numeric column.
|
214
|
+
# 3. a value of the Column's type, so Date.today would simply be evaluated
|
215
|
+
# for a Numeric column.
|
216
|
+
# 4. most flexibly of all, a proc or lambda taking arguments: f, the
|
217
|
+
# footer object itself; c, the column (or in the case of a group
|
218
|
+
# footer, the sub-column) corresponding to the current header, and in
|
219
|
+
# the case of a group footer, k, the number of the group (0-based).
|
220
|
+
# 5. Any other value is converted to a string with #to_s.
|
198
221
|
#
|
199
222
|
# Examples:
|
200
223
|
#
|
201
224
|
# Put the label in the :dickens column of the footer and the maximum value
|
202
225
|
# from the :alpha column in the :alpha column of the footer.
|
203
226
|
#
|
204
|
-
# fmtr.foot('Best', :dickens, alpha: :max)
|
227
|
+
# fmtr.foot(label: 'Best', label_col: :dickens, alpha: :max)
|
205
228
|
#
|
206
229
|
# Put the label 'Today' in the first column of the footer and today's date
|
207
230
|
# in the :beta column.
|
208
231
|
#
|
209
|
-
# fmtr.foot('Today', beta: Date.today)
|
232
|
+
# fmtr.foot(label: 'Today', beta: Date.today)
|
210
233
|
#
|
211
234
|
# Put the label 'Best' in the :dickens column of the footer and the string
|
212
235
|
# 'Tale of Two Cities' in the :alpha column of the footer. Since it can't
|
213
236
|
# be interpreted as Boolean, Numeric, or DateTime, it is placed in the
|
214
237
|
# footer literally.
|
215
238
|
#
|
216
|
-
# fmtr.foot('Best', :dickens, alpha: 'A Tale of Two
|
239
|
+
# fmtr.foot(label: 'Best', label_col: :dickens, alpha: 'A Tale of Two
|
240
|
+
# Cities')
|
241
|
+
#
|
242
|
+
# Use a lambda to calculate the value to be placed in the column :gamma.
|
243
|
+
#
|
244
|
+
# fmtr.foot(label: 'Gamma', beta: :avg, gamma: ->(f, c) {
|
245
|
+
# (Math.gamma(c.count) + f[:beta] } )
|
217
246
|
#
|
218
|
-
|
247
|
+
# Note that this way a footer can be made a function of the other footer
|
248
|
+
# values (using f[:other_col]) as well as the Column object corresponding
|
249
|
+
# to the lamda's column.
|
250
|
+
#
|
251
|
+
def foot(label: 'Total', label_col: nil, **agg_cols)
|
219
252
|
foot = Footer.new(label, table, label_col: label_col)
|
220
253
|
agg_cols.each_pair do |h, agg|
|
221
254
|
foot.add_value(h, agg)
|
@@ -255,9 +288,92 @@ module FatTable
|
|
255
288
|
foot
|
256
289
|
end
|
257
290
|
|
258
|
-
# Add
|
259
|
-
#
|
260
|
-
|
291
|
+
# :category: Add Footers
|
292
|
+
#
|
293
|
+
# A keyword method for adding a group footer to the formatted output
|
294
|
+
# having the label +label:+ (default 'Total') placed in the column with
|
295
|
+
# the header +label_col:+ or in the first column if +label_col+ is
|
296
|
+
# ommitted.
|
297
|
+
#
|
298
|
+
# This assigns a fixed group label to be placed in the :date column:
|
299
|
+
# #+begin_src ruby
|
300
|
+
# fmtr.gfoot(label: "Year's Average", label_col: :date, temp: avg)
|
301
|
+
# #+end_src
|
302
|
+
#
|
303
|
+
# Besides being a fixed string, the +label:+ can also be a proc or lambda
|
304
|
+
# taking one or two arguments. In the one argument form, the argument is
|
305
|
+
# the group number k. If a second argument is specified, the foooter
|
306
|
+
# itself is passed as the argument. Thus, a label such as:
|
307
|
+
#
|
308
|
+
# #+begin_src ruby
|
309
|
+
# fmtr.gfoot(label: -> (k) { "Group #{(k+1).to_roman} Average" }, temp: :avg)
|
310
|
+
# #+end_src
|
311
|
+
# This would format the label with a roman numeral (assuming you defined a
|
312
|
+
# method to do so) for the group number.
|
313
|
+
#
|
314
|
+
# #+begin_src ruby
|
315
|
+
# fmtr.gfoot(label: -> (k, f) { "Year #{f.column(:date, k).max.year} Group #{(k+1).to_roman} Average" },
|
316
|
+
# temp: :avg)
|
317
|
+
# #+end_src
|
318
|
+
# And this would add the group's year to label, assuming the :date column
|
319
|
+
# of the footer's table had the same year for each item in the group.
|
320
|
+
#
|
321
|
+
#
|
322
|
+
# The remaining hash arguments apply an aggregate to the values
|
323
|
+
# of the column, which can be:
|
324
|
+
#
|
325
|
+
# 1. a symbol representing one of the builtin aggregates, i.e., :first,
|
326
|
+
# :last, :range, :sum, :count, :min, :max, :avg, :var, :pvar, :dev,
|
327
|
+
# :pdev, :any?, :all?, :none?, and :one?, or a symbol for your own
|
328
|
+
# aggregate defined as an instance method on FatTable::Column.
|
329
|
+
# 2. a fixed string, but it the string can be converted into the Column's
|
330
|
+
# type, it will be converted, so the string '3.14159' will be converted
|
331
|
+
# to 3.14159 in a Numeric column.
|
332
|
+
# 3. a value of the Column's type, so Date.today would simply be evaluated
|
333
|
+
# for a Numeric column.
|
334
|
+
# 4. most flexibly of all, a proc or lambda taking arguments: f, the
|
335
|
+
# footer object itself; c, the column (or in the case of a group
|
336
|
+
# footer, the sub-column) corresponding to the current header, and k,
|
337
|
+
# this group's group number (0-based).
|
338
|
+
# 5. Any other value is converted to a string with #to_s.
|
339
|
+
#
|
340
|
+
# Examples:
|
341
|
+
#
|
342
|
+
# Put the label in the :dickens column of the footer and the maximum value
|
343
|
+
# from the :alpha column in the :alpha column of the footer.
|
344
|
+
#
|
345
|
+
# #+begin_src ruby
|
346
|
+
# fmtr.gfoot(label: 'Best', label_col: :dickens, alpha: :max)
|
347
|
+
# #+end_src
|
348
|
+
#
|
349
|
+
# Put the label 'Today' in the first column of the footer and today's date
|
350
|
+
# in the :beta column.
|
351
|
+
#
|
352
|
+
# #+begin_src ruby
|
353
|
+
# fmtr.gfoot(label: 'Today', beta: Date.today)
|
354
|
+
# #+end_src
|
355
|
+
#
|
356
|
+
# Put the label 'Best' in the :dickens column of the footer and the string
|
357
|
+
# 'Tale of Two Cities' in the :alpha column of the footer. Since it can't
|
358
|
+
# be interpreted as Boolean, Numeric, or DateTime, it is placed in the
|
359
|
+
# footer literally.
|
360
|
+
#
|
361
|
+
# #+begin_src ruby
|
362
|
+
# fmtr.gfoot(label: 'Best', label_col: :dickens, alpha: 'A Tale of Two
|
363
|
+
# Cities')
|
364
|
+
# #+end_src
|
365
|
+
#
|
366
|
+
# Use a lambda to calculate the value to be placed in the column :gamma.
|
367
|
+
#
|
368
|
+
# #+begin_src ruby
|
369
|
+
# fmtr.gfoot(label: 'Gamma', beta: :avg, gamma: ->(f, c) {
|
370
|
+
# (Math.gamma(c.count) + f[:beta] } )
|
371
|
+
# #+end_src
|
372
|
+
#
|
373
|
+
# Note that this way a footer can be made a function of the other footer
|
374
|
+
# values (using f[:other_col]) as well as the Column object corresponding
|
375
|
+
# to the lamda's column.
|
376
|
+
def gfoot(label: 'Group Total', label_col: nil, **agg_cols)
|
261
377
|
foot = Footer.new(label, table, label_col: label_col, group: true)
|
262
378
|
agg_cols.each_pair do |h, agg|
|
263
379
|
foot.add_value(h, agg)
|
data/lib/fat_table/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fat_table
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel E. Doherty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|