First a little bit of context:
In my package summarytools, I've defined a print
method for objects of classs "summarytools". I have also created a function view()
that handles objects created using by()
or lapply()
in such a way that the output doesn't include the lines stating the group -- or the variable in the case of lapply()
; summarytools displays its own headings containing that information, so there is some redundancy when using print
. Also, the main headings are not repeated when using view()
.
Here's an example. Note that in this version (in development), I included a message advising the use of view()
:
> library(summarytools)
> (tmp <- with(tobacco, by(smoker, gender, freq)))
gender: F
For best results printing list objects with summarytools, use view(x, method = 'pander')
Frequencies
tobacco$smoker
Type: Factor
Group: gender = M
Freq % Valid % Valid Cum. % Total % Total Cum.
----------- ------ --------- -------------- --------- --------------
Yes 147 30.06 30.06 30.06 30.06
No 342 69.94 100.00 69.94 100.00
<NA> 0 0.00 100.00
Total 489 100.00 100.00 100.00 100.00
------------------------------------------------------------------
gender: M
Frequencies
tobacco$smoker
Type: Factor
Group: gender = F
Freq % Valid % Valid Cum. % Total % Total Cum.
----------- ------ --------- -------------- --------- --------------
Yes 143 29.24 29.24 29.24 29.24
No 346 70.76 100.00 70.76 100.00
<NA> 0 0.00 100.00
Total 489 100.00 100.00 100.00 100.00
And now using view()
:
> view(tmp, method = "pander")
Frequencies
tobacco$smoker
Type: Factor
Group: gender = M
Freq % Valid % Valid Cum. % Total % Total Cum.
----------- ------ --------- -------------- --------- --------------
Yes 147 30.06 30.06 30.06 30.06
No 342 69.94 100.00 69.94 100.00
<NA> 0 0.00 100.00
Total 489 100.00 100.00 100.00 100.00
Group: gender = F
Freq % Valid % Valid Cum. % Total % Total Cum.
----------- ------ --------- -------------- --------- --------------
Yes 143 29.24 29.24 29.24 29.24
No 346 70.76 100.00 70.76 100.00
<NA> 0 0.00 100.00
Total 489 100.00 100.00 100.00 100.00
I've thought about ways through which the objects of class "by" would automatically be dispatched to view()
instead of print()
. If I add the class "summarytools" to those objects, the print()
method could redirect the call to view()
, making it simpler for users to get proper, optimal outputs.
The solutions I've thought of, so far, are the following:
lapply()
.by()
so that when it's called from one of summarytools' functions, it appends the desired class to the created objects. I've avoided this because I'm hesitant to redefine base functions. I'd rather not see messages to the effect that objects have been masked when the package is loaded.by()
, such as by_st()
; I could use basically the same code as by.default()
and by.data.frame()
, the only difference being that I'd add the "summarytools" class to the created objects. This is a sort of compromise that I'm considering.My question is the following: could there be other, maybe better solutions I'm not seeing?
You could use S3 method for print.by
to dispatch to your custom function:
old.print.by = print.by # save the original function so we can restore it later
print.by = summarytools::view # redefine print.by to dispatch to custom function
tmp
To restore original function later you can do print.by = old.print.by
.
If you only want your new function to operate on lists that contain objects of class "summarytools", you can use
print.by = function(x, method = 'pander', ...) {
if ("summarytools" %in% class(x[[1]])) {
summarytools::view(x, method, ...)
} else {
old.print.by(x, ...)
}
}