Card & Krueger (1994) – Minimum Wage and Fast-Food Employment

A Difference-in-Differences replication of the New Jersey minimum-wage natural experiment

R
Causal Inference
Difference-in-Differences
Labor Economics
R + Quarto replication of Card & Krueger (1994), reproducing core Diff-in-Diff results and re-expressing the employment effect with a more intuitive interactive visualization.
Published

April 20, 2026

Introduction

HW2 · Causal Replication · Difference-in-Differences

Did a higher minimum wage reduce fast-food jobs in New Jersey?

Card & Krueger’s 1994 paper became iconic because it challenged a simple competitive-model prediction. Using neighboring restaurants in New Jersey and Pennsylvania, they argued that employment rose rather than fell after the wage increase.

Main DiD estimate
+2.75 FTE
Table 3, row 3, columns (i)-(iii)
Regression check
2.33
Table 4 col (i), SE = 1.19
95% CI on DiD
[-0.01, 4.66]
Based on Table 4 col (i) OLS SE
Stores in sample
357
Paper benchmark: 357

Executive Summary

I replicate the core employment result from Card & Krueger (1994) with the public New Jersey-Pennsylvania fast-food dataset. The headline estimate is very close to the paper: employment in New Jersey restaurants increased by about 2.76 FTE workers relative to Pennsylvania after the minimum-wage increase. I also reproduce the simple reduced-form regression from Table 4, where the coefficient on the New Jersey dummy is 2.33.

Why This Matters

This paper matters well beyond labor economics. It is one of the cleanest examples of how to reason about a policy shock when you do not have a randomized experiment. That skill transfers directly to data analysis and finance:

  • policy changes often hit one group before another
  • markets and businesses react over time, not just cross-sectionally
  • naive before-vs-after comparisons can be badly misleading

For portfolio work, this is exactly the kind of project that shows you can do more than prediction. It shows you can think about identification, comparison groups, and why an estimated effect should be interpreted causally at all.

Research Design

The core setup is a textbook Difference-in-Differences design:

\[ \text{DiD} = ( \bar{Y}_{NJ, after} - \bar{Y}_{NJ, before} ) - ( \bar{Y}_{PA, after} - \bar{Y}_{PA, before} ) \]

New Jersey is the treatment group because its minimum wage rose from $4.25 to $5.05 in April 1992. Pennsylvania is the control group because its minimum wage stayed at the federal level.

Treatment group

Fast-food restaurants in New Jersey.

Control group

Comparable restaurants in eastern Pennsylvania.

Before / after

Wave 1 in February 1992 and wave 2 in November-December 1992.

Outcome

Full-time-equivalent employment, defined as FT + managers + 0.5 × PT.

The identifying assumption is the usual one: absent the New Jersey policy change, employment in NJ stores would have moved roughly in parallel to employment in nearby PA stores.

Assignment Checklist

What the Assignment Requires for Card & Krueger (1994)

  • Table 2: replicate some descriptive statistics
  • Table 3: replicate the 9 numbers in columns 1-3 and rows 1-3
  • Table 4: replicate column (i)
  • one additional thing beyond direct replication

This revised page now does all four explicitly. The main improvement over my earlier draft is that the Table 3 numbers, the hero estimate, and the comparison plots are now computed directly from the raw public.dat file, not hand-entered from the paper.

Data and Replication Targets

I read the public public.dat flat file using the original codebook positions and recreate the main variables from the paper’s SAS program:

  • fte = empft + nmgrs + 0.5 * emppt
  • fte2 = empft2 + nmgrs2 + 0.5 * emppt2
  • demp = fte2 - fte
  • gap = (5.05 - wage_st) / wage_st for sub-minimum NJ stores and 0 in PA

The assignment asked for three pieces:

  1. some of Table 2
  2. Table 3, columns 1-3 and rows 1-3
  3. Table 4, column (i)

