Calculating Relative Risk / Odds Ratio in gtsummary. Adding adjusted OR in same table

Hello,

I have been stuck on a particular topic for a while. I did try searching for it in the handbook but could not find it. I searched on Stack Overflow and got no response either.

In the past I have typically used the epitools package to calculate Odds Ratio / Relative Risk. However I have found myself increasingly using gtsummary to create tables. In this scenario is there a way I can directly calculate OR /RR with 95CI in a gtsummary table? Could I also add an adjusted OR (via regression) to the same table?

I did read up and gtsummary does have the tbl_reg function to create a table with adjusted OR post regression. But what if i want the normal “unadjusted” cross product OR as well? Also, what about Relative Risk.

I would love to have posted reprex code as well, but this is more of a “what is a good resource to read” rather than me getting stuck while coding so dont have any code to share.

Deepak

2 Likes

@aspina, @castory, @arranh, @cmaronga , @k.gaythorpe any recommendations?

1 Like

hey @deepakvarughese,

is this what you are looking for? There is a section in the handbook on combining univariate with multivariable regression estimates.

There is also a seciton in the handbook for cross product OR and RR using gtsummary

You may also be interested in this post

1 Like

Thank You Alex! This was precisely what i was looking for.

I had seen that text in the handbook. I guess the problem was that i was not familiar with the term “univariate regression”.

Would i be right in assuming that the OR generated from this would be the same as the OR (Cross Product ( ad/bc)) if we drew a simple 2x2 table between exposure and outcome? Also in this case would not Relative Risk need a different calculation (Incidence among exposed (a/a+b)/ Incidence among non exposed (c/ c+d) )

There is an oddsratio.wald() / riskratio.wald() function in the epitools library but it is really cumbersome to make a good looking table with that.

Thank you so much!!

1 Like

no worries deepak - yep you are right univariate regression produces the same OR and RRs as the cross product calculation.
You are also right about the calculation for RR - gtsummary does the calculating for you though!

Agree epitools is very heavy and outdated!

1 Like

Thank You Alex!

1 Like

Thank You @aspina . I got my tables exactly how I wanted them. Much appreciated.

PS: I must actively point out that I dislike the use of (abcd) while describing OR/ RR and make it a point to tell my Uni students to not try to remember it like that. I used it just to make sure we were talking about the same thing. It bugged me so much I NEED to clarify, LOL.

2 Likes

haha glad you could scratch that itch - out of interest how do you explain it to your students? Its the only way ive ever seen it explained, keen to hear other ways!

1 Like

Ah. Its not really different. Just that I would like them to think of Relative Risk as “incidence in one group (exposed)/ incidence in other group (unexposed)” rather than simply memorize a whole bunch of abcd formulae that make no sense to them. Similarly when learning about sensitivity I would rather them think of True Positives / (True Positives + False Positives) while visualizing the 2*2 table rather than rote memorizing a/ (a+c) . I guess the concept is the most important thing?

3 Likes

@deepakvarughese did you manage to find out how to calculate risk ratios using tbl_uvregression() by any chance? Or for that matter, how to calculate relative risk using glm()?

My understanding is that:

  • family = poisson(link = "log") gives incident rate ratios

  • family = binomial(link = "logit") gives odds ratios

  • family = binomial(link = "log") should give risk ratios but throws an error about start values

  • family = poisson(link = "log"), vcov = ~ hetero should give risk ratios and can be calculated with the fixest::feglm() function, but this function doesn’t work with gtsummary as the formula argument is called fml and it doesn’t match with formula created by gtsummary (even though the vignette lists this function and implies that it should work).

2 Likes

So I think poisson with a log link and an offset variable (person time) gives you IRR, otherwise it would just return a regular RR, no?

1 Like

Hello! Sorry for opening a solved discussion, but it’s still not clear to me how to use tbl_uvregression to give an output of RR instead of an OR. What option should I use?

Thanks.

Ian

1 Like

hey ian

You can get RR using either poisson or negative binomial as below (sorry not a proper reprex). Both will produce the same estimate, but likely slightly different confidence intervals. The choice between the two has to do with overdispersion - in reality, if you run the negative variable and there is no overdispersion the {MASS} package automatically runs a poisson (so saves you having to make decisions).

## RISK ratios (poisson)
linelist_cleaned %>%
  select(DIED, gender_bin, age_group) %>%
    gtsummary::tbl_uvregression(method = glm,
                               y = DIED,
                               method.args = list(family = poisson),
                               exponentiate = TRUE,
                               hide_n = TRUE)

## RISK RATIOS (negative binomial) 
linelist_cleaned %>%
   select(DIED, gender_bin, age_group) %>%
   gtsummary::tbl_uvregression(method = MASS::glm.nb,
                               y = DIED,
                               exponentiate = TRUE,
                               hide_n = TRUE)
3 Likes

EpiStats is back, in case it helps:
EpiStats: Tools for Epidemiologists (r-project.org)

3 Likes

Thank you! This package makes it easier to transition from Stata and teach case control and cohort studies.

1 Like

Hello, Alex!
Could you please clarify, what test is used in tbl_uvregression for calculation for p-value for categorical variables? Pearsons chi-square or Fisher test?
In tbl_summary when we add p_value default statistical test is chi-squared test, but if any expected call count is below 5 then a Fisher’s exact test is used. Is it the same to tbl_uvregression?

1 Like

hi @ulyana.9355 - it depends what method you choose. tbl_uvregression just uses other packages to do the calculation and then presents them nicely. For the examples above the {glm} and {MASS} packages are used for the regression and then p-values are calculated with the {broom} package (tidy function). The {broom} tidy function itself uses the base R summary function to calculate p-values, which from this discussion seems to just be doing a pearsons.
I imagine when you have cell counts less than 5 the glm will struggle to converge and you probably need to start looking at exact regression methods (e.g. exact logistic)
hope this helps

2 Likes

Hi Alex and Deepak,
Thanks for the nice discussion about getting OR and RR with 95% CI in univariate regression. Are you sure gtsummary package gives RR? I could not find that. The default option seems to be OR and C.I.
Even though it is fine to have OR, typically journals need RR or Mean difference and not OR in cases of univariate comparisons. Kindly clarify.

2 Likes

hello - yes can confirm it is possible to produce RR, see reply above for code

2 Likes