--- title: "Exercise template for 'Panel data'" author: Your name bibliography: book.bib format: html --- # Exercise template for 'Panel data' {#sec-panel-data} ```{r} #| label: libraries #| include: false library(tidyverse) library(farr) library(DBI) library(fixest) library(modelsummary) ``` ```{r} #| include: false db <- dbConnect(duckdb::duckdb()) seg_customer <- load_parquet(db, schema = "compseg", table = "seg_customer") names_seg <- load_parquet(db, schema = "compseg", table = "names_seg") funda <- load_parquet(db, schema = "comp", table = "funda") ``` ```{r} #| label: reg-data #| include: false #| cache: true #| cache.vars: ["reg_data"] sample_start <- as.Date("1994-01-01") sample_end <- as.Date("2010-12-31") disclosure_raw <- seg_customer |> filter(ctype == "COMPANY") |> filter(between(datadate, sample_start, sample_end)) |> collect() |> left_join(undisclosed_names, by = "cnms") |> mutate(disclosed = coalesce(disclosed, TRUE)) |> select(gvkey, datadate, cnms, salecs, disclosed) sales <- funda |> filter(indfmt == "INDL", datafmt == "STD", consol == "C", popsrc == "D") |> select(gvkey, datadate, sale) |> collect() biggest_customers <- disclosure_raw |> filter(disclosed) |> inner_join(sales, by = c("gvkey", "datadate")) |> filter(!is.na(sale), !is.na(salecs), sale > 0) |> group_by(gvkey, datadate) |> summarize(max_customer = max(salecs / sale), .groups = "drop") prin_custs <- disclosure_raw |> inner_join(sales, by = c("gvkey", "datadate")) |> group_by(gvkey, datadate) |> filter(!is.na(salecs), sale > 0) |> summarize(prin_cust = max(salecs / sale, na.rm = TRUE), .groups = "drop") |> mutate(has_prin_cust = prin_cust >= 0.1) disclosure <- disclosure_raw |> inner_join(sales, by = c("gvkey", "datadate")) |> semi_join(llz_2018, by = "gvkey") |> group_by(gvkey, datadate) |> summarize(ratio = mean(!disclosed), ratio_sale = sum((!disclosed) * salecs) / sum(salecs), .groups = "drop") |> mutate(year = year(datadate)) idd_periods <- get_idd_periods(min_date = sample_start, max_date = sample_end) ciks <- names_seg |> filter(!is.na(cik)) |> select(gvkey, cik) |> collect() state_hq_linked <- state_hq |> inner_join(ciks, by = "cik") |> inner_join(disclosure, join_by(gvkey, between(y$datadate, x$min_date, x$max_date))) |> select(gvkey, datadate, ba_state) |> rename(state = ba_state) reg_data <- disclosure |> inner_join(prin_custs, by = c("gvkey", "datadate")) |> filter(has_prin_cust) |> inner_join(state_hq_linked, by = c("gvkey", "datadate")) |> inner_join(idd_periods, join_by(state, datadate >= start_date, datadate <= end_date)) |> filter(period_type != "Post-rejection") |> mutate(post = period_type == "Post-adoption", ln_ratio = log(1 + ratio), ln_ratio_sale = log(1 + ratio_sale)) |> select(-start_date, -end_date) ``` ```{r} #| include: false dbDisconnect(db) rm(db, seg_customer, names_seg, funda) ``` ```{r} #| label: event-functions #| echo: true #| cache: true #| cache.vars: ["factor_t", "year_diff", "plot_coefs"] factor_t <- function(t, ref = -Inf) { t <- relevel(as.factor(t), ref = as.character(ref)) levels(t) <- str_replace(levels(t), "^([0-9]+)", "+\\1") levels(t) <- str_replace_all(levels(t), "([0-9]+)", " \\1") levels(t) <- str_replace(levels(t), "^", " ") levels(t) <- str_replace(levels(t), "-", "−") t } year_diff <- function(t, ref = -1) { t <- case_when(t < -5 ~ -5, t > 5 ~ 5, is.na(t) ~ -Inf, .default = t) factor_t(t, ref = ref) } plot_coefs <- function(fm, ref = -1) { coefs <- tibble(t = names(coef(fm)), value = coef(fm), se = se(fm)) |> filter(!str_detect(t, "Inf")) |> mutate(t = str_replace(t, "−", "-")) |> mutate(t = as.integer(str_replace_all(t, "[t ]+", ""))) ci <- 0.95 mult <- qnorm(1 - (1 - ci) / 2) tibble(t = ref, value = 0, se = 0) |> bind_rows(coefs) |> mutate(mean = value, top = value + mult * se, bot = value - mult * se) |> ggplot(aes(x = t, y = mean)) + geom_errorbar(aes(ymin = bot, ymax = top), width = .1) + geom_line() + geom_point() + scale_x_continuous(breaks = seq(from = min(coefs$t), to = max(coefs$t))) } ``` ```{r} #| label: supplied-models #| include: false #| message: false #| cache: true #| cache.vars: ["fms_orig", "switchers", "reg_data_switchers", "adoption_years", "reg_data_t", "fms_year"] #| dependson: [reg-data, event-functions] fms_orig <- list(feols(ln_ratio ~ post | gvkey + year, vcov = "iid", data = reg_data), feols(ln_ratio_sale ~ post | gvkey + year, vcov = "iid", data = reg_data)) switchers <- reg_data |> distinct(gvkey, post) |> group_by(gvkey) |> filter(n() > 1) |> select(gvkey) |> distinct() |> ungroup() reg_data_switchers <- reg_data |> semi_join(switchers, by = "gvkey") fms_orig[[3]] <- feols(ln_ratio ~ post | gvkey + year, vcov = "iid", data = reg_data_switchers) fms_orig[[4]] <- feols(ln_ratio_sale ~ post | gvkey + year, vcov = "iid", data = reg_data_switchers) adoption_years <- reg_data |> group_by(gvkey) |> arrange(datadate) |> filter(period_type == "Post-adoption", lag(period_type) == "Pre-adoption") |> group_by(gvkey) |> summarize(adoption_year = min(year), .groups = "drop") reg_data_t <- reg_data |> left_join(adoption_years, by = "gvkey") |> mutate(t = year_diff(year - adoption_year)) fms_year <- list(feols(ln_ratio ~ t | gvkey + year, vcov = "iid", data = reg_data_t), feols(ln_ratio_sale ~ t | gvkey + year, vcov = "iid", data = reg_data_t), feols(ln_ratio ~ t | gvkey + year, vcov = "iid", data = filter(reg_data_t, !str_detect(t, "Inf"))), feols(ln_ratio_sale ~ t | gvkey + year, vcov = "iid", data = filter(reg_data_t, !str_detect(t, "Inf")))) ``` ### Discussion questions 1. The proprietary cost hypothesis tested by @Li:2018tj posits that increased cost of disclosure will lead to reduced supply of disclosure. What rival theories exist that would make alternative predictions? Are there other elements of disclosure theory that might be tested? Why do you think @Li:2018tj focused on this specific element of the proprietary cost hypothesis? 2. In the analysis above, we do not include the control variables considered by @Li:2018tj. For example, @Li:2018tj "include R&D expenditures to sales, advertisement [sic] expenditure to sales, and intangible assets scaled by total assets to control for a firm's proprietary costs of disclosure." Using the approach outlined in [the causal inference chapter](https://iangow.github.io/far_book/causal-inf.html), in what circumstances would it be necessary to control for "a firm's proprietary costs of disclosure" in this way? Do these circumstances seem applicable in this setting, where the treatment is a (presumably exogenous) shock to disclosure costs and the outcome is disclosure choices? 3. What differs between the regressions reported in columns (1) and (3), and (2) and (4) of @tbl-table-2, respectively? Does this tell you anything about what drives the regression results in this setting? What happens if you omit the year fixed effects from both sets of regressions? What does this tell you about the role of the "non-switchers" (i.e., firms not in the `switchers` data frame) in the regression? ```{r} #| label: tbl-table-2 #| tbl-cap: "Effect of IDD adoption" #| echo: false #| output: asis modelsummary(fms_orig, estimate = "{estimate}{stars}", align = "cdddd", gof_map = c("nobs", "r.squared"), stars = c("*" = .1, "**" = .05, "***" = .01)) ``` 4. Would you expect the inclusion of controls (see the question above) to have a significant impact on the regression results? Why or why not? 5. What differs between the regressions reported in columns (1) and (3), and (2) and (4) of @tbl-idd-by-year, respectively? What happens if you omit the year fixed effects from both sets of regressions? What does this tell you about what drives the regression results in this setting? ```{r} #| label: tbl-idd-by-year #| tbl-cap: "Effect of IDD adoption by year" #| echo: false #| output: asis modelsummary(fms_year, estimate = "{estimate}{stars}", align = "cdddd", gof_map = c("nobs", "r.squared"), stars = c("*" = .1, "**" = .05, "***" = .01)) ``` 6. What patterns do you observe in the coefficients reported in @tbl-idd-by-year? Do these conform to what you would expect from @Li:2018tj? (It may be easiest to focus on these in groups, e.g., those in $t-5$ to $t-2$, those in $t + 0$ to $t+3$ and those for $t+4$ and $t+5$.) 7. How do the variables in @tbl-idd-by-year differ from those used in Table 3 of @Li:2018tj? Modify the code above (e.g., `year_diff()`) to produce analysis closer to that reported in Table 3 of @Li:2018tj. 8. The `year_diff()` function collapses years after $t + 5$ and before $t - 5$ into years $t + 5$ and $t - 5$, respectively. When would this approach make sense? What would be one alternative approach to handling these years? Does your suggested approach make a difference in this setting? 9. How helpful do you find @fig-coefs-by-year (plot of the coefficients by year)? ```{r} #| label: fig-coefs-by-year #| fig-cap: Plot of coefficients by year #| fig-height: 3 #| echo: false plot_coefs(fms_year[[1]]) ``` 10. Describe the data set created from the following code. What proportion of the firms in the data set have `same_state` equal to `TRUE`? For the purposes of empirical analysis, do the firms with `same_state` equal to `FALSE` enhance, or detract from, our ability to draw causal inferences about the effect of adoption of IDD? ```{r} switch_years <- reg_data_switchers |> group_by(gvkey) |> arrange(datadate) |> mutate(same_state = state == lag(state), adoption_year = period_type == "Post-adoption" & lag(period_type) == "Pre-adoption") |> filter(adoption_year) |> ungroup() ``` 11. What issues might be implied by the following data? How might you address these? ```{r} reg_data_t |> count(t) ```