Beyond strict replication I add three pieces: (1) Figure 2 of the paper, which visually shows that the minimum-wage shock actually bound in NJ and not in PA; (2) Table 4 column (ii), the paper’s preferred continuous-intensity specification using the wage-gap regressor; and (3) an interactive tabbed reframing of Table 3 so the DiD logic reads as a picture, not a table.

Main Analysis

Table 2: State-level descriptives

Code
table2_selected |>
  gt(groupname_col = "wave", rowname_col = "metric") |>
  fmt_number(
    columns = c(Pennsylvania, `New Jersey`, `NJ - PA`),
    rows = !(metric %in% percent_metrics),
    decimals = 2
  ) |>
  fmt_percent(
    columns = c(Pennsylvania, `New Jersey`, `NJ - PA`),
    rows = metric %in% percent_metrics,
    decimals = 1
  ) |>
  cols_label(
    `New Jersey` = "NJ",
    Pennsylvania = "PA"
  ) |>
  tab_header(
    title = "Replication of Selected Rows from Table 2",
    subtitle = "State-level descriptives before and after the New Jersey minimum-wage increase"
  ) |>
  tab_source_note("I focus on the rows most directly tied to the policy shock: employment, wages, meal prices, operating hours, and bonus/recruiting indicators. Note: the wave-1 `bonus` variable (any bonus offered) and the wave-2 `special2` variable (special recruiting program) are the paired fields used in the paper's own SAS code, but they are not perfectly identical in wording.")
Replication of Selected Rows from Table 2
State-level descriptives before and after the New Jersey minimum-wage increase
NJ PA NJ - PA
Wave 1
FTE employment 20.44 23.33 −2.89
Share full-time 32.8% 35.0% −2.2%
Starting wage 4.61 4.63 −0.02
Share at $4.25 32.2% 34.2% −2.0%
Share at $5.05 NA NA NA
Meal price 3.35 3.04 0.31
Hours open 14.42 14.53 −0.11
Bonus / recruiting program 23.6% 29.1% −5.5%
Wave 2
FTE employment 21.03 21.17 −0.14
Share full-time 35.9% 30.4% 5.5%
Starting wage 5.08 4.62 0.46
Share at $4.25 0.0% 28.2% −28.2%
Share at $5.05 89.0% 1.4% 87.6%
Meal price 3.41 3.03 0.39
Hours open 14.42 14.65 −0.23
Bonus / recruiting program 20.3% 23.4% −3.1%
I focus on the rows most directly tied to the policy shock: employment, wages, meal prices, operating hours, and bonus/recruiting indicators. Note: the wave-1 `bonus` variable (any bonus offered) and the wave-2 `special2` variable (special recruiting program) are the paired fields used in the paper's own SAS code, but they are not perfectly identical in wording.

This is still only a subset of Table 2, but it is now a clearer subset. It covers the variables that matter most for the policy story:

  • wages jump sharply in New Jersey and barely move in Pennsylvania
  • the share of NJ stores paying exactly $5.05 jumps mechanically after the law change
  • employment does not move in the direction the simple textbook prediction would suggest

The core comparison is not whether New Jersey changed on its own, but whether it changed relative to Pennsylvania. That is what makes the Difference-in-Differences estimate more informative than a simple before-after comparison in one state.

Table 3: The key DiD result

Code
table3_main |>
  gt(rowname_col = "row_label") |>
  fmt_number(columns = c(Pennsylvania, `New Jersey`, `NJ - PA`), decimals = 2) |>
  tab_header(
    title = "Replication of Table 3 Core Results",
    subtitle = "Average FTE employment before and after the minimum-wage increase"
  ) |>
  tab_style(
    style = list(cell_fill(color = "#eef6f5"), cell_text(weight = "bold")),
    locations = cells_body(rows = 1:3)
  ) |>
  tab_source_note("Rows 1-3 and columns 1-3 are the assignment target. Sensitivity checks are reported separately below in the dedicated sample-definition section.")
