# install.packages(c("wooldridge", "stargazer"))
library(wooldridge)   # provides the wage2 dataset
library(stargazer)    # side-by-side regression tables

Q1. What is the bias of an estimator?

An estimator \(\hat{\theta}\) is a rule (a formula applied to sample data) used to guess an unknown population parameter \(\theta\) — for us, the true regression coefficient \(\beta\). Because it depends on a random sample, \(\hat{\theta}\) is itself a random variable with a sampling distribution.

The bias of the estimator is the difference between its expected value (the average estimate we would get across infinitely many random samples) and the true parameter:

\[ \text{Bias}(\hat{\theta}) \;=\; E[\hat{\theta}] - \theta . \]

An estimator is unbiased when \(E[\hat{\theta}] = \theta\), i.e. the bias is zero — on average it hits the target, even if any single sample is off. It is biased when \(E[\hat{\theta}] \neq \theta\); the estimates are systematically centered away from the truth. Bias is about the center of the sampling distribution, not its spread. That distinction matters here: a biased estimator does not get better just because the spread shrinks.

Q2. Does OVB go away with a larger sample or more variables?

A bigger sample does NOT fix omitted variable bias. OVB is a bias problem, not a precision problem. Adding rows (observations) shrinks the standard errors and narrows the sampling distribution, so the estimate becomes more precise — but it becomes more precise around the wrong number. As \(n \to \infty\) the biased estimator converges to \(\beta + \text{bias}\), not to \(\beta\). In fact a large sample makes things worse in a sense: you get a tight, confident, and wrong answer. (This is the lighter-and-lung-cancer / smoking example from class.)

Adding the right variable CAN fix it — but “more variables” means new columns (the omitted variable itself, or a good proxy for it), not more rows. If you can actually measure and include the confounder, the bias disappears because the two OVB conditions can no longer both hold. When the confounder is unmeasurable, you instead change the research design (experiment, diff-in-diff, RDD, IV, fixed effects) to get around it. Note that adding irrelevant variables does nothing for bias (and only costs you degrees of freedom) — see the bonus questions.

Q3. A distinct OVB example: the return to education (“ability bias”)

The dataset

I use wage2 from the wooldridge package: 935 working men from the U.S. National Longitudinal Survey. Key variables:

  • wage — monthly earnings (dollars); I use lwage = log(wage)
  • educ — years of education
  • IQ — IQ score (a proxy for cognitive ability)
  • age — age in years
  • sibs — number of siblings

This is a different dataset and a different question from the class examples (gender/tenure wages and test-scores/STR).

data(wage2)
wage2$lwage <- log(wage2$wage)
stargazer(wage2[, c("wage", "educ", "IQ", "age", "sibs")],
          type = "text", title = "Summary Statistics")
## 
## Summary Statistics
## ========================================
## Statistic  N   Mean   St. Dev. Min  Max 
## ----------------------------------------
## wage      935 957.945 404.361  115 3,078
## educ      935 13.468   2.197    9   18  
## IQ        935 101.282  15.053  50   145 
## age       935 33.080   3.108   28   38  
## sibs      935  2.941   2.306    0   14  
## ----------------------------------------

(a) The full / correct model and the key regressor

We want the causal return to education. Wages depend on both schooling and underlying ability; ability is rewarded in the labor market and helps people get more schooling. The correct model therefore includes ability (proxied by IQ):

\[ \log(wage)_i \;=\; \beta_0 \;+\; \beta_1\, educ_i \;+\; \beta_2\, IQ_i \;+\; u_i \]

My key independent variable of interest is educ (\(\beta_1\) = the return to a year of schooling).

full_model <- lm(lwage ~ educ + IQ, data = wage2)
summary(full_model)
## 
## Call:
## lm(formula = lwage ~ educ + IQ, data = wage2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.01601 -0.24367  0.03359  0.27960  1.23783 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 5.6582876  0.0962408  58.793  < 2e-16 ***
## educ        0.0391199  0.0068382   5.721 1.43e-08 ***
## IQ          0.0058631  0.0009979   5.875 5.87e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3933 on 932 degrees of freedom
## Multiple R-squared:  0.1297, Adjusted R-squared:  0.1278 
## F-statistic: 69.42 on 2 and 932 DF,  p-value: < 2.2e-16

(b) The short / incorrect model (omitting ability)

In practice we rarely have a clean ability measure, so a researcher would be forced to drop it. Omitting IQ gives the short model:

\[ \log(wage)_i \;=\; \alpha_0 \;+\; \alpha_1\, educ_i \;+\; v_i \]

short_model <- lm(lwage ~ educ, data = wage2)
summary(short_model)
## 
## Call:
## lm(formula = lwage ~ educ, data = wage2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.94620 -0.24832  0.03507  0.27440  1.28106 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 5.973062   0.081374   73.40   <2e-16 ***
## educ        0.059839   0.005963   10.04   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4003 on 933 degrees of freedom
## Multiple R-squared:  0.09742,    Adjusted R-squared:  0.09645 
## F-statistic: 100.7 on 1 and 933 DF,  p-value: < 2.2e-16

