1 Introduction

This R Markdown file implements the empirical strategy described in Section 4 (Data and Methods) of the case study on the EC – Hormones dispute, and produces the four graphs and accompanying regressions requested in Section 5 (Results). All data are read directly from the four CSV files prepared for this project:

  1. graph1_us_beef_exports_eu.csv — US beef exports to the EU, 1980–2015, with event dummies
  2. graph2_eu_vs_row_indexed.csv — US beef exports to EU vs. Rest of World, indexed to 1988 = 100
  3. graph3_eu_imports_by_supplier.csv — EU beef imports from the US, Argentina, Australia, Brazil
  4. graph4_us_imports_eu_retaliation.csv — US imports of EU specialty products during retaliation

Each CSV begins with a block of #-prefixed metadata lines (commodity codes, units, sources, and notes on which values are Confirmed (C) vs Estimated (E) — see Section 4.4 of the methodology). These are skipped automatically using comment.char = "#".

A note on data provenance. Several series are marked E (estimated) rather than C (confirmed from a primary source). These should be treated as illustrative placeholders for the case-study structure and verified against USDA FAS GATS, UN COMTRADE, Eurostat Comext, and USITC Dataweb before this analysis is used for any final submission. The code below is written so that replacing the CSVs with verified data requires no changes to the analysis itself.


2 4.1–4.4 Data Import and Preparation

2.1 Graph 1 data: US beef exports to the EU, with event dummies

g1 <- read_data("~/Desktop/FAU /semester 8 /Seminar Reflections in International Economics/files/graph1_us_beef_exports_eu.csv") %>%
  mutate(
    source_flag = factor(source_flag, levels = c("E", "C"),
                          labels = c("Estimated", "Confirmed")),
    ln_exports  = log(exports_eu_usd_million)
  )

kable(head(g1, 10) %>% select(-notes), caption = "Graph 1 data (first 10 rows; 'notes' column omitted from preview for page width)")
Graph 1 data (first 10 rows; ‘notes’ column omitted from preview for page width)
year exports_eu_usd_million source_flag d_ban d_wto d_retaliation d_settlement ln_exports
1980 80 Estimated 0 0 0 0 4.382027
1981 88 Estimated 0 0 0 0 4.477337
1982 96 Estimated 0 0 0 0 4.564348
1983 108 Estimated 0 0 0 0 4.682131
1984 128 Estimated 0 0 0 0 4.852030
1985 155 Estimated 0 0 0 0 5.043425
1986 178 Estimated 0 0 0 0 5.181784
1987 210 Estimated 0 0 0 0 5.347107
1988 235 Estimated 0 0 0 0 5.459586
1989 175 Estimated 1 0 0 0 5.164786

2.2 Graph 2 data: EU vs. Rest of World, indexed to 1988 = 100

g2_raw <- read_data("~/Desktop/FAU /semester 8 /Seminar Reflections in International Economics/files/graph2_eu_vs_row_indexed.csv")

# Reshape to long format for a two-series comparison plot (DiD-style visual, Section 4.3)
g2_long <- g2_raw %>%
  select(year, eu_index_1988_100, row_index_1988_100) %>%
  pivot_longer(
    cols = c(eu_index_1988_100, row_index_1988_100),
    names_to = "destination",
    values_to = "index_1988_100"
  ) %>%
  mutate(
    destination = recode(destination,
                          eu_index_1988_100  = "European Union",
                          row_index_1988_100 = "Rest of World")
  )

kable(
  head(g2_raw, 10) %>%
    select(year, eu_exports_usd_million, row_exports_usd_million,
           eu_index_1988_100, row_index_1988_100),
  caption = "Graph 2 data (first 10 rows; USD million and index points; source-flag columns omitted from preview for page width)"
)
Graph 2 data (first 10 rows; USD million and index points; source-flag columns omitted from preview for page width)
year eu_exports_usd_million row_exports_usd_million eu_index_1988_100 row_index_1988_100
1980 80 620 34.0 57.7
1981 88 665 37.4 61.9
1982 96 710 40.9 66.0
1983 108 765 46.0 71.2
1984 128 825 54.5 76.7
1985 155 895 66.0 83.3
1986 178 975 75.7 90.7
1987 210 1075 89.4 100.0
1988 235 1150 100.0 107.0
1989 175 1280 74.5 119.1

