====================================
Creating tables of model estimates
====================================
The "mtable" function
=====================
In conjunction with LaTeX, the output of the ``mtable()`` function of
the package can produce output as can be seen in the following example
(which is LaTeX converted into a png-file):
This LaTeX output was generated by the following code:
.. code-block:: r
# First a couple of models are run:
model1 <- glm((vote3=="Truman")~occup4,data=vote.48,
family="binomial")
model2 <- glm((vote3=="Truman")~total.income,data=vote.48,
family="binomial")
model3 <- glm((vote3=="Truman")~occup4+total.income,data=vote.48,
family="binomial")
model4 <- glm((vote3=="Truman")~relig3,data=vote.48,
family="binomial")
model5 <- glm((vote3=="Truman")~occup4+relig3,data=vote.48,
family="binomial")
.. code-block:: r
# then an mtable object is produced, relabelled and converted
# to LaTeX:
mt145 <- mtable("Model 1"=model1,
"Model 4"=model4,
"Model 5"=model5,
summary.stats=c("Nagelkerke R-sq.","Deviance","AIC","N")
)
mt145 <- relabel(mt145,
"[(]Intercept[)]"="\\\\emph{Intercept}",
occup4="Occup. class",
relig3="Religion",
gsub=TRUE)
ltx.m145 <- toLatex(mt145,ddigits=5)
writeLines(ltx.m145,
con="somewhere/mt145.tex")
Creating of this output involves the following steps: *First*,
``mtable()`` is called
.. code-block:: r
mt145 <- mtable("Model 1"=model1,
"Model 4"=model4,
"Model 5"=model5,
summary.stats=c("Nagelkerke R-sq.","Deviance","AIC","N")
)
The resulting object, if printed to the R-console, looks like so:
.. code-block:: r
print(mt145)
::
Calls:
Model 1: glm(formula = (vote3 == "Truman") ~ occup4, family = "binomial",
data = vote.48)
Model 4: glm(formula = (vote3 == "Truman") ~ relig3, family = "binomial",
data = vote.48)
Model 5: glm(formula = (vote3 == "Truman") ~ occup4 + relig3, family = "binomial",
data = vote.48)
==================================================================================
Model 1 Model 4 Model 5
----------------------------------------------------------------------------------
(Intercept) -1.401*** -0.213 -1.687***
(0.271) (0.126) (0.294)
occup4: Other white collar/Upper white collar 1.368*** 1.287***
(0.373) (0.381)
occup4: Blue collar/Upper white collar 2.448*** 2.385***
(0.327) (0.337)
occup4: Farmer/Upper white collar 1.826*** 2.039***
(0.413) (0.426)
relig3: Catholic/Protestant 0.877*** 0.685*
(0.243) (0.292)
relig3: Other,none/Protestant 0.975** 1.191**
(0.347) (0.441)
----------------------------------------------------------------------------------
Nagelkerke R-sq. 0.2 0.1 0.3
Deviance 404.2 537.7 393.1
AIC 412.2 543.7 405.1
N 344 402 344
==================================================================================
*Second*, the result of ``mtable()`` is "embellished" using a call to
``relabel()``:
.. code-block:: r
mt145 <- relabel(mt145,
"[(]Intercept[)]"="\\\\emph{Intercept}",
occup4="Occup. class",
relig3="Religion",
gsub=TRUE)
*Third*, the relabelled objected is converted into LaTeX and written to
a file:
.. code-block:: r
ltx.m145 <- toLatex(mt145,ddigits=5)
writeLines(ltx.m145,
con="somewhere/mt145.tex")
``mtable()`` can also be used to generate HTML-formatted tables of
estimates that can be included into word-processor software such as
LibreOffice or MS-Word.
.. code-block:: r
# We get rid of the LaTeX formatting ...
mt145 <- relabel(mt145,
"\\emph{Intercept}"="Intercept",
fixed=TRUE)
show_html(mt145)
.. raw:: html
| Model 1 | Model 4 | Model 5 |
Intercept | −1 | . | 401*** | −0 | . | 213 | −1 | . | 687*** |
| (0 | . | 271) | (0 | . | 126) | (0 | . | 294) |
Occup. class: Other white collar/Upper white collar | 1 | . | 368*** | | | | 1 | . | 287*** |
| (0 | . | 373) | | | | (0 | . | 381) |
Occup. class: Blue collar/Upper white collar | 2 | . | 448*** | | | | 2 | . | 385*** |
| (0 | . | 327) | | | | (0 | . | 337) |
Occup. class: Farmer/Upper white collar | 1 | . | 826*** | | | | 2 | . | 039*** |
| (0 | . | 413) | | | | (0 | . | 426) |
Religion: Catholic/Protestant | | | | 0 | . | 877*** | 0 | . | 685* |
| | | | (0 | . | 243) | (0 | . | 292) |
Religion: Other,none/Protestant | | | | 0 | . | 975** | 1 | . | 191** |
| | | | (0 | . | 347) | (0 | . | 441) |
Nagelkerke R-sq. | 0 | . | 2 | 0 | . | 1 | 0 | . | 3 |
Deviance | 404 | . | 2 | 537 | . | 7 | 393 | . | 1 |
AIC | 412 | . | 2 | 543 | . | 7 | 405 | . | 1 |
N | 344 | | | 402 | | | 344 | | |
.. _displopt:
Choosing what information is presented in the table and how
===========================================================
``mtable()`` allows to determine what and how additional information
accompanies (coefficient) estimates in model tables, i.e. whether
- standard errors
- p-values
- symbols for statistical significance (for regression astrologists) or
- confidence intervals
are displayed and whether additional information
- appears below estimates
- or to their right.
Further ``mtable()`` allows to specify which summary statistics are
shown. In general, the way model estimated are represented can be
further customized as described further below.
Estimates, standard errors, confidence intervals etc.
-----------------------------------------------------
The chief method to determine how coefficient estmates are shown and
what and how additional information is provided is by using the
``coef.style=`` argument of ``mtable`` with which a pre-defined or
user-provided template is selected. To demonstrate this, we start with
the 'standard' way in which coefficient estimates are presented:
.. code-block:: r
library(memisc)
lm0 <- lm(sr ~ pop15 + pop75, data = LifeCycleSavings)
lm1 <- lm(sr ~ dpi + ddpi, data = LifeCycleSavings)
lm2 <- lm(sr ~ pop15 + pop75 + dpi + ddpi, data = LifeCycleSavings)
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628*** | 6 | . | 360*** | 28 | . | 566*** |
| (7 | . | 409) | (1 | . | 252) | (7 | . | 355) |
pop15 | −0 | . | 471** | | | | −0 | . | 461** |
| (0 | . | 147) | | | | (0 | . | 145) |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| (1 | . | 041) | | | | (1 | . | 084) |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (0 | . | 001) | (0 | . | 001) |
ddpi | | | | 0 | . | 529* | 0 | . | 410* |
| | | | (0 | . | 210) | (0 | . | 196) |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
N | 50 | | | 50 | | | 50 | | |
We now require Wald-statistics instead of standard errors:
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
coef.style="stat",
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628*** | 6 | . | 360*** | 28 | . | 566*** |
| (4 | . | 134) | (5 | . | 080) | (3 | . | 884) |
pop15 | −0 | . | 471** | | | | −0 | . | 461** |
| (−3 | . | 207) | | | | (−3 | . | 189) |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| (−1 | . | 858) | | | | (−1 | . | 561) |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (1 | . | 962) | (−0 | . | 362) |
ddpi | | | | 0 | . | 529* | 0 | . | 410* |
| | | | (2 | . | 517) | (2 | . | 088) |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
N | 50 | | | 50 | | | 50 | | |
then confidence intervals below estimates
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
coef.style="ci",
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628 | 6 | . | 360 | 28 | . | 566 |
| [15 | . | 724 | [3 | . | 841 | [13 | . | 753 |
| 45 | . | 532] | 8 | . | 879] | 43 | . | 379] |
pop15 | −0 | . | 471 | | | | −0 | . | 461 |
| [−0 | . | 766 | | | | [−0 | . | 753 |
| −0 | . | 175] | | | | −0 | . | 170] |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| [−4 | . | 028 | | | | [−3 | . | 874 |
| 0 | . | 160] | | | | 0 | . | 491] |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | [−0 | . | 000 | [−0 | . | 002 |
| | | | 0 | . | 002] | 0 | . | 002] |
ddpi | | | | 0 | . | 529 | 0 | . | 410 |
| | | | [0 | . | 106 | [0 | . | 015 |
| | | | 0 | . | 952] | 0 | . | 805] |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
N | 50 | | | 50 | | | 50 | | |
confidence intervals to the right
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
coef.style="ci.horizontal",
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628 | [15 | . | 724 | 45 | . | 532] | 6 | . | 360 | [3 | . | 841 | 8 | . | 879] | 28 | . | 566 | [13 | . | 753 | 43 | . | 379] |
pop15 | −0 | . | 471 | [−0 | . | 766 | −0 | . | 175] | | | | | | | | | | −0 | . | 461 | [−0 | . | 753 | −0 | . | 170] |
pop75 | −1 | . | 934 | [−4 | . | 028 | 0 | . | 160] | | | | | | | | | | −1 | . | 691 | [−3 | . | 874 | 0 | . | 491] |
dpi | | | | | | | | | | 0 | . | 001 | [−0 | . | 000 | 0 | . | 002] | −0 | . | 000 | [−0 | . | 002 | 0 | . | 002] |
ddpi | | | | | | | | | | 0 | . | 529 | [0 | . | 106 | 0 | . | 952] | 0 | . | 410 | [0 | . | 015 | 0 | . | 805] |
R-squared | 0 | . | 3 | | | | | | | 0 | . | 2 | | | | | | | 0 | . | 3 | | | | | | |
N | 50 | | | | | | | | | 50 | | | | | | | | | 50 | | | | | | | | |
confidence intervals *and* standard errors
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
coef.style="ci.se.horizontal",
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628 | (7 | . | 409) | 6 | . | 360 | (1 | . | 252) | 28 | . | 566 | (7 | . | 355) |
| [15 | . | 724 | 45 | . | 532] | [3 | . | 841 | 8 | . | 879] | [13 | . | 753 | 43 | . | 379] |
pop15 | −0 | . | 471 | (0 | . | 147) | | | | | | | −0 | . | 461 | (0 | . | 145) |
| [−0 | . | 766 | −0 | . | 175] | | | | | | | [−0 | . | 753 | −0 | . | 170] |
pop75 | −1 | . | 934 | (1 | . | 041) | | | | | | | −1 | . | 691 | (1 | . | 084) |
| [−4 | . | 028 | 0 | . | 160] | | | | | | | [−3 | . | 874 | 0 | . | 491] |
dpi | | | | | | | 0 | . | 001 | (0 | . | 001) | −0 | . | 000 | (0 | . | 001) |
| | | | | | | [−0 | . | 000 | 0 | . | 002] | [−0 | . | 002 | 0 | . | 002] |
ddpi | | | | | | | 0 | . | 529 | (0 | . | 210) | 0 | . | 410 | (0 | . | 196) |
| | | | | | | [0 | . | 106 | 0 | . | 952] | [0 | . | 015 | 0 | . | 805] |
R-squared | 0 | . | 3 | | | | 0 | . | 2 | | | | 0 | . | 3 | | | |
N | 50 | | | | | | 50 | | | | | | 50 | | | | | |
It is also possible to change the symbols for the significance levels:
.. code-block:: r
# Why would one want to have letters instead? I have no idea, but
# some Germen authors/editors seem to like it that way ...
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
signif.symbols=c("a"=.05,
"b"=.01,
"c"=.001),
summary.stats=c("R-squared","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628c | 6 | . | 360c | 28 | . | 566c |
| (7 | . | 409) | (1 | . | 252) | (7 | . | 355) |
pop15 | −0 | . | 471b | | | | −0 | . | 461b |
| (0 | . | 147) | | | | (0 | . | 145) |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| (1 | . | 041) | | | | (1 | . | 084) |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (0 | . | 001) | (0 | . | 001) |
ddpi | | | | 0 | . | 529a | 0 | . | 410a |
| | | | (0 | . | 210) | (0 | . | 196) |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
N | 50 | | | 50 | | | 50 | | |
Summary statistics
------------------
In general there is a certain variety of summary statistics available in
``mtable()``. What statistics these are depends on the statistical model
in question and the facilities provided by the corresponding
``getSummary()`` method (see below). If ``mtable()`` is called without
the ``summary.stats=`` argument *all* available summary statistics are
shown:
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2)
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628*** | 6 | . | 360*** | 28 | . | 566*** |
| (7 | . | 409) | (1 | . | 252) | (7 | . | 355) |
pop15 | −0 | . | 471** | | | | −0 | . | 461** |
| (0 | . | 147) | | | | (0 | . | 145) |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| (1 | . | 041) | | | | (1 | . | 084) |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (0 | . | 001) | (0 | . | 001) |
ddpi | | | | 0 | . | 529* | 0 | . | 410* |
| | | | (0 | . | 210) | (0 | . | 196) |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
adj. R-squared | 0 | . | 2 | 0 | . | 1 | 0 | . | 3 |
sigma | 3 | . | 9 | 4 | . | 2 | 3 | . | 8 |
F | 8 | . | 3 | 4 | . | 5 | 5 | . | 8 |
p | 0 | . | 0 | 0 | . | 0 | 0 | . | 0 |
Log-likelihood | −137 | . | 8 | −141 | . | 0 | −135 | . | 1 |
Deviance | 726 | . | 2 | 824 | . | 7 | 650 | . | 7 |
AIC | 283 | . | 7 | 290 | . | 0 | 282 | . | 2 |
BIC | 291 | . | 3 | 297 | . | 7 | 293 | . | 7 |
N | 50 | | | 50 | | | 50 | | |
So if we prefer (or our reviewer, editor, supervisor or boss) we can show some unusual
statistics
.. code-block:: r
mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
summary.stats=c("sigma","BIC","N"))
.. raw:: html
| Model 1 | Model 2 | Model 3 |
(Intercept) | 30 | . | 628*** | 6 | . | 360*** | 28 | . | 566*** |
| (7 | . | 409) | (1 | . | 252) | (7 | . | 355) |
pop15 | −0 | . | 471** | | | | −0 | . | 461** |
| (0 | . | 147) | | | | (0 | . | 145) |
pop75 | −1 | . | 934 | | | | −1 | . | 691 |
| (1 | . | 041) | | | | (1 | . | 084) |
dpi | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (0 | . | 001) | (0 | . | 001) |
ddpi | | | | 0 | . | 529* | 0 | . | 410* |
| | | | (0 | . | 210) | (0 | . | 196) |
sigma | 3 | . | 9 | 4 | . | 2 | 3 | . | 8 |
BIC | 291 | . | 3 | 297 | . | 7 | 293 | . | 7 |
N | 50 | | | 50 | | | 50 | | |
For more examples regarding the content of the results of ``mtable()``
refer to the example code in the help page given by ``?mable``.
Exporting mtable results
========================
Of course you would not only like to see your table of estimates on
screen but also to include it into a documement that reports your
findings. ``memisc()`` supports exporting tables of model estimates
(i.e. results of ``mtable()``) into *LaTeX* documents and into formats
that can be read in by word-processing software: *tab-delimited* format
and *HTML*. There is no direct way to export model tables into a
word-processing format yet, mainly because there is no (simple) file
format standard (*OpenDocument* may be an emerging standard, but it is
not easy to create files in this format - at least not as easy as HTML).
These various options of exporting the results of ``mtable()`` are
discussed in the following. To this purpose, we return to the example
from above and 'embellish' a bit by changing the coefficient labels:
.. code-block:: r
lm0 <- lm(sr ~ pop15 + pop75, data = LifeCycleSavings)
lm1 <- lm(sr ~ dpi + ddpi, data = LifeCycleSavings)
lm2 <- lm(sr ~ pop15 + pop75 + dpi + ddpi, data = LifeCycleSavings)
mt123 <- mtable("Model 1"=lm0,"Model 2"=lm1,"Model 3"=lm2,
summary.stats=c("R-squared","N"))
mt123 <- relabel(mt123,
"(Intercept)" = "Constant",
pop15 = "Percentage of population under 15",
pop75 = "Percentage of population over 75",
dpi = "Real per-capita disposable income",
ddpi = "Growth rate of real per-capita disp. income"
)
mt123
::
Calls:
Model 1: lm(formula = sr ~ pop15 + pop75, data = LifeCycleSavings)
Model 2: lm(formula = sr ~ dpi + ddpi, data = LifeCycleSavings)
Model 3: lm(formula = sr ~ pop15 + pop75 + dpi + ddpi, data = LifeCycleSavings)
================================================================================
Model 1 Model 2 Model 3
--------------------------------------------------------------------------------
Constant 30.628*** 6.360*** 28.566***
(7.409) (1.252) (7.355)
Percentage of population under 15 -0.471** -0.461**
(0.147) (0.145)
Percentage of population over 75 -1.934 -1.691
(1.041) (1.084)
Real per-capita disposable income 0.001 -0.000
(0.001) (0.001)
Growth rate of real per-capita disp. income 0.529* 0.410*
(0.210) (0.196)
--------------------------------------------------------------------------------
R-squared 0.3 0.2 0.3
N 50 50 50
================================================================================
LaTeX Format
------------
The first format to export ``mtable()`` results into is *TeX/LaTeX*
simply because this is the format in which the author of this package
usually writes his papers. This is achieved by, first, applying the
function ``toLatex()`` to the results of ``mtable()``, which tranlates
them into a character string containing *TeX/LaTeX* code and, second,
using ``writeLines()`` to send this character string into a text file.
This was already shown at the beginning, but we take a closer look at it
here. Continuing the example immediately above, we call ``toLatex()`` to
see the *TeX/LaTeX* code:
.. code-block:: r
toLatex(mt123)
::
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Calls:
% Model 1: lm(formula = sr ~ pop15 + pop75, data = LifeCycleSavings)
% Model 2: lm(formula = sr ~ dpi + ddpi, data = LifeCycleSavings)
% Model 3: lm(formula = sr ~ pop15 + pop75 + dpi + ddpi, data = LifeCycleSavings)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tabular}{lD{.}{.}{3}cD{.}{.}{3}cD{.}{.}{3}}
\toprule
&\multicolumn{1}{c}{Model 1}&&\multicolumn{1}{c}{Model 2}&&\multicolumn{1}{c}{Model 3}\\
\midrule
Constant&30.628^{***}&&6.360^{***}&&28.566^{***}\\
&(7.409)&&(1.252)&&(7.355)\\
Percentage of population under 15&-0.471^{**}&&&&-0.461^{**}\\
&(0.147)&&&&(0.145)\\
Percentage of population over 75&-1.934&&&&-1.691\\
&(1.041)&&&&(1.084)\\
Real per-capita disposable income&&&0.001&&-0.000\\
&&&(0.001)&&(0.001)\\
Growth rate of real per-capita disp. income&&&0.529^{*}&&0.410^{*}\\
&&&(0.210)&&(0.196)\\
\midrule
R-squared&0.3&&0.2&&0.3\\
N&50&&50&&50\\
\bottomrule
\end{tabular}
After formatting with LaTex, this may look like this:
.. image:: mt123.png
:width: 650px
It should be noted that ``toLatex()`` is a generic function and the
"memisc" package 'only' defines a method for "mtable" objects.
Alternatively one could use the call
.. code-block:: r
format(mt123,target="LaTeX")
or even call the internal formatting function itself:
.. code-block:: r
mtable_format_latex(m123)
By default, the TeX/LaTeX code created this way uses the macros
``\toprule``, ``\midrule``, and ``\bottomrule`` provided by the LaTeX
package "booktabs". If you do not like this package (why shouldn't
anyone?) you can resolve this dependency by calling ``toLatex()``,
``format()``, or ``mtable_format_latex()`` with the optional argument
``useBooktabs=FALSE``. Another default dependency is the LaTeX package
"dcolumn", which is used to make sure that floating point numbers are
aligned on their decimal dots. This dependency can be resolved by the
optional argument ``useDcolumn=FALSE``. For more aspects of LaTeX output
that can be customized see the help page ``?mtable_format_latex``.
Until version 0.97 of "memisc", creating a text file with TeX/LaTeX code
had to be done in two steps, first creating a text string with the code
and then writing the text string into the file. Since version 0.98 both
steps can be done with a single function call, using ``write.mtable()``.
That is, to write the LaTeX formatted ``mtable()`` result in ``mt123``
one can simple call:
.. code-block:: r
write.mtable(mt123,format="LaTeX",
file="mt123.tex")
Text file format (tab-delimited and "CSV")
------------------------------------------
Tab-delimited format is of course best-suited for exporting data frames
or matrices into files, but since the results of ``mtable()`` have a
tabular structure, they can also be exported into this format.
Tab-delimited format is quite simple and can be read by a wide variety
of software. However, this simplicity also means that only the cell
contents are exported while embellishments of the contents (e.g.
horizonal alignment of cells and cell borders) are not.
The following code exports the ``mtable()`` result named ``mt123`` into
a text file in tab-delimited format:
.. code-block:: r
write.mtable(mt123,file="mt123.txt")
After opening this file with LibreWriter, using its "covert text into
table" tool, and some manual tweaking the result looks like this:
.. image:: mt123-tabdelim-odt.png
:alt: mtable exported in tab-delimited file and included into LibreWriter
:width: 550px
(The original text file is available
`here `__ while the LibreOffice file is available
`here `__.)
Obviously some further tweaking
(such as comma-oriented column tabulators) is needed to make this work
in a publication.
It is also posslibe export an ``mtable()`` result into "CSV" format and
import it into some spreadsheet software. This would be done so:
.. code-block:: r
write.mtable(mt123,file="mt123.csv",colsep=",")
After opening this file with LibreCalc and some tweaking of the format,
the result looks like this:
.. image:: mt123-csv.png
:alt: mtable exported in csv-format and opened with LibreCalc
:width: 550px
(`Here `__ is the original CSV file.)
HTML (for web-pages, knitr reports and word processors)
-------------------------------------------------------
Of course, having to tweak the format of ``mtable()`` results by hand is
frustrating, so in order to make easier to get well-formatted tables,
version 0.98 of "memisc" provides for exporting the results of
``mtable()`` into HTML. HTML is the format of websites, but it can also
imported into contemporary word processing software with little loss in
formatting. Further, if one is using the "Rmarkdown" and "knitr"
packages to produced HTML-formatted reports, it is convenient to have
HTML versions of ``mtable()`` results.
To get a file in HTML format that contains the results of ``mtable()``
one can again use the function ``write.mtable()``, yet in this case with
the option ``format="HTML"``, or directly the function ``write_html()``:
.. code-block:: r
write_html(mt123,file="mt123.html")
The file "mt123.html" generated that way can be included into your
favourite word-processing software, e.g. LibreOffice. This is how the
table would look like after including it into LibreOffece (and setting
the columns to "optimal width"):
.. image:: mt123-html-odt.png
:alt: mtable exported in HTML and opened with LibreWriter
:width: 550px
and this
how it would look like after including into Word:
.. image:: mt123-html-wrd.png
:alt: mtable exported in HTML and opened with Word
:width: 550px
To view results of ``mtable()`` in HTML in interactive sessions with
RStudio, one can simply call ``show_html()`` as in
.. code-block:: r
show_html(mt123)
Of course, this document is not an interactive sesssion but produced
using the "knitr" package. In this context, ``show_html()`` used inside
an R-chunk with chunk option ``results='asis'`` and the options setting
``options(html_viewer="stdout")``. With the following code one could
even make sure that all results of ``mtable()`` in a *knitr* document
are printed in HTML format:
.. code-block:: r
knit_print.mtable <-function(x,...)
knitr::asis_output(format_html(x))
This "trick" was used :ref:`previously in this document ` where
the different display options of coefficient estmates were discussed.
Thus after this trick, in a knitr document we get
.. code-block:: r
mt123
.. raw:: html
| Model 1 | Model 2 | Model 3 |
Constant | 30 | . | 628*** | 6 | . | 360*** | 28 | . | 566*** |
| (7 | . | 409) | (1 | . | 252) | (7 | . | 355) |
Percentage of population under 15 | −0 | . | 471** | | | | −0 | . | 461** |
| (0 | . | 147) | | | | (0 | . | 145) |
Percentage of population over 75 | −1 | . | 934 | | | | −1 | . | 691 |
| (1 | . | 041) | | | | (1 | . | 084) |
Real per-capita disposable income | | | | 0 | . | 001 | −0 | . | 000 |
| | | | (0 | . | 001) | (0 | . | 001) |
Growth rate of real per-capita disp. income | | | | 0 | . | 529* | 0 | . | 410* |
| | | | (0 | . | 210) | (0 | . | 196) |
R-squared | 0 | . | 3 | 0 | . | 2 | 0 | . | 3 |
N | 50 | | | 50 | | | 50 | | |
Adapting mtable to new model classes and other tricks - the API of mtable
=========================================================================
``mtable()`` is designed to be easily adapted to all kind of model
classes: If there is a model class like, say, "modcls" then all that is
needed to get ``mtable()`` to report estimates of instances of this
model class is to define a function ``getSummary.modcls()``, i.e. a
method function of objects of class "modcls". This function needs to
return a list with components
- "coef": A matrix or array with coefficients and additional
information. The rows should refer to coefficients, the columns
should contain the estimates, standard errors, p-values, lower and
upper confidence interval limits. The columns should be labelled
"est", "se", "stat", "p", "lwr", and "upr".
For single-equation models, this component should be a matrix. For
multiple-equation models, it should be a three-dimensional array,
with the third dimension corresponding to the equations.
- "sumstat": A vector (with named elements) containing model summary
statistics, such goodness-of-fit statistics etc.
- "contrasts": A list of the contrast functions, their names, or
contrast matrices; one for each (ordered or unordered) factors
present in the model.
- "xlevels": A list with the names of the levels of the factors present
in the model.
- "call": A language object describing the call that created the model
estimates.
To illustrate, here are the results of the method function
``getSummary.glm()`` (which is called when the generic function
``getSummary()`` is applied to an object of class "glm"):
.. code-block:: r
# Model from the first example at the beginning ...
model1 <- glm((vote3=="Truman")~occup4,data=vote.48,
family="binomial")
getSummary(model1) # or getSummary.glm(model1)
::
$coef
est se stat p lwr upr
(Intercept) -1.40 0.271 -5.17 2.29e-07 -1.932 -0.87
occup4Other white collar 1.37 0.373 3.67 2.42e-04 0.638 2.10
occup4Blue collar 2.45 0.327 7.48 7.36e-14 1.807 3.09
occup4Farmer 1.83 0.413 4.42 9.85e-06 1.016 2.64
$sumstat
phi LR df p logLik
1.00e+00 7.01e+01 3.00e+00 4.11e-15 -2.02e+02
deviance Aldrich.Nelson McFadden Cox.Snell Nagelkerke
4.04e+02 1.69e-01 1.48e-01 1.84e-01 2.46e-01
AIC BIC N
4.12e+02 4.28e+02 3.44e+02
$contrasts
$contrasts$occup4
[1] "contr.treatment"
$xlevels
$xlevels$occup4
[1] "Upper white collar" "Other white collar" "Blue collar"
[4] "Farmer"
$call
glm(formula = (vote3 == "Truman") ~ occup4, family = "binomial",
data = vote.48)
The definition of this function is available in
`here `__ and can be used as a starting
point for other such method functions.
A demonstration: "mtable" and sandwich estimators of variance
-------------------------------------------------------------
The modularity of ``mtable()`` through the use of the generic
``getSummary()`` function allows other kinds of extensions, e.g.
adapting it to the use of "sandwich" estimators of standard errors. This
can be achieved, first, by defining yet another method function of
``getSummary()``, e.g. the one defined in the *R* available
`here `__. As a second step, one
marks model estimation results such that this newly defined method
function is applied to them by attaching the appropriate class
attribute. For example to get sandwich estimators of standard errors for
"lm"" or "glm"" objects one can attach the classes "lm\_sandwich" or
"glm\_sandwich", respectively, as in the following example:
.. code-block:: r
library(memisc)
library(sandwich)
library(lmtest)
source("getSummary-glm-sandwich.R")
data(Mandible)
fm1 <- lm(length ~ age, data=Mandible, subset=(age <= 28))
fm1.sw <- fm1
class(fm1.sw) <- c("lm_sandwich",class(fm1))
mtable(
"Conventional"=fm1,
"Sandwich"=fm1.sw,
summary.stats=c("R-squared","N"))
.. raw:: html
| Conventional | Sandwich |
(Intercept) | −11 | . | 953*** | −11 | . | 953*** |
| (0 | . | 976) | (1 | . | 010) |
age | 1 | . | 773*** | 1 | . | 773*** |
| (0 | . | 048) | (0 | . | 054) |
R-squared | 0 | . | 9 | 0 | . | 9 |
N | 158 | | | 158 | | |
Alternatively, one can use an appropriate ``getSummary=`` argument to
``mtable()`` like in this example:
.. code-block:: r
fm1 <- lm(length ~ age, data=Mandible, subset=(age <= 28))
fm2 <- lm(length ~ age+I(scale(age)^2), data=Mandible, subset=(age <= 28))
# Using 'conventional' i.e. model-based standard errors:
mtable(fm1,fm2,summary.stats=c("R-squared","N"))
.. raw:: html
| fm1 | fm2 |
(Intercept) | −11 | . | 953*** | −11 | . | 303*** |
| (0 | . | 976) | (1 | . | 060) |
age | 1 | . | 773*** | 1 | . | 754*** |
| (0 | . | 048) | (0 | . | 049) |
I(scale(age)^2) | | | | −0 | . | 362 |
| | | | (0 | . | 236) |
R-squared | 0 | . | 9 | 0 | . | 9 |
N | 158 | | | 158 | | |
.. code-block:: r
# Using sandwich-based standard errors:
mtable(fm1,fm2,
summary.stats=c("R-squared","N"),
getSummary=getSummary.lm_sandwich)
.. raw:: html
| fm1 | fm2 |
(Intercept) | −11 | . | 953*** | −11 | . | 303*** |
| (1 | . | 010) | (1 | . | 348) |
age | 1 | . | 773*** | 1 | . | 754*** |
| (0 | . | 054) | (0 | . | 063) |
I(scale(age)^2) | | | | −0 | . | 362 |
| | | | (0 | . | 258) |
R-squared | 0 | . | 9 | 0 | . | 9 |
N | 158 | | | 158 | | |
Since version 0.98 of "memisc" we can also put mtable results together etc.
.. code-block:: r
mtfm12.conv <- mtable("Model 1"=fm1,
"Model 2"=fm2,
summary.stats=c("R-squared","N"))
mtfm12.sndw <- mtable("Model 1"=fm1,
"Model 2"=fm2,
summary.stats=c("R-squared","N"),
getSummary=getSummary.lm_sandwich)
c(Conventional=mtfm12.conv,Sandwich=mtfm12.sndw)
.. raw:: html
| Conventional | Sandwich |
| Model 1 | Model 2 | Model 1 | Model 2 |
(Intercept) | −11 | . | 953*** | −11 | . | 303*** | −11 | . | 953*** | −11 | . | 303*** |
| (0 | . | 976) | (1 | . | 060) | (1 | . | 010) | (1 | . | 348) |
age | 1 | . | 773*** | 1 | . | 754*** | 1 | . | 773*** | 1 | . | 754*** |
| (0 | . | 048) | (0 | . | 049) | (0 | . | 054) | (0 | . | 063) |
I(scale(age)^2) | | | | −0 | . | 362 | | | | −0 | . | 362 |
| | | | (0 | . | 236) | | | | (0 | . | 258) |
R-squared | 0 | . | 9 | 0 | . | 9 | 0 | . | 9 | 0 | . | 9 |
N | 158 | | | 158 | | | 158 | | | 158 | | |