(c) Are the two OVB conditions met?

For omitted variable bias to occur, both conditions must hold. With educ as the key regressor \(A\) and the omitted IQ as \(B\):

Condition I — The omitted variable is correlated with the key regressor. Here: is IQ correlated with educ? More able people tend to acquire more schooling, so we expect a positive correlation.

cor.test(wage2$IQ, wage2$educ)
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$IQ and wage2$educ
## t = 18.385, df = 933, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.4670255 0.5612531
## sample estimates:
##      cor 
## 0.515697

The correlation is about +0.52 and highly significant (\(p < 2.2\times10^{-16}\)), so Condition I is met (positive).

Condition II — The omitted variable is a determinant of the outcome \(Y\). Here: does IQ affect lwage? Ability is rewarded in the labor market, so we expect a positive effect. Both the raw correlation and the significant, positive \(\beta_2\) in the full model support this.

cor.test(wage2$IQ, wage2$lwage)
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$IQ and wage2$lwage
## t = 10.13, df = 933, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2558383 0.3714047
## sample estimates:
##       cor 
## 0.3147877

The correlation is about +0.31 and highly significant (\(p < 2.2\times10^{-16}\)), and in the full model \(\hat\beta_2 \approx 0.0059\) (\(p<0.001\)). Condition II is met (positive).

Both conditions hold, so omitting IQ biases the coefficient on educ.

(d) Direction of the bias — which cell of the 2×2 matrix?

Full model: \(Y = \beta_0 + \beta_1 A + \beta_2 B + u\); short model: \(Y = \alpha_0 + \alpha_1 A + v\). The OVB formula gives

\[ \alpha_1 \;=\; \beta_1 \;+\; \underbrace{\beta_2 \cdot \delta_1}_{\text{bias}}, \qquad \text{where } B = \delta_0 + \delta_1 A + e . \]

The sign of the bias is the sign of \(\beta_2\) (effect of \(B\) on \(Y\)) times the sign of \(\delta_1\) (correlation of \(A\) and \(B\)):

\(A,B\) positively correlated \(A,B\) negatively correlated
\(B\) has positive effect on \(Y\) Positive bias Negative bias
\(B\) has negative effect on \(Y\) Negative bias Positive bias

In our case educ and IQ are positively correlated (\(+0.52\)) and IQ has a positive effect on lwage (\(\hat\beta_2 > 0\)). That is the top-left cell → positive bias. So the short-model return to education is biased upward: it overstates the true return.

# delta1: slope of IQ on educ
aux <- lm(IQ ~ educ, data = wage2)
delta1 <- coef(aux)["educ"]

beta1  <- coef(full_model)["educ"]   # true-ish return to educ
beta2  <- coef(full_model)["IQ"]     # effect of IQ on lwage
alpha1 <- coef(short_model)["educ"]  # biased return to educ

c(beta1_full = beta1, bias = beta2 * delta1,
  predicted_short = beta1 + beta2 * delta1, actual_short = alpha1)
##      beta1_full.educ              bias.IQ predicted_short.educ 
##           0.03911990           0.02071931           0.05983921 
##    actual_short.educ 
##           0.05983921

The predicted short coefficient (\(\beta_1 + \beta_2\delta_1\)) reproduces the actual short coefficient almost exactly (≈ 0.0598), confirming the formula.

(e) The two regressions side by side

stargazer(full_model, short_model,
          type = "text",
          column.labels = c("Full (correct)", "Short (omits IQ)"),
          covariate.labels = c("Education", "IQ", "Constant"),
          title = "Return to Education: Full vs. Short Model")

Return to Education: Full vs. Short Model

                              Dependent variable:               
                ------------------------------------------------
                                     lwage                      
                    Full (correct)          Short (omits IQ)    
                          (1)                     (2)           
Education 0.039*** 0.060*** (0.007) (0.006)
IQ 0.006*** (0.001)
Constant 5.658*** 5.973*** (0.096) (0.081)

Observations 935 935
R2 0.130 0.097
Adjusted R2 0.128 0.096
Residual Std. Error 0.393 (df = 932) 0.400 (df = 933)
F Statistic 69.419*** (df = 2; 932) 100.700*** (df = 1; 933) ==================================================================== Note: p<0.1; p<0.05; p<0.01

The short coefficient is larger, exactly the positive (upward) bias the OVB formula predicted. Confirmed.

(f) Intuition — why the bias goes this way

In the short model, educ is doing two jobs at once. It carries its own genuine effect on wages plus it stands in for the ability it is correlated with but which we failed to control for. More-educated workers also tend to be higher-ability workers, and ability independently raises pay. So part of the wage premium that really comes from ability gets wrongly credited to schooling. educ “absorbs” ability’s effect, and because both links are positive (able people get more schooling, and ability pays), the credit pushes the coefficient up. Control for ability and that borrowed credit is handed back to IQ, so the education coefficient falls to its true, smaller value.

Advanced Bonus

The two OVB conditions are jointly necessary. Break either one and the omitted variable causes essentially no bias — the key coefficient barely moves. Each bonus below breaks exactly one condition.