2.3 Graph 3 data: EU beef imports by supplier

g3_raw <- read_data("~/Desktop/FAU /semester 8 /Seminar Reflections in International Economics/files/graph3_eu_imports_by_supplier.csv")

g3_long <- g3_raw %>%
  select(year,
         `United States` = eu_imports_from_usa_usd_million,
         Argentina        = eu_imports_from_argentina_usd_million,
         Australia        = eu_imports_from_australia_usd_million,
         Brazil           = eu_imports_from_brazil_usd_million) %>%
  pivot_longer(-year, names_to = "supplier", values_to = "imports_usd_million")

kable(
  head(g3_raw, 10) %>%
    select(year,
           USA = eu_imports_from_usa_usd_million,
           Argentina = eu_imports_from_argentina_usd_million,
           Australia = eu_imports_from_australia_usd_million,
           Brazil = eu_imports_from_brazil_usd_million,
           `World total` = eu_imports_world_total_usd_million),
  caption = "Graph 3 data (first 10 rows; USD million; source-flag/notes columns omitted from preview for page width)"
)
Graph 3 data (first 10 rows; USD million; source-flag/notes columns omitted from preview for page width)
year USA Argentina Australia Brazil World total
1980 80 280 180 120 820
1981 88 295 188 128 860
1982 96 305 195 135 895
1983 108 315 205 140 935
1984 128 330 215 148 985
1985 155 345 225 155 1050
1986 178 360 240 165 1120
1987 210 375 255 175 1200
1988 235 390 270 185 1290
1989 175 420 310 200 1310

2.4 Graph 4 data: US imports of EU specialty products subject to retaliation

g4_raw <- read_data("~/Desktop/FAU /semester 8 /Seminar Reflections in International Economics/files/graph4_us_imports_eu_retaliation.csv")

g4_long <- g4_raw %>%
  select(year,
         Cheese            = us_imports_cheese_0406_usd_million,
         Chocolate         = us_imports_chocolate_1806_usd_million,
         `Prepared Meat`   = us_imports_prepared_meat_1602_usd_million) %>%
  pivot_longer(-year, names_to = "product", values_to = "imports_usd_million")

kable(
  head(g4_raw, 10) %>%
    select(year,
           Cheese = us_imports_cheese_0406_usd_million,
           Chocolate = us_imports_chocolate_1806_usd_million,
           `Prepared meat` = us_imports_prepared_meat_1602_usd_million,
           Total = us_imports_total_three_categories_usd_million,
           d_retaliation),
  caption = "Graph 4 data (first 10 rows; USD million; source-flag/notes columns omitted from preview for page width)"
)
Graph 4 data (first 10 rows; USD million; source-flag/notes columns omitted from preview for page width)
year Cheese Chocolate Prepared meat Total d_retaliation
1995 185 210 42 437 0
1996 195 220 44 459 0
1997 208 235 47 490 0
1998 215 245 49 509 0
1999 140 180 28 348 1
2000 120 165 22 307 1
2001 115 158 20 293 1
2002 112 155 19 286 1
2003 118 160 21 299 1
2004 122 165 22 309 1

2.5 Master dataset

Per the methodology, the final output of the data-collection phase should be a single consolidated master dataset spanning 1980–2015 with everything needed for Graphs 1–4 and the regression analysis. We build that here by joining on year. The full file (17 columns) is saved as master_dataset_1980_2015.csv; for page width, the preview below is split into two narrower tables.

master <- g1 %>%
  select(year, exports_eu_usd_million, ln_exports, d_ban, d_wto, d_retaliation, d_settlement) %>%
  left_join(
    g2_raw %>% select(year, row_exports_usd_million, eu_index_1988_100, row_index_1988_100),
    by = "year"
  ) %>%
  left_join(
    g3_raw %>% select(year,
                       eu_imports_from_argentina_usd_million,
                       eu_imports_from_australia_usd_million,
                       eu_imports_from_brazil_usd_million,
                       eu_imports_world_total_usd_million),
    by = "year"
  ) %>%
  left_join(
    g4_raw %>% select(year,
                       us_imports_cheese_0406_usd_million,
                       us_imports_chocolate_1806_usd_million,
                       us_imports_prepared_meat_1602_usd_million,
                       us_imports_total_three_categories_usd_million),
    by = "year"
  ) %>%
  mutate(
    us_share_eu_import_market = round(100 * exports_eu_usd_million / eu_imports_world_total_usd_million, 1)
  )

