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:
graph1_us_beef_exports_eu.csv — US beef exports to the
EU, 1980–2015, with event dummiesgraph2_eu_vs_row_indexed.csv — US beef exports to EU
vs. Rest of World, indexed to 1988 = 100graph3_eu_imports_by_supplier.csv — EU beef imports
from the US, Argentina, Australia, Brazilgraph4_us_imports_eu_retaliation.csv — US imports of EU
specialty products during retaliationEach 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 thanC(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.
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)")
| 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 |
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)"
)
| 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 |
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)"
)
| 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 |
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)"
)
| 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 |
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)"
)
| 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)"
)
| 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
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
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)")
| 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.
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)")
| 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.
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.
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)")
| period | mean_total |
|---|---|
| Pre-retaliation (1995-1998) | 473.8 |
| Retaliation (1999-2008) | 317.6 |
| Post-settlement (2009-2012) | 527.0 |
\[ \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)")
| 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")
| 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.
\[ \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)")
| 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")
| 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)"
)
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")
| 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 |
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")
| 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:
apps.fas.usda.gov/gats)
for US export serieswits.worldbank.org) for Graph 3’s non-US supplier
seriesdataweb.usitc.gov) for
Graph 4’s US import seriessessionInfo()
## 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