Replication of Table 3 Core Results
Average FTE employment before and after the minimum-wage increase
Pennsylvania New Jersey NJ - PA
1. FTE employment before, all available observations 23.33 20.44 −2.89
2. FTE employment after, all available observations 21.17 21.03 −0.14
3. Change in mean FTE employment −2.17 0.59 2.75
Rows 1-3 and columns 1-3 are the assignment target. Sensitivity checks are reported separately below in the dedicated sample-definition section.

The key quantity is row 3, column 3:

  • Pennsylvania changes by -2.16
  • New Jersey changes by +0.59
  • the Difference-in-Differences estimate is +2.76 FTE workers

That is the controversial punchline of the paper. The point estimate says employment grew in New Jersey relative to Pennsylvania after the wage hike.

Table 4: Reduced-form regression check

Code
table4_gt |>
  gt(rowname_col = "Specification") |>
  fmt_number(columns = c(Estimate, `Std. Error`, Intercept), decimals = 2) |>
  fmt_integer(columns = `Sample size`) |>
  tab_header(
    title = "Replication of Table 4, Columns (i) and (ii)",
    subtitle = "OLS regression of change in FTE employment on treatment intensity"
  ) |>
  tab_style(
    style = list(cell_fill(color = "#eef6f5"), cell_text(weight = "bold")),
    locations = cells_body(columns = Estimate)
  ) |>
  tab_source_note(
    source_note = paste0(
      "Column (i) reproduces the assignment target — the NJ-dummy specification. Column (ii) is the paper's preferred ",
      "continuous-intensity design, where the regressor is the percentage wage shortfall relative to $5.05."
    )
  )
Replication of Table 4, Columns (i) and (ii)
OLS regression of change in FTE employment on treatment intensity
Treatment variable Estimate Std. Error Intercept Sample size
(i) NJ dummy New Jersey dummy 2.33 1.19 −2.13 357
(ii) Wage gap Wage gap (NJ shortfall) 15.65 6.08 −1.58 357
Column (i) reproduces the assignment target — the NJ-dummy specification. Column (ii) is the paper's preferred continuous-intensity design, where the regressor is the percentage wage shortfall relative to $5.05.

Column (i) is the assignment target. The coefficient of 2.33 is close to the published 2.33 and close in spirit to the raw DiD estimate of 2.75 from Table 3. The slight gap versus Table 3 is expected because Table 4 imposes a stricter sample: stores must have both employment and wage information.

Column (ii) is a bonus I added because the paper actually treats it as its preferred specification. Instead of a binary NJ indicator, it uses the wage gap — how far each store’s starting wage sat below $5.05 as a fraction of its own starting wage, with zero for Pennsylvania and for NJ stores already paying \(\geq\) $5.05. The coefficient of 15.65 says that a store forced to raise wages by 10 percent added roughly 1.57 FTE relative to stores with no bite — the same sign and a similar magnitude to the NJ-dummy estimate, which is reassuring.

Statistical Significance, Honestly Reported

The OLS SE of 1.19 on the NJ dummy implies a 95% CI of roughly [-0.01, 4.66] FTE. The effect is estimated positively, but it is only marginally statistically distinguishable from zero. That is an honest read of the data — Card & Krueger’s contribution was rejecting the textbook prediction of a large negative effect, not proving a large positive one.

Replication Accuracy Check

Code
accuracy_table3 |>
  gt(rowname_col = "row_label") |>
  fmt_number(
    columns = c(
      `PA (paper)`, `PA (ours)`, `PA diff`,
      `NJ (paper)`, `NJ (ours)`, `NJ diff`,
      `DiD (paper)`, `DiD (ours)`, `DiD diff`
    ),
    decimals = 2
  ) |>
  tab_header(
    title = "Replication Accuracy Check for Table 3",
    subtitle = "Published values versus reproduced values for the required 9 numbers"
  ) |>
  tab_style(
    style = list(cell_fill(color = "#edf7f2"), cell_text(weight = "bold")),
    locations = cells_body(columns = c(`PA diff`, `NJ diff`, `DiD diff`))
  ) |>
  tab_source_note(
    source_note = "Published benchmarks were manually keyed from the published Card & Krueger (1994) Table 3 for direct paper-vs-reproduction comparison."
  )