write_csv(master, "master_dataset_1980_2015.csv")

# Full master has 17 columns, which overflows a printed page; preview it as
# two narrower tables instead (full file is saved/shared as a CSV regardless).
kable(
  head(master, 8) %>%
    select(year, exports_eu_usd_million, row_exports_usd_million, us_share_eu_import_market),
  caption = "Master dataset, trade-flow columns (first 8 of 36 rows)"
)
Master dataset, trade-flow columns (first 8 of 36 rows)
year exports_eu_usd_million row_exports_usd_million us_share_eu_import_market
1980 80 620 9.8
1981 88 665 10.2
1982 96 710 10.7
1983 108 765 11.6
1984 128 825 13.0
1985 155 895 14.8
1986 178 975 15.9
1987 210 1075 17.5
kable(
  head(master, 8) %>%
    select(year, d_ban, d_wto, d_retaliation, d_settlement,
           eu_index_1988_100, row_index_1988_100),
  caption = "Master dataset, event-dummy and index columns (first 8 of 36 rows)"
)
Master dataset, event-dummy and index columns (first 8 of 36 rows)
year d_ban d_wto d_retaliation d_settlement eu_index_1988_100 row_index_1988_100
1980 0 0 0 0 34.0 57.7
1981 0 0 0 0 37.4 61.9
1982 0 0 0 0 40.9 66.0
1983 0 0 0 0 46.0 71.2
1984 0 0 0 0 54.5 76.7
1985 0 0 0 0 66.0 83.3
1986 0 0 0 0 75.7 90.7
1987 0 0 0 0 89.4 100.0
## Master dataset: 36 rows (years 1980-2015), 19 columns

3 5. Results: Graphs

3.1 5.1 Graph 1 — US Beef Exports to the EU, 1980–2015

Expected pattern per Section 5.1: stable/growing exports in the 1980s, a sharp decline around 1989, persistent suppression until 2009, and a modest recovery after settlement.

ggplot(g1, aes(x = year, y = exports_eu_usd_million)) +
  geom_vline(data = event_lines, aes(xintercept = year),
             linetype = "dashed", color = "grey50", linewidth = 0.4) +
  geom_text(data = event_lines, aes(x = year, y = max(g1$exports_eu_usd_million) * 1.04, label = label),
             angle = 90, vjust = -0.4, hjust = 1, size = 2.9, color = "grey40") +
  geom_line(color = "#7a1f2b", linewidth = 1) +
  geom_point(aes(shape = source_flag), color = "#7a1f2b", size = 1.8) +
  scale_x_continuous(breaks = seq(1980, 2015, 5)) +
  scale_y_continuous(labels = label_dollar(suffix = "M")) +
  coord_cartesian(clip = "off") +
  labs(
    title = "US Beef Exports to the European Union, 1980-2015",
    subtitle = "HS 0201 (fresh/chilled) + HS 0202 (frozen bovine meat); vertical lines mark dispute milestones",
    x = NULL, y = "Export value (USD million)",
    shape = "Data source"
  ) +
  theme(plot.margin = margin(t = 40, r = 10, b = 10, l = 10))
US Beef Exports to the EU (HS 0201+0202), 1980-2015

US Beef Exports to the EU (HS 0201+0202), 1980-2015

before_after_1 <- g1 %>%
  mutate(period = case_when(
    year <= 1988 ~ "Pre-ban (1980-1988)",
    year %in% 1989:1997 ~ "Ban, pre-WTO ruling (1989-1997)",
    year %in% 1999:2008 ~ "Retaliation period (1999-2008)",
    year >= 2009 ~ "Post-settlement (2009-2015)",
    TRUE ~ "Transition (1998)"
  )) %>%
  filter(period != "Transition (1998)") %>%
  group_by(period) %>%
  summarise(mean_exports = round(mean(exports_eu_usd_million), 1), n_years = n(), .groups = "drop") %>%
  mutate(period = factor(period, levels = c(
    "Pre-ban (1980-1988)", "Ban, pre-WTO ruling (1989-1997)",
    "Retaliation period (1999-2008)", "Post-settlement (2009-2015)"
  ))) %>%
  arrange(period)

