# ANN: RegressionTables.jl produces publication-quality regression tables

**URL:** https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516
**Category:** Data
**Tags:** announcement
**Created:** [December 5, 2017, 4:02am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516 "2017-12-05T04:02:37Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)
#### Post date: [December 5, 2017, 4:02am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/1 "2017-12-05T04:02:37Z")

</div>

Hi all,

I’ve been working on [RegressionTables.jl](https://github.com/jmboehm/RegressionTables.jl), a package that produces regression tables as seen in scientific journals (similar to R’s `stargazer` and Stata’s `esttab`).

It currently works with output from the absolutely terrific [FixedEffectModels.jl](https://github.com/matthieugomez/FixedEffectModels.jl). Version 0.0.2, which also supports output from [GLM.jl](https://github.com/JuliaStats/GLM.jl), is tagged and will hopefully go live tomorrow.

Quick demo:

```julia
using RegressionTables, DataFrames, FixedEffectModels, RDatasets

df = dataset("datasets", "iris")
df[:SpeciesDummy] = pool(df[:Species])

rr1 = reg(df, @model(SepalLength ~ SepalWidth , fe = SpeciesDummy))
rr2 = reg(df, @model(SepalLength ~ SepalWidth + PetalLength , fe = SpeciesDummy))
rr3 = reg(df, @model(SepalLength ~ SepalWidth + PetalLength + PetalWidth , fe = SpeciesDummy))
rr4 = reg(df, @model(SepalWidth ~ SepalLength + PetalLength + PetalWidth , fe = SpeciesDummy))

regtable(rr1,rr2,rr3,rr4; renderSettings = asciiOutput())

```

produces

```julia
----------------------------------------------------------
                         SepalLength SepalWidth
               ------------------------------ ----------
                    (1) (2) (3) (4)
----------------------------------------------------------
SepalWidth 0.804 ***0.432*** 0.496***             
                (0.106) (0.081) (0.086)             
PetalLength 0.776 ***0.829*** -0.188*
                           (0.064) (0.069) (0.083)
PetalWidth -0.315* 0.626***
                                      (0.151) (0.123)
SepalLength 0.378***
                                                   (0.066)
----------------------------------------------------------
SpeciesDummy Yes Yes Yes Yes
----------------------------------------------------------
Estimator OLS OLS OLS OLS
----------------------------------------------------------
N 150 150 150 150
R2 0.726 0.863 0.867 0.635
----------------------------------------------------------

```

LaTeX output can be generated by using `renderSettings = latexOutput()`. See the readme for the full list of arguments and options.

Look forward to comments and feedback.

---

<div class="post-metadata">

### Author: ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)
#### Post date: [December 5, 2017, 7:54am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/2 "2017-12-05T07:54:51Z")

</div>

Nice!!  
So I noticed you created your own rendering functions for the different outputs (ascii and latex) of the table. I’m not sure what the current situation is, but it would be great if we could centralize some kind of effort when it comes to converting texts, particularly tables, and printing them. Converting an array to markdown, latex, html, in the form of a table is very useful.  
In your case it might not be so useful to decouple the frontend (formatting and printing the table) from the backend (parsing all the variables in the table from the regression model), but I thought your effort in those differently formatted outputs could be of use to a larger more generalized package.

---

<div class="post-metadata">

### Author: ![waldyrious](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/waldyrious/32/80_2.png) [@waldyrious](https://discourse.julialang.org/u/waldyrious)
#### Post date: [December 5, 2017, 10:00am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/3 "2017-12-05T10:00:35Z")

</div>

> [@yakir12](#):
>
> I’m not sure what the current situation is, but it would be great if we could centralize some kind of effort when it comes to converting texts, particularly tables, and printing them. Converting an array to markdown, latex, html, in the form of a table is very useful.

There’s some related discussion in the thread [Pretty printing of tables](https://discourse.julialang.org/t/pretty-printing-of-tables/7254).

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [December 5, 2017, 11:00am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/4 "2017-12-05T11:00:55Z")

</div>

That’s really a useful package, thanks for writing it!

Regarding the rendering, the Julian approach is to implement various `show` methods for your `RegressionTable` type, one for each backend (plain text, LaTeX, Markdown, HTML, CSV…). That way you don’t need to define your own `render` method, nor require the user to explicitly pass the expected type of output via an argument (except of course when s/he wants to): it’s automatically chosen depending on the current interface, so it will look good in the REPL, IJulia, Atom, etc. For example, `asciiOutput` would be replaced with `MIME"text/plain"` and so on. Julia is much more powerful than R in that regard. See [the manual](https://docs.julialang.org/en/latest/manual/types/#Custom-pretty-printing-1) for details.

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 5, 2017, 2:05pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/5 "2017-12-05T14:05:41Z")

</div>

Thanks for the work! I’m excited to try it out.

> [@yakir12](#):
>
> Converting an array to markdown, latex, html, in the form of a table is very useful.

I agree with this a ton. Being able to output an arbitrary matrix to a latex table with multi-level column titles is a godsend for my job. R’s fragmented regression landscape is case in point. Writers of packages like Stargazer have to keep up to date with any new model objects that people produce. Rather, it would Julia ecosystem were centered around users making their own matrices in a matrix or data-frame object, then give them options for nice tables from there.

Of course, being able to pretty print a latex table like this is an incredible tool and is the very first step for any analysis. If the table isn’t made in the code, it doesn’t exist!

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 5, 2017, 2:18pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/6 "2017-12-05T14:18:11Z")

</div>

Additionally, an idea that would make this package blow Stargazer out of the water would be the inclusion of a `Dict` as an optional argument, which would then perform a string replace on variable names.

The way I imagine a functionality might be

```julia
 dict = Dict{String,Integer}(SepalWidth=> "Sepal Width", "SepalLength" => "Sepal Length")
regtable(rr1,rr2,rr3,rr4; renderSettings = asciiOutput(), Labels = dict)

```

And could then print “Sepal Width” whenever it sees the string “SepalWidth”.

Could this happen in the `render` command that prints the table itself?

---

<div class="post-metadata">

### Author: ![Yifan\_Liu](https://avatars.discourse-cdn.com/v4/letter/y/4da419/32.png) [@Yifan\_Liu](https://discourse.julialang.org/u/Yifan_Liu)
#### Post date: [December 5, 2017, 2:41pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/7 "2017-12-05T14:41:14Z")

</div>

Great! I have been using Stargazer for a long time, and it is really useful for academic writing.

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [December 5, 2017, 3:00pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/8 "2017-12-05T15:00:44Z")

</div>

> [@pdeffebach](#):
>
> Additionally, an idea that would make this package blow Stargazer out of the water would be the inclusion of a Dict as an optional argument, which would then perform a string replace on variable names.

Actually, I’ve been thinking for some time that this should be handled at the root, by specifying “variable labels” on data frame columns, which would be passed to the models so that they can be used for printing. See [this issue](https://github.com/JuliaData/DataFrames.jl/issues/35). That way you only need to specify the information once, and often survey datasets come with this kind of information already.

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 5, 2017, 3:11pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/9 "2017-12-05T15:11:07Z")

</div>

As far as I understand, the concern of dataframes developers is that a) there is still a lot of core functionality that needs to be worked on and b) making it work as well as Stata would require a lot of changes for plotting packages and tables packages. It would have to become a huge standard for any package that interfaces with DataFrames.

However I think column metadata is crucial for reproducibility. It’s important for the names of rows and columns in tables to match the code itself, and for a user to be able to look at column metadata to find out the original source of variables.

---

<div class="post-metadata">

### Author: ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)
#### Post date: [December 5, 2017, 3:52pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/10 "2017-12-05T15:52:55Z")

</div>

@pdeffebach I don’t have access to julia right now, but the following should work:

```julia
using RegressionTables, DataFrames, FixedEffectModels, RDatasets

df = dataset("datasets", "iris")
df[:SpeciesDummy] = pool(df[:Species])

rr1 = reg(df, @model(SepalLength ~ SepalWidth , fe = SpeciesDummy))
rr2 = reg(df, @model(SepalLength ~ SepalWidth + PetalLength , fe = SpeciesDummy))
rr3 = reg(df, @model(SepalLength ~ SepalWidth + PetalLength + PetalWidth , fe = SpeciesDummy))
rr4 = reg(df, @model(SepalWidth ~ SepalLength + PetalLength + PetalWidth , fe = SpeciesDummy))

regtable(rr1,rr2,rr3,rr4; renderSettings = asciiOutput(), labels = Dict("SepalLength" => "My dependent variable: SepalLength", "PetalLength" => "Length of Petal", "PetalWidth" => "Width of Petal", "(Intercept)" => "Const." , "isSmall" => "isSmall Dummies", "SpeciesDummy" => "Species Dummies"))

```

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 5, 2017, 3:54pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/11 "2017-12-05T15:54:54Z")

</div>

Fantastic! I didn’t notice that feature at first. This is really great.

---

<div class="post-metadata">

### Author: ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)
#### Post date: [December 5, 2017, 4:08pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/12 "2017-12-05T16:08:33Z")

</div>

@nalimilan I see your point. On the other hand, I feel that some of the backends like LaTeX will most likely not be called from an interface that requests LaTeX output. I could have used something like

```julia
tab = regtable(rr1,rr2)
asLaTeX(tab)

```

but decided against it to have everything in one line (I don’t imagine users to do a lot of other stuff with RegressionTables other than rendering).

---

<div class="post-metadata">

### Author: ![Yifan\_Liu](https://avatars.discourse-cdn.com/v4/letter/y/4da419/32.png) [@Yifan\_Liu](https://discourse.julialang.org/u/Yifan_Liu)
#### Post date: [December 5, 2017, 4:55pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/13 "2017-12-05T16:55:12Z")

</div>

I received this error message when tried to install your package

```julia
unknown package RegressionTables
macro expansion at .\pkg\entry.jl:53 [inlined]
(::Base.Pkg.Entry.##1#3{String,Base.Pkg.Types.VersionSet})() at .\task.jl:335
sync_end() at task.jl:287
macro expansion at task.jl:303 [inlined]
add(::String, ::Base.Pkg.Types.VersionSet) at entry.jl:51
(::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}})() at dir.jl:36
cd(::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}}, ::String) at file.jl:59
#cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{String,N} where N) at dir.jl:36
add(::String) at pkg.jl:117
include_string(::String, ::String) at loading.jl:522
eval(::Module, ::Any) at boot.jl:235
(::Atom.##61#64)() at eval.jl:102
withpath(::Atom.##61#64, ::Void) at utils.jl:30
withpath(::Function, ::Void) at eval.jl:38
macro expansion at eval.jl:101 [inlined]
(::Atom.##60#63{Dict{String,Any}})() at task.jl:80

```

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [December 5, 2017, 5:19pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/14 "2017-12-05T17:19:55Z")

</div>

Have you run `Pkg.update()` recently @Yifan_Liu ?

---

<div class="post-metadata">

### Author: ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)
#### Post date: [December 5, 2017, 6:26pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/15 "2017-12-05T18:26:14Z")

</div>

> [@jmboehm](#):
>
> @nalimilan I see your point. On the other hand, I feel that some of the backends like LaTeX will most likely not be called from an interface that requests LaTeX output. I could have used something like
> 
> tab = regtable(rr1,rr2)  
> asLaTeX(tab)
> 
> but decided against it to have everything in one line (I don’t imagine users to do a lot of other stuff with RegressionTables other than rendering).

That’s not incompatible. You could return a `RegressionTable` object by default, which is printed using the `show` method using the most appropriate format for the current display, but still allow choosing a different output via an argument, in which case you’d just print the requested representation directly.

EDIT: To give more context, a situation where automatically choosing the default output format is really useful is IJulia notebooks. When I use stargazer in RStudio notebooks, I find it annoying that I need to specify whether to output HTML or LaTeX, and if I get it wrong instead of a nice table I get a wall of text. Then if you decide to compile your notebook to HTML rather than to LaTeX, you need to change the code. That doesn’t sound like a correctly designed system.

---

<div class="post-metadata">

### Author: ![Yifan\_Liu](https://avatars.discourse-cdn.com/v4/letter/y/4da419/32.png) [@Yifan\_Liu](https://discourse.julialang.org/u/Yifan_Liu)
#### Post date: [December 5, 2017, 10:59pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/16 "2017-12-05T22:59:47Z")

</div>

After updating all packages, I was able to install the package, but could not load it and got the error message:

```julia
Failed to precompile RegressionTables to 
C:\Users\user\.julia`Preformatted text`\lib\v0.6\RegressionTables.ji.
compilecache(::String) at loading.jl:710
_require(::Symbol) at loading.jl:497
require(::Symbol) at loading.jl:405
include_string(::String, ::String) at loading.jl:522
eval(::Module, ::Any) at boot.jl:235
(::Atom.##61#64)() at eval.jl:102
withpath(::Atom.##61#64, ::Void) at utils.jl:30
withpath(::Function, ::Void) at eval.jl:38
macro expansion at eval.jl:101 [inlined]
(::Atom.##60#63{Dict{String,Any}})() at task.jl:80

```

---

<div class="post-metadata">

### Author: ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)
#### Post date: [December 6, 2017, 1:23am UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/17 "2017-12-06T01:23:37Z")

</div>

@nalimilan Fair enough. I can put that into the next version.

---

<div class="post-metadata">

### Author: ![IljaK91](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iljak91/32/44301_2.png) [@IljaK91](https://discourse.julialang.org/u/IljaK91)
#### Post date: [December 12, 2017, 2:13pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/18 "2017-12-12T14:13:16Z")

</div>

Thanks a lot for writing the package! I have one question: Is it possible to choose to a different set of standard errors to show? For many cases the standard homoskedastic standard errors from a fit(LinearModel,…) regression using GLM are not appropriate and instead I would like to use HC or HAC standard errors. Is there a way to have them included automatically in your output?

---

<div class="post-metadata">

### Author: ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)
#### Post date: [December 12, 2017, 3:33pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/19 "2017-12-12T15:33:43Z")

</div>

@IljaK91 `regtable()` prints the square root of the diagonal of `vcov(dfrm::DataFrameRegressionModel)` (in case of GLM.jl’s output), or the `vcov` field of a `AbstractRegressionResult` (if you use FixedEffectModels.jl). As long as you pass the adjusted vcov matrix in these objects to `regtable()`, they should print correctly.

Are you adjusting the standard errors yourself, or are you using a package to do it for you? If so, it would be great to support it.

---

<div class="post-metadata">

### Author: ![IljaK91](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iljak91/32/44301_2.png) [@IljaK91](https://discourse.julialang.org/u/IljaK91)
#### Post date: [December 12, 2017, 4:24pm UTC](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516/20 "2017-12-12T16:24:00Z")

</div>

It would be great if [https://github.com/gragusa/CovarianceMatrices.jl](https://github.com/gragusa/CovarianceMatrices.jl) was supported directly. I use that package to get robust standard errors. There should be also a bit of information at the bottom of the table about which standard errors were used, (HC, HAC, and which type).

I don’t know if GLM.jl supports somehow directly providing the adjusted SEs, in which case this request would be obsolete. So far run regressions with GLM.fit() and adjust the SEs afterwards using CovarianceMatrices.jl. This is a bit tiresome, if you have many regressions.

[Next page](https://discourse.julialang.org/t/ann-regressiontables-jl-produces-publication-quality-regression-tables/7516.md?page=2)