Replication Accuracy Check for Table 3
Published values versus reproduced values for the required 9 numbers
PA (paper) PA (ours) PA diff NJ (paper) NJ (ours) NJ diff DiD (paper) DiD (ours) DiD diff
1. FTE employment before, all available observations 23.33 23.33 0.00 20.44 20.44 0.00 −2.89 −2.89 0.00
2. FTE employment after, all available observations 21.17 21.17 0.00 21.03 21.03 0.00 −0.14 −0.14 0.00
3. Change in mean FTE employment −2.16 −2.17 −0.01 0.59 0.59 0.00 2.76 2.75 −0.01
Published benchmarks were manually keyed from the published Card & Krueger (1994) Table 3 for direct paper-vs-reproduction comparison.
Code
accuracy_table4 |>
  gt(rowname_col = "quantity") |>
  fmt_number(columns = c(paper, ours, diff), decimals = 2) |>
  tab_header(
    title = "Replication Accuracy Check for Table 4, Column (i)",
    subtitle = "Published benchmark versus reproduced regression output"
  ) |>
  tab_source_note(
    source_note = "Published benchmarks were manually keyed from Card & Krueger (1994) Table 4, column (i): coefficient 2.33, standard error 1.19, sample size 357."
  )
Replication Accuracy Check for Table 4, Column (i)
Published benchmark versus reproduced regression output
paper ours diff
Coefficient on New Jersey dummy 2.33 2.33 0.00
Std. Error 1.19 1.19 0.00
Sample size 357.00 357.00 0.00
Published benchmarks were manually keyed from Card & Krueger (1994) Table 4, column (i): coefficient 2.33, standard error 1.19, sample size 357.

This is the most honest way to summarize the current status:

  • Table 3: the required 9 numbers line up with the published values to rounding precision
  • Table 4 column (i): the coefficient, standard error, and sample size line up closely with the published benchmark
  • Table 2: this page reproduces a defensible subset of rows, which is consistent with the assignment wording, but it does not claim to recreate every row of the original table

Something Additional

Replicating Figure 2: The wage-distribution shock

Table 3 shows that the policy moved wages in New Jersey. Figure 2 of the paper shows how cleanly it did so, and it is by far the most persuasive picture in the paper. The histograms below are the replication: they plot the distribution of starting wages across fast-food stores in each state, separately for wave 1 (February 1992, before the hike) and wave 2 (November-December 1992, after).

Code
wage_dist |>
  ggplot(aes(x = wage, fill = wave)) +
  geom_histogram(
    aes(y = after_stat(density)),
    binwidth = 0.1,
    position = position_identity(),
    alpha = 0.75,
    color = "white"
  ) +
  geom_vline(xintercept = 4.25, linetype = "dashed", color = "#6c7a89") +
  geom_vline(xintercept = 5.05, linetype = "dashed", color = "#0f766e") +
  annotate("text", x = 4.23, y = Inf, label = "$4.25",
           vjust = 1.6, hjust = 1, size = 3, color = "#6c7a89", fontface = "bold") +
  annotate("text", x = 5.07, y = Inf, label = "$5.05",
           vjust = 1.6, hjust = 0, size = 3, color = "#0f766e", fontface = "bold") +
  facet_grid(state_name ~ wave) +
  scale_fill_manual(values = c("Wave 1 (Feb 1992)" = "#6c7a89",
                                "Wave 2 (Nov-Dec 1992)" = "#0f766e")) +
  scale_x_continuous(limits = c(4.0, 5.75), breaks = seq(4.0, 5.75, 0.25)) +
  labs(
    title = "The minimum-wage hike bit in New Jersey, not in Pennsylvania",
    subtitle = "Distribution of starting wages across fast-food restaurants, by state and survey wave",
    x = "Starting wage ($/hour)",
    y = "Density",
    fill = NULL,
    caption = "Dashed lines: $4.25 old federal minimum, $5.05 new NJ minimum. Replication of Card & Krueger (1994), Figure 2."
  ) +
  theme(legend.position = "none", strip.text = element_text(face = "bold"))