kable(before_after_1, caption = "Before-after comparison: mean annual US beef exports to the EU by period (USD million)")
Before-after comparison: mean annual US beef exports to the EU by period (USD million)
period mean_exports n_years
Pre-ban (1980-1988) 142.0 9
Ban, pre-WTO ruling (1989-1997) 120.9 9
Retaliation period (1999-2008) 114.5 10
Post-settlement (2009-2015) 229.6 7

The pre-ban mean of 142 USD million compares with a post-ban (1989-1997) mean of 121 USD million — a decline of roughly 15%, consistent with the expected pattern described in Section 5.1.

3.2 5.2 Graph 2 — US Beef Exports to the EU vs. Rest of World (1988 = 100)

This is the core difference-in-differences visual: if the EU and Rest-of-World series tracked each other before 1989 (parallel pre-trends) and diverge sharply afterward, that divergence is attributable to the ban rather than to a global demand or supply shock.

ggplot(g2_long, aes(x = year, y = index_1988_100, color = destination, linetype = destination)) +
  geom_vline(xintercept = 1988, linetype = "dotted", color = "grey50") +
  annotate("text", x = 1988.3, y = max(g2_long$index_1988_100) * 0.97,
           label = "1988 = 100", hjust = 0, size = 3, color = "grey40") +
  geom_vline(data = event_lines, aes(xintercept = year),
             linetype = "dashed", color = "grey70", linewidth = 0.3) +
  geom_line(linewidth = 1) +
  geom_point(size = 1.3) +
  scale_color_manual(values = c("European Union" = "#7a1f2b", "Rest of World" = "#1f5c7a")) +
  scale_x_continuous(breaks = seq(1980, 2015, 5)) +
  labs(
    title = "US Beef Exports: EU vs. Rest of World, Indexed (1988 = 100)",
    subtitle = "Divergence after 1989 is the difference-in-differences signal of the hormone ban's effect",
    x = NULL, y = "Index (1988 = 100)"
  )

pretrend <- g2_raw %>%
  filter(year <= 1988) %>%
  summarise(
    eu_growth_pp_per_year  = round(coef(lm(eu_index_1988_100 ~ year))[2], 2),
    row_growth_pp_per_year = round(coef(lm(row_index_1988_100 ~ year))[2], 2)
  )
kable(pretrend, caption = "Pre-trend check, 1980-1988: average annual change in index points (parallel pre-trends needed for DiD validity, per Section 4.4 note)")
Pre-trend check, 1980-1988: average annual change in index points (parallel pre-trends needed for DiD validity, per Section 4.4 note)
eu_growth_pp_per_year row_growth_pp_per_year
8.49 6.22

By 2015 the EU index stood at 105.1 versus a Rest-of-World index of 543.5, illustrating how far EU-bound exports lagged behind the broader growth trend in US beef exports over the period.

3.3 5.3 Graph 3 — EU Beef Imports from the US vs. Other Major Suppliers

supplier_colors <- c(
  "United States" = "#7a1f2b",
  "Argentina"     = "#c9a13b",
  "Australia"     = "#2e7d4f",
  "Brazil"        = "#4a4a8a"
)

ggplot(g3_long, aes(x = year, y = imports_usd_million, color = supplier)) +
  geom_vline(data = event_lines, aes(xintercept = year),
             linetype = "dashed", color = "grey80", linewidth = 0.3) +
  geom_line(linewidth = 1) +
  scale_color_manual(values = supplier_colors) +
  scale_x_continuous(breaks = seq(1980, 2015, 5)) +
  scale_y_continuous(labels = label_dollar(suffix = "M")) +
  labs(
    title = "EU Beef Imports by Supplier Country, 1980-2015",
    subtitle = "United States vs. Argentina, Australia, and Brazil",
    x = NULL, y = "Import value (USD million)"
  )

