6

I am using texreg to show regressions side-by-side, including SUR systems with systemfit, but I have some formatting constraints/preferences. I would like to be able to round the coefficients one way, while rounding the goodness-of-fit measures to more digits. For now at least I will also be displaying confidence intervals instead of standard errors, so those are not necessarily a factor here. I also need to output this in HTML and not LaTeX format.

My issue is similar to emagar's How to show only coefficients rounded to whole numbers in LaTeX tables?, but the answer there was largely based around LaTeX tables, while I currently need to be using HTML tables, so the answer to that question, for this and other reasons, is not sufficiently applicable to my issue.
The actual function I am using to do this is actually knitreg (since this is in R Markdown), but have generally been treating it as htmlreg.

    texreg::knitreg(
    l=list(ln(...), systemfit_object), 
    <various formatting>, 
    digits=?
    )

I suspect that there are several potential work-arounds, and I have already done some complex in this project for other purposes. Obviously, though, I would prefer something simpler, if possible, but really my main preference would be to able to use primarily R-based code for this.

Andrew A
  • 185
  • 2
  • 11
  • For those who are wondering, the "complexity" that I am alluding to at the end there is really just that I rolled the actual function into a `purr::as_mapper(~knitreg(...)` thing so that I can use the `file=` value to export to multiple formats and also can vary the digits when I call it. – Andrew A Apr 21 '22 at 00:57
  • 1
    To format the coefficient and goodness-of-fit blocks separately, there is currently no provision within the `texreg` package. But maybe the `matrixreg` function could help you work towards a solution outside of `texreg`. It returns a `character` matrix of the table. Maybe that's something you can work on in the ways you want. But then you won't have the other formatting options of the package at your disposal, such as turning the table into HTML or rounding coefficients etc. – Philip Leifeld May 14 '22 at 08:26
  • Thanks, I will look into `matrixreg`, but converting to html is pretty central to what I want to do with this, so I doubt This will be enough on its own to solve this. – Andrew A May 18 '22 at 14:29
  • 1
    can you make a reproducible example with data and code? – Mike May 18 '22 at 19:08
  • @Mike I am basing this off of relatively large and complex datasets and regressions, and I am still relatively new to posting questions on here, but I will try to see if I can put together some reproducible code. It seems that the functionality I want does not exist within the specific function I have been using, and it seems completely redoing to workflow, or at least switching functions, will be necessary to get this to work the way I want. Given that, I am not sure that reproducible code will be all that helpful. – Andrew A May 23 '22 at 19:00

2 Answers2

2

One approach would be to map2 two lists (one of models, one of desired digits), reduce the output by cbinding the second column of matrixreg (= the coefficients), and afterwards kableing them to the desired output format:

library(systemfit)
library(purrr)
library(kableExtra)

## generate some example models,
## e.g. fit3sls and fit2sls (used below):
example(systemfit)


## map2 and reduce:
map2(list(fit3sls, fit2sls), ## list of models
     list(2, 3), ## list of desired output digits per model
     function(MODEL, DIGITS) matrixreg(MODEL, digits = DIGITS)
     ) %>%
  ## cbind 2nd columns (coefficients) of upstream matrixreg results:
  reduce(~ cbind(.x, .y[,2])) %>%
  as.data.frame %>% ## convert to dataframe for kable
  kable(format = 'html') ## or 'latex' etc.

Below code shows (for other occasions, but since I were at it ...) how to modify the output digits per result class (inspired by this SO thread). So, if you were to choose digits per result class (e.g. print systemfit() results with 4, and lm() results with 6 digits) you could:

... inspect the "factory default" like this: systemfit:::print.systemfit (note the threefold colon) which reveals that the number of digits is part of the function's arguments (formals)

## > systemfit:::print.systemfit
## function (x, digits = max(3, getOption("digits") - 1), ...) 
## {
## etc.

... then hoist the "factory version" into your global environment:

print.systemfit <- systemfit:::print.systemfit

... and set the digits formal for the session like this:

formals(print.systemfit)$digits <-  10

... see if it works:

## > example(systemfit)
## ...
Coefficients:
demand_(Intercept)       demand_price      demand_income supply_(Intercept) 
     99.8954229115      -0.3162988049       0.3346355982      58.2754312020 
      supply_price   supply_farmPrice       supply_trend 
      0.1603665957       0.2481332947       0.2483023473 
## ...
## it works! :-)
1

If you're happy using my huxtable package, this is very simple:

