You are right about the interpretation of the betas when there is a single categorical variable with $k$ levels. If there were multiple categorical variables (and there were no interaction term), the intercept ($\hat\beta_0$) is the mean of the group that constitute the reference level for *both* (all) categorical variables. Using your example scenario, consider the case where there is no interaction, then the betas are: - $\hat\beta_0$: the mean of white males - $\hat\beta_{\rm Female}$: the *difference* between the mean of females and the mean of white males - $\hat\beta_{\rm Black}$: the *difference* between the mean of black males and the mean of white males We can also think of this in terms of how to calculate the various group means: \begin{align} &\bar x_{\rm White\ Males}& &= \hat\beta_0 \\ &\bar x_{\rm White\ Females}& &= \hat\beta_0 + \hat\beta_{\rm Female} \\ &\bar x_{\rm Black\ Males}& &= \hat\beta_0 + \hat\beta_{\rm Black} \\ &\bar x_{\rm Black\ Females}& &= \hat\beta_0 + \hat\beta_{\rm Female} + \hat\beta_{\rm Black} \end{align} If you had an interaction term, it would be added at the end of the equation for black females. (The interpretation of such an interaction term is quite convoluted, but I walk through it here: [Interpretation of interaction term](http://stats.stackexchange.com/a/122251/7290).) ------------------------------------ *Update*: To clarify my points, let's consider a canned example. d = data.frame(Sex =factor(rep(c("Male","Female"),times=2), levels=c("Male","Female")), Race =factor(rep(c("White","Black"),each=2), levels=c("White","Black")), y =c(1, 3, 5, 7)) d # Sex Race y # 1 Male White 1 # 2 Female White 3 # 3 Male Black 5 # 4 Female Black 7 ![enter image description here][1] The means of `y` for these categorical variables are: aggregate(y~Sex, d, mean) # Sex y # 1 Male 3 # 2 Female 5 aggregate(y~Race, d, mean) # Race y # 1 White 2 # 2 Black 6 We can compare these means to the coefficients from a fitted model: summary(lm(y~Sex+Race, d)) # ... # Coefficients: # Estimate Std. Error t value Pr(>|t|) # (Intercept) 1 3.85e-16 2.60e+15 2.4e-16 *** # SexFemale 2 4.44e-16 4.50e+15 < 2e-16 *** # RaceBlack 4 4.44e-16 9.01e+15 < 2e-16 *** # ... # Warning message: # In summary.lm(lm(y ~ Sex + Race, d)) : # essentially perfect fit: summary may be unreliable The thing to recognize about this situation is that, without an interaction term, we are assuming parallel lines. [1]: https://i.sstatic.net/cEHiC.png