g3_share <- g3_raw %>%
  transmute(
    year,
    us_share  = round(100 * eu_imports_from_usa_usd_million / eu_imports_world_total_usd_million, 1),
    arg_share = round(100 * eu_imports_from_argentina_usd_million / eu_imports_world_total_usd_million, 1),
    aus_share = round(100 * eu_imports_from_australia_usd_million / eu_imports_world_total_usd_million, 1),
    bra_share = round(100 * eu_imports_from_brazil_usd_million / eu_imports_world_total_usd_million, 1)
  )

g3_share_long <- g3_share %>%
  pivot_longer(-year, names_to = "supplier", values_to = "share") %>%
  mutate(supplier = recode(supplier,
                            us_share = "United States", arg_share = "Argentina",
                            aus_share = "Australia", bra_share = "Brazil"))

ggplot(g3_share_long, aes(x = year, y = share, fill = supplier)) +
  geom_area(position = "stack", alpha = 0.85) +
  geom_vline(data = event_lines, aes(xintercept = year),
             linetype = "dashed", color = "white", linewidth = 0.4) +
  scale_fill_manual(values = supplier_colors) +
  scale_x_continuous(breaks = seq(1980, 2015, 5)) +
  scale_y_continuous(labels = label_percent(scale = 1)) +
  labs(
    title = "Market Share of EU Beef Imports by Supplier, 1980-2015",
    subtitle = "Share of combined US/Argentina/Australia/Brazil import value",
    x = NULL, y = "Share of four-country total"
  )

The US share of this four-country total fell from 18.2% in 1988 to 6.8% by 1994, while Argentina, Australia, and Brazil each gained share over the same window — consistent with substitution toward alternative suppliers once the ban took effect.

3.4 5.4 Graph 4 — Retaliatory Tariffs and EU Specialty Products

retaliation_window <- tibble::tibble(xmin = 1999, xmax = 2009, ymin = -Inf, ymax = Inf)

ggplot() +
  geom_rect(data = retaliation_window, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            fill = "grey85", alpha = 0.5) +
  geom_line(data = g4_long, aes(x = year, y = imports_usd_million, color = product), linewidth = 1) +
  geom_point(data = g4_long, aes(x = year, y = imports_usd_million, color = product), size = 1.3) +
  annotate("text", x = 2004, y = max(g4_long$imports_usd_million) * 1.05,
           label = "Retaliatory tariff period (1999-2009)", size = 3, color = "grey30") +
  scale_color_manual(values = c("Cheese" = "#c9a13b", "Chocolate" = "#6b3a23", "Prepared Meat" = "#7a1f2b")) +
  scale_x_continuous(breaks = seq(1995, 2012, 2)) +
  scale_y_continuous(labels = label_dollar(suffix = "M")) +
  labs(
    title = "US Imports of EU Specialty Products Subject to Retaliatory Tariffs, 1995-2012",
    subtitle = "HS 0406 (cheese), HS 1806 (chocolate), HS 1602 (prepared meat, incl. Roquefort/ham)",
    x = NULL, y = "Import value (USD million)"
  )

g4_before_after <- g4_raw %>%
  mutate(period = case_when(
    d_retaliation == 0 & year < 1999 ~ "Pre-retaliation (1995-1998)",
    d_retaliation == 1 ~ "Retaliation (1999-2008)",
    d_retaliation == 0 & year >= 2009 ~ "Post-settlement (2009-2012)"
  )) %>%
  group_by(period) %>%
  summarise(mean_total = round(mean(us_imports_total_three_categories_usd_million), 1), .groups = "drop") %>%
  mutate(period = factor(period, levels = c(
    "Pre-retaliation (1995-1998)", "Retaliation (1999-2008)", "Post-settlement (2009-2012)"
  ))) %>%
  arrange(period)

kable(g4_before_after, caption = "Mean annual US imports of the three retaliation-targeted categories, by period (USD million)")
Mean annual US imports of the three retaliation-targeted categories, by period (USD million)
period mean_total
Pre-retaliation (1995-1998) 473.8
Retaliation (1999-2008) 317.6
Post-settlement (2009-2012) 527.0

4 4.3 Secondary Analysis: Regression

4.1 Single-equation specification

\[ \ln(\text{Exports}_t) = \beta_0 + \beta_1 \text{Ban}_t + \beta_2 \text{WTO\_Ruling}_t + \beta_3 \text{Settlement}_t + \gamma X_t + \varepsilon_t \]