library(huxtable)
r1 <- lm(Sepal.Width ~ Sepal.Length, iris)
r2 <- lm(Sepal.Width ~ Sepal.Length + Petal.Width, iris)
h <- huxreg(r1, r2)
h
              ────────────────────────────────────────────────────
                                      (1)              (2)        
                               ───────────────────────────────────
                (Intercept)           3.419 ***        1.926 ***  
                                     (0.254)          (0.321)     
                Sepal.Length         -0.062            0.289 ***  
                                     (0.043)          (0.066)     
                Petal.Width                           -0.466 ***  
                                                      (0.072)     
                               ───────────────────────────────────
                N                   150              150          
                R2                    0.014            0.234      
                logLik              -86.732          -67.781      
                AIC                 179.464          143.563      
              ────────────────────────────────────────────────────
                *** p < 0.001; ** p < 0.01; * p < 0.05.           

Column names: names, model1, model2

# rows 9-11, columns 2-3 are the model statistics
# display them to one decimal place:
number_format(h)[9:11, 2:3] <- 1 
h
              ────────────────────────────────────────────────────
                                      (1)              (2)        
                               ───────────────────────────────────
                (Intercept)           3.419 ***        1.926 ***  
                                     (0.254)          (0.321)     
                Sepal.Length         -0.062            0.289 ***  
                                     (0.043)          (0.066)     
                Petal.Width                           -0.466 ***  
                                                      (0.072)     
                               ───────────────────────────────────
                N                   150              150          
                R2                    0.0              0.2        
                logLik              -86.7            -67.8        
                AIC                 179.5            143.6        
              ────────────────────────────────────────────────────
                *** p < 0.001; ** p < 0.01; * p < 0.05.           

Column names: names, model1, model2

Huxtable tables will automatically print to the right format in knitr documents, so you can just evaluate the object.

An alternative is to use pipe style:

huxreg(r1, r2) |>
  set_number_format(9:11, -1, 1)
              ────────────────────────────────────────────────────
                                      (1)              (2)        
                               ───────────────────────────────────
                (Intercept)           3.419 ***        1.926 ***  
                                     (0.254)          (0.321)     
                Sepal.Length         -0.062            0.289 ***  
                                     (0.043)          (0.066)     
                Petal.Width                           -0.466 ***  
                                                      (0.072)     
                               ───────────────────────────────────
                N                   150              150          
                R2                    0.0              0.2        
                logLik              -86.7            -67.8        
                AIC                 179.5            143.6        
              ────────────────────────────────────────────────────
                *** p < 0.001; ** p < 0.01; * p < 0.05.           

Column names: names, model1, model2

Incidentally, if you like the texreg output style, then you can use huxtablereg in that package, then set number_format as above.

dash2
  • 2,024
  • 6
  • 15
  • Though this answer does technically work for reformatting these things to how I would want it, it actually does not solve my specific problem. I am using `systemfit`, and it seems that `huxtable` is unable to handle it correctly: it treats the various regressions I want to show as if they were a single model, which they technically sort of are, but the point of creating a table is to look at each one separately. Even when I try to use `texreg::huxtablereg` using formatting that works for all other versions of `texreg`, it comes out wrong. – Andrew A May 25 '22 at 17:13
  • Re `systemfit`, that sounds like it could be a huxtable bug. Regarding `texreg`, that sounds like a separate issue, maybe worth checking `?huxtablereg` and/or using huxtable formatting on the texreg object. – dash2 May 26 '22 at 10:02
  • Also, if the output shows everything as a single model, why not just split the table into two? – dash2 May 26 '22 at 10:04
  • I have a whole bunch (like 5-to-10) regressions within a `systemfit` object, and I may need to add an additional one on to that. I want to show them side by side because they use mainly the same variables. The main problem I have been running into is that it seems that `huxtable` just does not seem to recognize `systemfit`-generated objects, even when I disaggregate them into a list of individual equations, they are still typed as systemfit-regressions and the function seemingly refuses to work with them. – Andrew A Jun 03 '22 at 22:21
  • 1
    So if I do e.g. the first example from `?systemfit` and then call `hr <- huxreg(fitols, statistics = c())`, I get a long table with one column. If I then do e.g. `cbind(hr[2:7,], hr[8:13,])` I get the columns side by side. – dash2 Jun 04 '22 at 12:09
  • I have been busy and haven't had much time to get back to this issue. The method of your last comment does produce them roughly in the form I want, so that is what I am going for. If you just want confirmation of what the end result should look like, then that is correct, but it is not methodologically all that helpful when I am using a larger group of `SUR` regressions. `texreg` is usually able to distinguish the different regressions to format them, but for some reason, it does not appear to work only for `huxtablereg`. Cutting it 10 times is less practical than 2, but possible. – Andrew A Jun 10 '22 at 17:49
  • Sounds like a texreg bug. – dash2 Jun 10 '22 at 19:14
  • agreed. I think I might report it if it doesn't already have there attention. – Andrew A Jun 10 '22 at 19:16