File Coverage

blib/lib/App/CSVUtils/csv_avg.pm
Criterion Covered Total %
statement 14 14 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 19 19 100.0


line stmt bran cond sub pod time code
1             package App::CSVUtils::csv_avg;
2              
3 1     1   4481 use 5.010001;
  1         4  
4 1     1   5 use strict;
  1         2  
  1         22  
5 1     1   5 use warnings;
  1         5  
  1         88  
6              
7             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
8             our $DATE = '2023-04-01'; # DATE
9             our $DIST = 'App-CSVUtils'; # DIST
10             our $VERSION = '1.024'; # VERSION
11              
12 1         186 use App::CSVUtils qw(
13             gen_csv_util
14 1     1   6 );
  1         2  
15              
16             gen_csv_util(
17             name => 'csv_avg',
18             summary => 'Output a summary row which are arithmetic averages of data rows',
19             description => <<'_',
20              
21             Non-numbers will be assumed to be 0.
22              
23             Example:
24              
25             # students.csv
26             name,age
27             andi,13
28             budi,12
29             chandra,12
30             dudi,12
31              
32             % csv-avg students.csv
33             name,age
34             0,12.25
35              
36             % csv-avg students.csv --with-data-row
37             name,age
38             andi,13
39             budi,12
40             chandra,12
41             dudi,12
42             0,12.25
43              
44             _
45             add_args => {
46             %App::CSVUtils::argspecopt_with_data_rows,
47             },
48             tags => ['add-row','category:summarizing'],
49              
50             on_input_header_row => sub {
51             my $r = shift;
52              
53             # we add this key to the stash
54             $r->{summary_row} = [map {0} @{$r->{input_fields}}];
55             $r->{row_count} = 0;
56              
57             # because input_* will be cleared by the time of after_read_input,
58             # we save and set it now
59             $r->{output_fields} = $r->{input_fields};
60             },
61              
62             on_input_data_row => sub {
63             my $r = shift;
64              
65             for my $j (0 .. $#{ $r->{input_fields} }) {
66 1     1   7 no warnings 'numeric', 'uninitialized';
  1         2  
  1         212  
67             $r->{summary_row}[$j] += $r->{input_row}[$j]+0;
68             }
69             $r->{code_print_row}->($r->{input_row}) if $r->{util_args}{with_data_rows};
70             $r->{row_count}++;
71             },
72              
73             after_read_input => sub {
74             my $r = shift;
75              
76             if ($r->{row_count} > 0) {
77             for my $j (0 .. $#{ $r->{output_fields} }) {
78             $r->{summary_row}[$j] /= $r->{row_count};
79             }
80             }
81             $r->{code_print_row}->($r->{summary_row});
82             },
83             );
84              
85             1;
86             # ABSTRACT: Output a summary row which are arithmetic averages of data rows
87              
88             __END__
89              
90             =pod
91              
92             =encoding UTF-8
93              
94             =head1 NAME
95              
96             App::CSVUtils::csv_avg - Output a summary row which are arithmetic averages of data rows
97              
98             =head1 VERSION
99              
100             This document describes version 1.024 of App::CSVUtils::csv_avg (from Perl distribution App-CSVUtils), released on 2023-04-01.
101              
102             =head1 FUNCTIONS
103              
104              
105             =head2 csv_avg
106              
107             Usage:
108              
109             csv_avg(%args) -> [$status_code, $reason, $payload, \%result_meta]
110              
111             Output a summary row which are arithmetic averages of data rows.
112              
113             Non-numbers will be assumed to be 0.
114              
115             Example:
116              
117             # students.csv
118             name,age
119             andi,13
120             budi,12
121             chandra,12
122             dudi,12
123            
124             % csv-avg students.csv
125             name,age
126             0,12.25
127            
128             % csv-avg students.csv --with-data-row
129             name,age
130             andi,13
131             budi,12
132             chandra,12
133             dudi,12
134             0,12.25
135              
136             This function is not exported.
137              
138             Arguments ('*' denotes required arguments):
139              
140             =over 4
141              
142             =item * B<inplace> => I<true>
143              
144             Output to the same file as input.
145              
146             Normally, you output to a different file than input. If you try to output to the
147             same file (C<-o INPUT.csv -O>) you will clobber the input file; thus the utility
148             prevents you from doing it. However, with this C<--inplace> option, you can
149             output to the same file. Like perl's C<-i> option, this will first output to a
150             temporary file in the same directory as the input file then rename to the final
151             file at the end. You cannot specify output file (C<-o>) when using this option,
152             but you can specify backup extension with C<-b> option.
153              
154             Some caveats:
155              
156             =over
157              
158             =item * if input file is a symbolic link, it will be replaced with a regular file;
159              
160             =item * renaming (implemented using C<rename()>) can fail if input filename is too long;
161              
162             =item * value specified in C<-b> is currently not checked for acceptable characters;
163              
164             =item * things can also fail if permissions are restrictive;
165              
166             =back
167              
168             =item * B<inplace_backup_ext> => I<str> (default: "")
169              
170             Extension to add for backup of input file.
171              
172             In inplace mode (C<--inplace>), if this option is set to a non-empty string, will
173             rename the input file using this extension as a backup. The old existing backup
174             will be overwritten, if any.
175              
176             =item * B<input_escape_char> => I<str>
177              
178             Specify character to escape value in field in input CSV, will be passed to Text::CSV_XS.
179              
180             Defaults to C<\\> (backslash). Overrides C<--input-tsv> option.
181              
182             =item * B<input_filename> => I<filename> (default: "-")
183              
184             Input CSV file.
185              
186             Use C<-> to read from stdin.
187              
188             Encoding of input file is assumed to be UTF-8.
189              
190             =item * B<input_header> => I<bool> (default: 1)
191              
192             Specify whether input CSV has a header row.
193              
194             By default, the first row of the input CSV will be assumed to contain field
195             names (and the second row contains the first data row). When you declare that
196             input CSV does not have header row (C<--no-input-header>), the first row of the
197             CSV is assumed to contain the first data row. Fields will be named C<field1>,
198             C<field2>, and so on.
199              
200             =item * B<input_quote_char> => I<str>
201              
202             Specify field quote character in input CSV, will be passed to Text::CSV_XS.
203              
204             Defaults to C<"> (double quote). Overrides C<--input-tsv> option.
205              
206             =item * B<input_sep_char> => I<str>
207              
208             Specify field separator character in input CSV, will be passed to Text::CSV_XS.
209              
210             Defaults to C<,> (comma). Overrides C<--input-tsv> option.
211              
212             =item * B<input_tsv> => I<true>
213              
214             Inform that input file is in TSV (tab-separated) format instead of CSV.
215              
216             Overriden by C<--input-sep-char>, C<--input-quote-char>, C<--input-escape-char>
217             options. If one of those options is specified, then C<--input-tsv> will be
218             ignored.
219              
220             =item * B<output_always_quote> => I<bool> (default: 0)
221              
222             Whether to always quote values.
223              
224             When set to false (the default), values are quoted only when necessary:
225              
226             field1,field2,"field three contains comma (,)",field4
227              
228             When set to true, then all values will be quoted:
229              
230             "field1","field2","field three contains comma (,)","field4"
231              
232             =item * B<output_escape_char> => I<str>
233              
234             Specify character to escape value in field in output CSV, will be passed to Text::CSV_XS.
235              
236             This is like C<--input-escape-char> option but for output instead of input.
237              
238             Defaults to C<\\> (backslash). Overrides C<--output-tsv> option.
239              
240             =item * B<output_filename> => I<filename>
241              
242             Output filename.
243              
244             Use C<-> to output to stdout (the default if you don't specify this option).
245              
246             Encoding of output file is assumed to be UTF-8.
247              
248             =item * B<output_header> => I<bool>
249              
250             Whether output CSV should have a header row.
251              
252             By default, a header row will be output I<if> input CSV has header row. Under
253             C<--output-header>, a header row will be output even if input CSV does not have
254             header row (value will be something like "col0,col1,..."). Under
255             C<--no-output-header>, header row will I<not> be printed even if input CSV has
256             header row. So this option can be used to unconditionally add or remove header
257             row.
258              
259             =item * B<output_quote_char> => I<str>
260              
261             Specify field quote character in output CSV, will be passed to Text::CSV_XS.
262              
263             This is like C<--input-quote-char> option but for output instead of input.
264              
265             Defaults to C<"> (double quote). Overrides C<--output-tsv> option.
266              
267             =item * B<output_quote_empty> => I<bool> (default: 0)
268              
269             Whether to quote empty values.
270              
271             When set to false (the default), empty values are not quoted:
272              
273             field1,field2,,field4
274              
275             When set to true, then empty values will be quoted:
276              
277             field1,field2,"",field4
278              
279             =item * B<output_sep_char> => I<str>
280              
281             Specify field separator character in output CSV, will be passed to Text::CSV_XS.
282              
283             This is like C<--input-sep-char> option but for output instead of input.
284              
285             Defaults to C<,> (comma). Overrides C<--output-tsv> option.
286              
287             =item * B<output_tsv> => I<bool>
288              
289             Inform that output file is TSV (tab-separated) format instead of CSV.
290              
291             This is like C<--input-tsv> option but for output instead of input.
292              
293             Overriden by C<--output-sep-char>, C<--output-quote-char>, C<--output-escape-char>
294             options. If one of those options is specified, then C<--output-tsv> will be
295             ignored.
296              
297             =item * B<overwrite> => I<bool>
298              
299             Whether to override existing output file.
300              
301             =item * B<with_data_rows> => I<bool>
302              
303             Whether to also output data rows.
304              
305              
306             =back
307              
308             Returns an enveloped result (an array).
309              
310             First element ($status_code) is an integer containing HTTP-like status code
311             (200 means OK, 4xx caller error, 5xx function error). Second element
312             ($reason) is a string containing error message, or something like "OK" if status is
313             200. Third element ($payload) is the actual result, but usually not present when enveloped result is an error response ($status_code is not 2xx). Fourth
314             element (%result_meta) is called result metadata and is optional, a hash
315             that contains extra information, much like how HTTP response headers provide additional metadata.
316              
317             Return value: (any)
318              
319             =head1 HOMEPAGE
320              
321             Please visit the project's homepage at L<https://metacpan.org/release/App-CSVUtils>.
322              
323             =head1 SOURCE
324              
325             Source repository is at L<https://github.com/perlancar/perl-App-CSVUtils>.
326              
327             =head1 AUTHOR
328              
329             perlancar <perlancar@cpan.org>
330              
331             =head1 CONTRIBUTING
332              
333              
334             To contribute, you can send patches by email/via RT, or send pull requests on
335             GitHub.
336              
337             Most of the time, you don't need to build the distribution yourself. You can
338             simply modify the code, then test via:
339              
340             % prove -l
341              
342             If you want to build the distribution (e.g. to try to install it locally on your
343             system), you can install L<Dist::Zilla>,
344             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
345             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
346             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
347             that are considered a bug and can be reported to me.
348              
349             =head1 COPYRIGHT AND LICENSE
350              
351             This software is copyright (c) 2023, 2022, 2021, 2020, 2019, 2018, 2017, 2016 by perlancar <perlancar@cpan.org>.
352              
353             This is free software; you can redistribute it and/or modify it under
354             the same terms as the Perl 5 programming language system itself.
355              
356             =head1 BUGS
357              
358             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-CSVUtils>
359              
360             When submitting a bug or request, please include a test-file or a
361             patch to an existing test-file that illustrates the bug or desired
362             feature.
363              
364             =cut