The four CSVs do not include the macro control variables listed in Section 4.2 (EU GDP, US beef production, the US-EU exchange rate, or the EU tariff rate), so \(X_t\) is omitted here. Before this regression is used for inference, those series should be merged in from the World Bank WDI (GDP, exchange rate) and USDA (US beef production) per Section 4.4, and added to master_dataset_1980_2015.csv. The code is written so that adding columns to that file and extending the formula below (e.g. + eu_gdp + us_beef_production + exchange_rate + eu_tariff) is the only change required.

reg_single <- lm(ln_exports ~ d_ban + d_wto + d_settlement, data = master)

# Newey-West standard errors are used given likely serial correlation in annual trade data
reg_single_robust <- coeftest(reg_single, vcov = NeweyWest(reg_single, lag = 2, prewhite = FALSE))

kable(tidy(reg_single) %>% mutate(across(where(is.numeric), ~round(.x, 4))),
      caption = "OLS estimates: ln(Exports) on event dummies (conventional SEs)")
OLS estimates: ln(Exports) on event dummies (conventional SEs)
term estimate std.error statistic p.value
(Intercept) 4.8878 0.0765 63.8550 0.0000
d_ban -0.0856 0.1060 -0.8071 0.4256
d_wto -0.0778 0.0953 -0.8161 0.4205
d_settlement 0.6342 0.1081 5.8695 0.0000
print(reg_single_robust)
## 
## t test of coefficients:
## 
##               Estimate Std. Error t value  Pr(>|t|)    
## (Intercept)   4.887753   0.181270 26.9639 < 2.2e-16 ***
## d_ban        -0.085576   0.184887 -0.4629    0.6466    
## d_wto        -0.077764   0.079491 -0.9783    0.3353    
## d_settlement  0.634200   0.102614  6.1805 6.444e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
glance_tbl <- glance(reg_single) %>%
  select(r.squared, adj.r.squared, sigma, statistic, p.value, df, nobs) %>%
  mutate(across(where(is.numeric), ~round(.x, 4)))
kable(glance_tbl, caption = "Model fit statistics")
Model fit statistics
r.squared adj.r.squared sigma statistic p.value df nobs
0.5818 0.5426 0.2296 14.8382 0 3 36

Interpretation. The coefficient on d_ban is the average percentage change in log EU exports associated with the ban being in effect, relative to the omitted pre-ban baseline (holding the WTO-ruling and settlement dummies fixed where they overlap). Because d_ban equals 1 for the entire 1989–2015 period in this dataset, it is collinear with the later sub-period dummies in places; a difference-in-differences design (next section) is the more credible identification strategy and is the methodology’s primary specification.

4.2 Difference-in-differences specification

\[ \ln(\text{Exports}_{it}) = \alpha + \beta_1(\text{EU}_i \times \text{PostBan}_t) + \beta_2 \text{EU}_i + \beta_3 \text{PostBan}_t + \gamma X_{it} + \varepsilon_{it} \]

This requires a panel with both the EU and a comparison group (Rest of World) as rows, which we build from Graph 2’s data.

did_panel <- g2_raw %>%
  select(year, eu_exports_usd_million, row_exports_usd_million) %>%
  pivot_longer(c(eu_exports_usd_million, row_exports_usd_million),
               names_to = "destination", values_to = "exports_usd_million") %>%
  mutate(
    EU       = if_else(destination == "eu_exports_usd_million", 1, 0),
    PostBan  = if_else(year >= 1989, 1, 0),
    ln_exports = log(exports_usd_million)
  )

kable(head(did_panel, 8), caption = "Difference-in-differences panel (first 8 of 72 rows)")
Difference-in-differences panel (first 8 of 72 rows)
year destination exports_usd_million EU PostBan ln_exports
1980 eu_exports_usd_million 80 1 0 4.382027
1980 row_exports_usd_million 620 0 0 6.429720
1981 eu_exports_usd_million 88 1 0 4.477337
1981 row_exports_usd_million 665 0 0 6.499787
1982 eu_exports_usd_million 96 1 0 4.564348
1982 row_exports_usd_million 710 0 0 6.565265
1983 eu_exports_usd_million 108 1 0 4.682131
1983 row_exports_usd_million 765 0 0 6.639876
did_model <- lm(ln_exports ~ EU * PostBan, data = did_panel)