The story the histogram tells is almost mechanical:

  • In wave 1, both states cluster at or just above the old $4.25 federal minimum. The two states look similar.
  • In wave 2, the NJ distribution collapses onto $5.05 — the new binding minimum. Pennsylvania barely moves.

This is the “first stage” of the natural experiment: the policy really did reshape NJ wages, while PA served as a clean counterfactual. Without this picture, the Table 3 employment comparison would be much less convincing — a DiD estimate is only as credible as the treatment actually being different between groups.

Rewriting Table 3 as a Visual Story

The paper gives the core result in a table. That is fine for replication, but it is not the easiest way to build intuition. The interactive tabbed module below uses the same data calculations as the table and lets you compare three sample definitions without relying on hard-coded values.

This is the same result as Table 3, but it reads more intuitively: Pennsylvania drifts downward, while New Jersey roughly holds steady or improves depending on the sample definition. The gap between those two trends is the DiD estimate.

Sensitivity Check: Temporarily Closed Stores

Code
sensitivity_table |>
  gt(rowname_col = "sample") |>
  fmt_number(columns = c(`PA change`, `NJ change`, `Diff-in-Diff`), decimals = 2) |>
  tab_header(
    title = "Sensitivity of the DiD Estimate to Sample Definition",
    subtitle = "All values are computed directly from the public survey file"
  ) |>
  tab_source_note("This is my additional analysis beyond strict table replication.")
Sensitivity of the DiD Estimate to Sample Definition
All values are computed directly from the public survey file
PA change NJ change Diff-in-Diff
All available −2.17 0.59 2.75
Balanced sample −2.28 0.47 2.75
Temporarily closed = 0 −2.28 0.23 2.51
This is my additional analysis beyond strict table replication.

This is a better extra section than a purely decorative chart because it does something substantive. It shows that the exact treatment of temporarily closed stores matters at the margin, but it does not overturn the paper’s central conclusion. The estimate shrinks from about 2.76 to 2.51, which is movement worth acknowledging but not a reversal.

Interpretation

There are three progressively better comparisons here:

  1. Cross-section only: NJ stores were smaller than PA stores even before the policy change, so a simple after-period comparison is not useful.
  2. Before-after only: employment falls in PA and rises slightly in NJ, but either state could also be affected by seasonality or macro conditions.
  3. Difference-in-Differences: by comparing the change in NJ to the change in PA, we difference out common time shocks and get a much more credible estimate of the policy effect.

Taken together, Table 3 and Table 4 tell the same story: once the comparison is framed relative to Pennsylvania, the employment effect is not negative in the way a simple textbook model would predict.

Why the DiD Framing Is the Right One

If I only compared New Jersey before versus after, I might wrongly attribute any seasonal or regional macro movement to the minimum wage. If I only compared New Jersey and Pennsylvania after the policy, I would ignore the fact that PA stores started larger. DiD fixes both problems by asking a cleaner question: how much did NJ change relative to PA?

The remaining caveat is the standard DiD caveat: parallel trends is an assumption, not something we observe directly with only two waves. That is why the neighboring-state comparison and the robustness checks around balanced samples matter.

What I Learned

  • The paper’s headline claim survives replication surprisingly well with the public data.
  • The most important move is not the regression. It is defining the right comparison.
  • Turning the table into a visual made the logic much easier to follow than reading coefficients alone.
  • For future finance or policy-analysis work, this project is a reminder that the core challenge is often not prediction accuracy but credible counterfactual thinking.

Notes on Matching the Paper

My point estimates line up closely with the published numbers for the required rows and columns. Small differences in standard errors are expected and are consistent with the assignment note: the paper’s exact treatment of subsamples, closures, and standard-error construction is a little idiosyncratic in places.

Back to top