# Do these odds and probabilities seem correct?

Here are some of the coefficients from my model

                       (Intercept)                 Source_FixedAirbnb            Source_FixedBooking.com                Source_FixedExpedia
-1.6075966                         -0.2557988                         -0.3294187                         -0.6887709
Source_FixedOther                       MetroAtlanta                        MetroAustin                     MetroCharlotte
-0.5993866                         -0.0312761                         -0.5221161                         -0.1229700


When converting them to odds ratio:

exp(Regression_Return$coef) (Intercept) Source_FixedAirbnb Source_FixedBooking.com Source_FixedExpedia 0.200369 0.774298 0.719342 0.502193 Source_FixedOther MetroAtlanta MetroAustin MetroCharlotte 0.549148 0.969208 0.593264 0.884290  When converting them to probability  (Intercept) Source_FixedAirbnb Source_FixedBooking.com Source_FixedExpedia 0.166923 0.436397 0.418382 0.334307 Source_FixedOther MetroAtlanta MetroAustin MetroCharlotte 0.354484 0.492182 0.372358 0.469296  My issue here is I should be expecting something in the range of a few percent, but all the coefficients are coming out 20-40%. Have I converted this correctly, ie is it an issue with my model? Additionally, can I combine coefficients in the form of probabilities to find the prediction, or do I have do to this at the log odds point? Does anyone know of a better way to represent logit output for a someone who is only familiar with linear outputs? Giving someone a list of log odds hardly seems useful. ## 2 Answers When you have coefficients reported in terms of log odds, and the predictors are categorical variables (as yours seem to be), you have to add the relevant log odds together. So for example, in your case, if you had a booking in Austin made through Expedia, you would add the intercept, the coefficient for Austin and the coefficient for Expedia: #Intercept #Expedia #Austin (-1.6075966) + (-0.6887709) + (-0.5221161) #> [1] -2.818484  We now exponentiate this to get the odds: exp((-1.6075966) + (-0.6887709) + (-0.5221161)) [1] 0.0596964  To present this number in a way people can understand, you could convert it to a percentage probability: 100 * 0.0596964/(1 + 0.0596964) [1] 5.633349  So 5.6% of bookings in Austin made through Expedia had the outcome (whatever it is was - you don't mention that in your question) Note that you don't need to do this by hand. You can use the predict function with the parameter type = "response" to get the predicted outcome in terms of probabilities. Edit Here's a worked example of producing a table of predicted percent probabilities of the outcome (whatever it is). Note that in your example, the intercept incorporates one factor level each from your two predictor variables, so I have added in two reasonable-seeming alternatives. You will obviously need to change the variable name of your data frame to suit. The steps involved in creating the table are quite straightforward. The difficult part was trying to recreate an approximation of your data and your model because you did not provide a reproducible example. Here's the attempt to recreate your data: # Attempt to recreate data with approximate probabilities taken from OP ps <- c(0.167, 0.134, 0.126, 0.091, 0.099, 0.163, 0.131, 0.123, 0.089, 0.096, 0.106, 0.084, 0.079, 0.056, 0.061, 0.151, 0.121, 0.113, 0.082, 0.089) # Define factor levels of our two variables sources <- c("9flats", "AirBnB", "Booking", "Expedia", "Other") cities <- c("Albuquerque", "Atlanta", "Austin", "Charlotte") # Recreate approximation of data set.seed(1) df <- data.frame(Source_Fixed = factor(rep(sources, 400)), Metro = factor(rep(rep(cities, each = 5), 100)), Outcome = rbinom(2000, 1, rep(ps, 100))) # Recreate approximation of model Regression_Return <- glm(Outcome ~ Source_Fixed + Metro, binomial, df)  Now we have that out the way, we can review our model: Regression_Return #> #> Call: glm(formula = Outcome ~ Source_Fixed + Metro, family = binomial, #> data = df) #> #> Coefficients: #> (Intercept) Source_FixedAirBnB Source_FixedBooking Source_FixedExpedia #> -1.5372 -0.4528 -0.1955 -0.3970 #> Source_FixedOther MetroAtlanta MetroAustin MetroCharlotte #> -0.3970 -0.1403 -0.5246 -0.3394 #> #> Degrees of Freedom: 1999 Total (i.e. Null); 1992 Residual #> Null Deviance: 1419 #> Residual Deviance: 1405 AIC: 1421  Not identical, but pretty similar Anyway, all we need to do now is get each factor level combination with expand.grid: pred_df <- expand.grid(Source_Fixed = levels(df$Source_Fixed),
Metro = levels(df$Metro))  Then we get a prediction for each combination and put it in the prediction data frame as a rounded percentage: preds <- predict(Regression_Return, newdata = pred_df, type = "response") pred_df$percent <- round(100 * preds, 1)


Finally, we use tidyr::pivot_longer to turn this into a table:

tidyr::pivot_wider(pred_df,
id_cols = Metro,
names_from = Source_Fixed,
values_from = percent)
#> # A tibble: 4 x 6
#>   Metro       9flats AirBnB Booking Expedia Other
#>   <fct>          <dbl>  <dbl>   <dbl>   <dbl> <dbl>
#> 1 Albuquerque     17.7   12      15      12.6  12.6
#> 2 Atlanta         15.7   10.6    13.3    11.2  11.2
#> 3 Austin          11.3    7.5     9.5     7.9   7.9
#> 4 Charlotte       13.3    8.9    11.2     9.3   9.3
$$$$

• Thanks. How can I programmatically make a table of all combinations in probability? Do you also have any comment on whether say even my intercept in probability (alone) looks correct? 16% seems too high... – Adam Jun 21 '20 at 0:55
• @Adam without seeing your data it's difficult to know, but since all your coefficients are negative, it means 16% is the highest probability you will have in your table. Most of the rest will be single digits. If you take the mean of your outcome column, it will give you the overall probability across the whole data set to get an idea of whether this seems right. See my update. – Allan Cameron Jun 21 '20 at 12:03
• Thanks! For some reason, I had to run each of these types of line in isolation, else it would say the object names didn't exist. Source_Fixed_Airbnb = levels(datab_c$Source_Fixed_Airbnb) I'm also getting further errors: Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) : invalid type (NULL) for variable 'Twilio_phone_IsLandline'  – Adam Jun 21 '20 at 21:58
• Any idea on the source of these errors? I have more factors that I've added, but for whatever reason, it absolutely can't stand at least one of them. – Adam Jun 27 '20 at 19:46
• oops, forgot to tag. @Allan Cameron – Adam Jun 28 '20 at 0:43

In my experience, the most common way to present logistic regression results is in a table, with columns for some combination of variable, beta hat (parameter estimate), standard error, odds ratio, 95% CI of OR and p value.

• To me, that just seems entirely unreachable for my client who can read linear regression output. Maybe I should just swap to linear and modify the predictor to fit. – Adam Jun 21 '20 at 0:44
• Oh I see, I misunderstood your comment. Are there any packages that will be able to take my model and generate me a table of all the combinations and above factors? I had a good luck but I don't think I know the right keywords to use so aren't finding anything useable. – Adam Jun 21 '20 at 2:27
• There probably are, but I don't know which ones – Peter Flom Jun 22 '20 at 12:39