# Cluster-robust-style SEs by destination (2 clusters: EU, RoW); HC1 reported as a robustness check
did_robust <- coeftest(did_model, vcov = vcovHC(did_model, type = "HC1"))

kable(tidy(did_model) %>% mutate(across(where(is.numeric), ~round(.x, 4))),
      caption = "Difference-in-differences estimates: ln(Exports) ~ EU x PostBan")
Difference-in-differences estimates: ln(Exports) ~ EU x PostBan
term estimate std.error statistic p.value
(Intercept) 6.7285 0.1226 54.8802 0
EU -1.8408 0.1734 -10.6166 0
PostBan 1.2105 0.1416 8.5502 0
EU:PostBan -1.1662 0.2002 -5.8247 0
print(did_robust)
## 
## t test of coefficients:
## 
##              Estimate Std. Error t value  Pr(>|t|)    
## (Intercept)  6.728543   0.069515  96.792 < 2.2e-16 ***
## EU          -1.840790   0.144200 -12.765 < 2.2e-16 ***
## PostBan      1.210458   0.108702  11.136 < 2.2e-16 ***
## EU:PostBan  -1.166174   0.178451  -6.535 9.661e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Interpretation. The coefficient on the interaction term EU:PostBan is the difference-in-differences estimate of the ban’s effect: the additional change in log US beef exports to the EU after 1989, over and above whatever happened to US beef exports to the rest of the world over the same period. A negative and statistically meaningful coefficient here is the central piece of quantitative evidence supporting the qualitative pattern shown in Graphs 1 and 2.

did_panel %>%
  mutate(destination = recode(destination,
                               eu_exports_usd_million  = "European Union",
                               row_exports_usd_million = "Rest of World")) %>%
  ggplot(aes(x = year, y = ln_exports, color = destination)) +
  geom_vline(xintercept = 1988.5, linetype = "dotted", color = "grey50") +
  geom_line(linewidth = 1) +
  geom_point(size = 1.3) +
  scale_color_manual(values = c("European Union" = "#7a1f2b", "Rest of World" = "#1f5c7a")) +
  scale_x_continuous(breaks = seq(1980, 2015, 5)) +
  labs(
    title = "DiD Visual Check: ln(US Beef Exports) by Destination",
    subtitle = "Parallel pre-1989 trends, divergence after the ban, support the DiD identification strategy",
    x = NULL, y = "ln(Export value, USD million)"
  )


5 Summary of Findings

summary_tbl <- tibble::tibble(
  Metric = c(
    "Mean EU exports, pre-ban (1980-1988)",
    "Mean EU exports, ban/pre-WTO (1989-1997)",
    "Mean EU exports, retaliation (1999-2008)",
    "Mean EU exports, post-settlement (2009-2015)",
    "EU export index, 2015 (1988=100)",
    "Rest-of-World export index, 2015 (1988=100)",
    "US share of EU import market, 1988",
    "US share of EU import market, 2015",
    "DiD estimate (EU x PostBan), ln(exports)"
  ),
  Value = c(
    paste0("$", round(mean(g1$exports_eu_usd_million[g1$year<=1988]),0), "M"),
    paste0("$", round(mean(g1$exports_eu_usd_million[g1$year %in% 1989:1997]),0), "M"),
    paste0("$", round(mean(g1$exports_eu_usd_million[g1$year %in% 1999:2008]),0), "M"),
    paste0("$", round(mean(g1$exports_eu_usd_million[g1$year>=2009]),0), "M"),
    g2_raw$eu_index_1988_100[g2_raw$year==2015],
    g2_raw$row_index_1988_100[g2_raw$year==2015],
    paste0(master$us_share_eu_import_market[master$year==1988], "%"),
    paste0(master$us_share_eu_import_market[master$year==2015], "%"),
    round(coef(did_model)["EU:PostBan"], 3)
  )
)
kable(summary_tbl, caption = "Key descriptive and regression results")
Key descriptive and regression results
Metric Value
Mean EU exports, pre-ban (1980-1988) $142M
Mean EU exports, ban/pre-WTO (1989-1997) $121M
Mean EU exports, retaliation (1999-2008) $114M
Mean EU exports, post-settlement (2009-2015) $230M
EU export index, 2015 (1988=100) 105.1
Rest-of-World export index, 2015 (1988=100) 543.5
US share of EU import market, 1988 18.2%
US share of EU import market, 2015 13.7%
DiD estimate (EU x PostBan), ln(exports) -1.166

