- ๐ Introduction
- โจ Key Features
- ๐ฆ Installation
- ๐ Quick Start
- ๐งฎ Example 1: Full Sample Estimation
- ๐งฉ Example 2: Subsample Estimation
- ๐ Example 3: Subsample Estimation with Non-Positive Elasticities
- ๐ง Example 4: Estimation with User-Added Variables
- ๐ Citation
- ๐ค Contributing
- ๐ฌ Contact
rfcipDemand provides a reproducible pipeline for analyzing U.S.
Federal Crop Insurance Program (FCIP) demand.
It enables flexible modeling of participation, coverage, and elasticity
across counties, crops, and insurance plans.
Its empirical foundations build on:
- Tsiboe, F., & Turner, D. (2023). The crop insurance demand response to premium subsidies: Evidence from U.S. Agriculture. Food Policy, 119(3)
- Tsiboe, F., & Turner, D. (2023). Econometric identification of crop insurance participation. Agricultural and Resource Economics Review
- Builds harmonized FCIP panel datasets across crops, years, and insurance plans.
- Estimates multi-equation demand systems with endogenous premium rates.
- Supports heterogeneity and calibration to maintain economic consistency.
- Provides diagnostics for instrument validity and elasticity bounds.
- Integrates easily with other ARPC and NIFA-supported research pipelines.
Disclaimer: This package uses USDA data but is not endorsed by or affiliated with USDA or the Federal Government.
See LICENSE for terms.
# Install from GitHub
if (!requireNamespace("devtools", quietly = TRUE)) install.packages("devtools")
devtools::install_github("ftsiboe/rfcipDemand", force = TRUE, upgrade = "never")The three core functions are:
fcip_demand_data_dispatcher()โ assemble the modeling datafcip_demand_sys_estimate()โ estimate demand equationscalibrate_fcip_demand_elasticities()โ estimate with non-positive elasticities
In this example, we estimate a baseline FCIP demand system to evaluate
how demand changes with percentage changes in the premium rate.
This estimation uses the full sample, following the structure in Tsiboe
& Turner (2023) but with
updated RMA data.
๐ฆ Click to expand setup code
# library(rfcipDemand)
# 1) Identify fields for panel building
FCIP_INSURANCE_POOL <- c("state_code","county_code","commodity_code","type_code","practice_code")
# 2) Build data (example years - keep short so examples are fast)
df <- fcip_demand_data_dispatcher(
study_years = 2001:2024,
identifiers = c("commodity_year", FCIP_INSURANCE_POOL, "insurance_plan_code", "unit_structure_code")
)
# Set price to 1 for crops with no RP/RP-HPE options [NEW]
df[insurance_plan_code %in% c(1L, 90L), insurance_plan_code := 1L]
df[insurance_plan_code %in% c(44L, 2L), insurance_plan_code := 2L]
df[insurance_plan_code %in% c(25L, 42L, 3L), insurance_plan_code := 3L]
df[, rp_eligible := max(as.numeric(insurance_plan_code %in% 2:3)), by = "commodity_code"]
df[rp_eligible == 0, price := 1]
# 3) Prep variables
data <- as.data.frame(df)
data$net_reporting_level_amount <- log(data$net_reporting_level_amount/10000)
data$coverage_level_percent_aggregate <- log(data$coverage_level_percent_aggregate)
data$rate <- log(data$premium_per_liability*(1-data$subsidy_per_premium))
data$county_acreage <- log(data$county_acreage/10000)
data$rent <- log(data$rent/1000)
data$price <- log(data$price)
data$tauS0 <- log(data$tau*(1-((data$subsidy_rate_65+data$subsidy_rate_75)/2)))
data$trend <- data$commodity_year - min(data$commodity_year, na.rm=TRUE)
for(i in unique(data$commodity_code)){ data[,paste0("Crop_",i)] <- ifelse(data$commodity_code %in% i,1,0)*data$trend }
for(i in unique(data$commodity_year)){ data[,paste0("year_",i)] <- ifelse(data$commodity_year %in% i,1,0) }
data <- data[names(data)[!names(data) %in% c(paste0("year_",max(data$commodity_year,na.rm=T)),"Crop_41")]]Estimate model
# Specify the system
model <- list(
name = "demo_sys",
FE = TRUE,
outcome = c("net_reporting_level_amount","coverage_level_percent_aggregate"),
endogenous = "rate",
excluded = "tauS0",
partial = c("trend", names(data)[grepl("Crop_", names(data))],
names(data)[grepl("year_", names(data))]),
disag = NULL,
included = c("county_acreage","price","rent")
)
# Estimate demand system
res <- fcip_demand_sys_estimate(model = model, data = data)
# Save results
write.csv(res, "data-raw/examples/example1.csv", row.names = FALSE)Discussion:
The premium rate enters with a negative sign as expected, indicating that higher producer-paid premiums reduce insurance demand.
County acreage remains the strongest driver of participation across all margins. For more detailes on the resulst see Example 1 โ Discussion of Results โ
This example explores heterogeneity in demand response across
subgroupsโspecifically by commodity using the variable CROP.
# Specify the system
model <- list(
name = "demo_sys",
FE = TRUE,
outcome = c("net_reporting_level_amount","coverage_level_percent_aggregate"),
endogenous = "rate",
excluded = "tauS0",
partial = c("trend", names(data)[grepl("year_", names(data))]),
disag = "CROP",
included = c("county_acreage","price","rent")
)
# Estimate demand system
res <- fcip_demand_sys_estimate(model = model, data = data)
# Save results
write.csv(res, "data-raw/examples/example2.csv", row.names = FALSE)Note: This setup allows estimation of separate elasticities and participation effects for each commodity group.
This example estimates demand heterogeneity while constraining elasticities to be non-positive, ensuring consistency with the law of demand.
# Prep data
df2 <- fcip_demand_data_dispatcher(
study_years = 2001:2024,
identifiers = c("commodity_year", FCIP_INSURANCE_POOL,
"insurance_plan_code", "unit_structure_code")
)
# Specify and Estimate demand system
res <- calibrate_fcip_demand_elasticities(
calibration_year = 2024,
estimation_window = 5,
data = df2,
disaggregate = "CROP"
)
# Save results
write.csv(res, "data-raw/examples/example3.csv", row.names = FALSE)Insight:
Capping elasticities between โ2 and 0 ensures stable simulation behavior and adherence to demand theory.
fcip_demand_data_dispatcher() generates a standard analysis-ready
dataset.
Users can merge additional variables of interest (e.g., external climate
or policy data) by matching on identifiers such as state_code,
county_code, and commodity_year.
If a new variable (ramble) is: - Exogenous โ add under
included - Endogenous โ add under endogenous and specify
instruments under excluded
# Prep data
exampleX_data <- unique(data[c("state_code", "commodity_year", "county_code")])
set.seed(123)
exampleX_data$ramble <- runif(nrow(exampleX_data), min = 0, max = 1)
data4 <- dplyr::inner_join(data, exampleX_data, by = c("state_code", "commodity_year", "county_code"))
# Specify the system
model <- list(
name = "demo_sys",
FE = TRUE,
outcome = c("net_reporting_level_amount", "coverage_level_percent_aggregate"),
endogenous = "rate",
excluded = "tauS0",
partial = c("trend",
names(data4)[grepl("Crop_", names(data4))],
names(data4)[grepl("year_", names(data4))]),
disag = NULL,
included = c("county_acreage","price","rent","ramble")
)
# Estimate demand system
res <- fcip_demand_sys_estimate(model = model, data = data4)
# Save results
write.csv(res, "data-raw/examples/example4.csv", row.names = FALSE)Tip: Adding stochastic variables like
ramblehelps test robustness and explore model sensitivity under simulated shocks.
If you use rfcipDemand in your research, please cite:
-
Tsiboe, F., & Turner, D. (2023). The crop insurance demand response to premium subsidies: Evidence from U.S. Agriculture.
Food Policy, 119(3). https://doi.org/10.1016/j.foodpol.2023.102505 -
Tsiboe, F., & Turner, D. (2023). Econometric identification of crop insurance participation.
Agricultural and Resource Economics Review. https://doi.org/10.1017/age.2023.13
Contributions, issues, and feature requests are welcome.
Please see the Code of Conduct.
Questions or collaboration ideas?
Email Francis Tsiboe at ftsiboe@hotmail.com.
โญ Star this repository if you find it useful!