Bonus 1 — Correlated with the key \(X\), but NOT a determinant of \(Y\)

Here I add a variable Z that is correlated with educ (Condition I holds) but has no independent effect on wages (Condition II fails). I build it as 0.6*educ + noise, where the noise is unrelated to wages, so any link Z has to lwage runs only through educ.

set.seed(123)
wage2$Z <- 0.6 * wage2$educ + rnorm(nrow(wage2), mean = 0, sd = 4)

cor.test(wage2$Z, wage2$educ)   # Condition I: correlated with key X  -> significant
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$Z and wage2$educ
## t = 10.515, df = 933, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.2669571 0.3816470
## sample estimates:
##       cor 
## 0.3254988
cor.test(wage2$Z, wage2$lwage)  # only a weak, educ-induced link to Y
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$Z and wage2$lwage
## t = 2.579, df = 933, p-value = 0.01006
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.02012933 0.14745079
## sample estimates:
##        cor 
## 0.08413345
m_base <- lm(lwage ~ educ, data = wage2)
m_addZ <- lm(lwage ~ educ + Z, data = wage2)

stargazer(m_base, m_addZ, type = "text",
          column.labels = c("Base", "Add Z"),
          title = "Bonus 1: adding a variable that does not determine Y")
## 
## Bonus 1: adding a variable that does not determine Y
## ====================================================================
##                                   Dependent variable:               
##                     ------------------------------------------------
##                                          lwage                      
##                               Base                    Add Z         
##                               (1)                      (2)          
## --------------------------------------------------------------------
## educ                        0.060***                0.061***        
##                             (0.006)                  (0.006)        
##                                                                     
## Z                                                    -0.002         
##                                                      (0.003)        
##                                                                     
## Constant                    5.973***                5.973***        
##                             (0.081)                  (0.081)        
##                                                                     
## --------------------------------------------------------------------
## Observations                  935                      935          
## R2                           0.097                    0.098         
## Adjusted R2                  0.096                    0.096         
## Residual Std. Error     0.400 (df = 933)        0.400 (df = 932)    
## F Statistic         100.700*** (df = 1; 933) 50.491*** (df = 2; 932)
## ====================================================================
## Note:                                    *p<0.1; **p<0.05; ***p<0.01

Z is strongly correlated with educ, yet its own coefficient is insignificant (it is not a determinant of lwage), and the educ estimate is essentially unchanged. Because Condition II fails, there is no bias to correct — the variable carries no wage information beyond what educ already provides.

Bonus 2 — A determinant of \(Y\), but NOT correlated with the key \(X\)

Now the opposite: age genuinely affects wages (Condition II holds) but is essentially uncorrelated with educ (Condition I fails).

cor.test(wage2$age, wage2$lwage)  # Condition II: age affects wages   -> significant
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$age and wage2$lwage
## t = 5.0089, df = 933, p-value = 6.546e-07
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.09873397 0.22361503
## sample estimates:
##       cor 
## 0.1618223
cor.test(wage2$age, wage2$educ)   # Condition I fails: ~uncorrelated  -> not significant
## 
##  Pearson's product-moment correlation
## 
## data:  wage2$age and wage2$educ
## t = -0.37433, df = 933, p-value = 0.7082
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.07630670  0.05189951
## sample estimates:
##         cor 
## -0.01225396
m_addage <- lm(lwage ~ educ + age, data = wage2)

stargazer(m_base, m_addage, type = "text",
          column.labels = c("Base", "Add age"),
          title = "Bonus 2: adding a determinant of Y uncorrelated with X")
## 
## Bonus 2: adding a determinant of Y uncorrelated with X
## ====================================================================
##                                   Dependent variable:               
##                     ------------------------------------------------
##                                          lwage                      
##                               Base                   Add age        
##                               (1)                      (2)          
## --------------------------------------------------------------------
## educ                        0.060***                0.060***        
##                             (0.006)                  (0.006)        
##                                                                     
## age                                                 0.022***        
##                                                      (0.004)        
##                                                                     
## Constant                    5.973***                5.225***        
##                             (0.081)                  (0.160)        
##                                                                     
## --------------------------------------------------------------------
## Observations                  935                      935          
## R2                           0.097                    0.125         
## Adjusted R2                  0.096                    0.123         
## Residual Std. Error     0.400 (df = 933)        0.394 (df = 932)    
## F Statistic         100.700*** (df = 1; 933) 66.486*** (df = 2; 932)
## ====================================================================
## Note:                                    *p<0.1; **p<0.05; ***p<0.01

age is a strong, significant predictor of lwage (\(p < 10^{-6}\)) but is uncorrelated with educ (\(p \approx 0.7\)). Adding it moves the educ coefficient by a trivial amount (≈ 0.0598 → 0.0602). Because Condition I fails, age has no overlapping variation with educ to reallocate, so the key estimate stays put.

Takeaway: an omitted variable only biases your key coefficient when it is correlated with the key regressor and determines the outcome. Miss either condition and — no matter how important the variable is on its own — your point estimate is safe.