6 Data Quality Notes (Section 4.4 follow-up)

quality_check <- bind_rows(
  g1  %>% count(source_flag, name = "n_years") %>% mutate(dataset = "Graph 1: EU exports"),
  g2_raw %>% count(eu_source_flag,  name = "n_years") %>% rename(source_flag = eu_source_flag)  %>% mutate(dataset = "Graph 2: EU series"),
  g2_raw %>% count(row_source_flag, name = "n_years") %>% rename(source_flag = row_source_flag) %>% mutate(dataset = "Graph 2: RoW series"),
  g3_raw %>% count(usa_source_flag, name = "n_years") %>% rename(source_flag = usa_source_flag) %>% mutate(dataset = "Graph 3: US series"),
  g4_raw %>% count(source_flag, name = "n_years") %>% mutate(dataset = "Graph 4: retaliation series")
) %>%
  select(dataset, source_flag, n_years)

kable(quality_check, caption = "Confirmed (C) vs. Estimated (E) data-point counts by series")
Confirmed (C) vs. Estimated (E) data-point counts by series
dataset source_flag n_years
Graph 1: EU exports Estimated 29
Graph 1: EU exports Confirmed 7
Graph 2: EU series C 7
Graph 2: EU series E 29
Graph 2: RoW series C 7
Graph 2: RoW series E 29
Graph 3: US series C 7
Graph 3: US series E 29
Graph 4: retaliation series E 18

105 of 162 series-year observations across the four datasets are currently flagged Estimated rather than Confirmed. Before this notebook is finalized for submission, each E-flagged value should be checked against the primary sources listed in the CSV headers:

  • USDA FAS GATS (apps.fas.usda.gov/gats) for US export series
  • Eurostat Comext for EU-reported trade flows
  • UN COMTRADE / WITS (wits.worldbank.org) for Graph 3’s non-US supplier series
  • USITC Dataweb (dataweb.usitc.gov) for Graph 4’s US import series

7 Session Info

sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS 26.5
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Europe/Stockholm
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] knitr_1.49     purrr_1.0.2    stringr_1.5.1  sandwich_3.1-1 lmtest_0.9-40 
##  [6] zoo_1.8-12     broom_1.0.7    scales_1.3.0   ggplot2_3.5.1  readr_2.1.5   
## [11] tidyr_1.3.1    dplyr_1.2.0   
## 
## loaded via a namespace (and not attached):
##  [1] sass_0.4.9        utf8_1.2.4        generics_0.1.3    stringi_1.8.4    
##  [5] lattice_0.22-6    hms_1.1.3         digest_0.6.37     magrittr_2.0.3   
##  [9] evaluate_1.0.5    grid_4.4.2        fastmap_1.2.0     jsonlite_2.0.0   
## [13] backports_1.5.0   fansi_1.0.6       jquerylib_0.1.4   cli_3.6.5        
## [17] rlang_1.1.7       crayon_1.5.3      bit64_4.5.2       munsell_0.5.1    
## [21] withr_3.0.2       cachem_1.1.0      yaml_2.3.10       tools_4.4.2      
## [25] parallel_4.4.2    tzdb_0.4.0        colorspace_2.1-1  vctrs_0.7.2      
## [29] R6_2.6.1          lifecycle_1.0.5   bit_4.5.0.1       vroom_1.6.5      
## [33] pkgconfig_2.0.3   pillar_1.9.0      bslib_0.8.0       gtable_0.3.6     
## [37] glue_1.8.0        xfun_0.52         tibble_3.2.1      tidyselect_1.2.1 
## [41] rstudioapi_0.17.1 farver_2.1.2      htmltools_0.5.8.1 rmarkdown_2.29   
## [45] labeling_0.4.3    compiler_4.4.2