The emburden package provides tools for analyzing household energy burden using the Net Energy Return (Nh) methodology. This vignette will walk you through the basic workflow for calculating and analyzing energy burden metrics.
You can install emburden from GitHub:
Energy burden is the ratio of household energy spending to gross income:
Energy Burden (EB) = S / G
Where: - S = Energy spending (electricity, gas, other fuels) - G = Gross household income
A household spending $3,000 on energy with $50,000 income has a 6% energy burden.
# Calculate energy burden for a single household
gross_income <- 50000
energy_spending <- 3000
# Method 1: Direct energy burden
eb <- energy_burden_func(gross_income, energy_spending)
print(paste("Energy Burden:", scales::percent(eb)))
#> [1] "Energy Burden: 6%"
# Method 2: Via Net Energy Return (mathematically identical)
nh <- ner_func(gross_income, energy_spending)
neb <- 1 / (nh + 1)
print(paste("Net Energy Burden:", scales::percent(neb)))
#> [1] "Net Energy Burden: 6%"
print(paste("Net Energy Return:", round(nh, 2)))
#> [1] "Net Energy Return: 15.67"For a single household, both methods give the same result: 6% energy burden.
The package automatically downloads data from OpenEI on first use:
When working with pre-aggregated cohort data (total income and spending), calculate metrics from the totals:
# Calculate mean income and spending from totals
nc_data <- nc_ami %>%
mutate(
mean_income = total_income / households,
mean_energy_spending = (total_electricity_spend +
coalesce(total_gas_spend, 0) +
coalesce(total_other_spend, 0)) / households
) %>%
filter(!is.na(mean_income), !is.na(mean_energy_spending), households > 0) %>%
mutate(
eb = energy_burden_func(mean_income, mean_energy_spending),
nh = ner_func(mean_income, mean_energy_spending),
neb = neb_func(mean_income, mean_energy_spending)
)Important: Energy burden is a ratio and cannot be aggregated using arithmetic mean!
# ✅ CORRECT Method 1: Aggregate using Nh, then convert to NEB
nh_mean <- weighted.mean(nc_data$nh, nc_data$households)
neb_correct <- 1 / (1 + nh_mean)
# ✅ CORRECT Method 2: Use neb_func() with weights (simpler!)
# neb_func() automatically uses the Nh method internally
neb_correct2 <- neb_func(nc_data$mean_income,
nc_data$mean_energy_spending,
weights = nc_data$households)
print(paste("Correct NEB (manual Nh):", scales::percent(neb_correct)))
print(paste("Correct NEB (neb_func): ", scales::percent(neb_correct2)))
# Both give identical results!Why does this work? The Nh transformation allows us
to use simple arithmetic weighted mean instead of harmonic mean, making
aggregation both simpler and more intuitive. The neb_func()
with weights does this automatically.
# Method 1: Manual Nh aggregation
nc_by_income <- nc_data %>%
group_by(income_bracket) %>%
summarise(
households = sum(households),
nh_mean = weighted.mean(nh, households),
neb = 1 / (1 + nh_mean), # Correct aggregation
.groups = "drop"
)
# Method 2: Using neb_func() with weights (simpler!)
nc_by_income2 <- nc_data %>%
group_by(income_bracket) %>%
summarise(
neb = neb_func(mean_income, mean_energy_spending, weights = households),
households = sum(households),
.groups = "drop"
)
print(nc_by_income)The 6% energy burden threshold is commonly used to identify energy poverty:
# 6% energy burden corresponds to Nh = 15.67
high_burden_threshold <- 15.67
high_burden_households <- sum(nc_data$households[nc_data$nh < high_burden_threshold])
total_households <- sum(nc_data$households)
high_burden_pct <- (high_burden_households / total_households) * 100
print(paste("Households with >6% energy burden:",
scales::percent(high_burden_pct/100)))For more complex grouped analysis, use the built-in function:
results <- calculate_weighted_metrics(
graph_data = nc_ami,
group_columns = "income_bracket",
metric_name = "ner",
metric_cutoff_level = 15.67, # 6% burden threshold
upper_quantile_view = 0.95,
lower_quantile_view = 0.05
)
# Format for publication
results$formatted_median <- to_percent(results$metric_median)
print(results)The package provides a dedicated function for comparing energy burden across data vintages (2018 vs 2022):
# Compare by income bracket
comparison <- compare_energy_burden(
dataset = "ami",
states = "NC",
group_by = "income_bracket"
)
# View results
print(comparison)
# The function automatically:
# - Loads both 2018 and 2022 data
# - Normalizes schema differences (4 vs 6 AMI brackets)
# - Performs proper Nh-based aggregation
# - Calculates changes in energy burden
# Grouping options:
# - "income_bracket": Compare by AMI/FPL brackets (default)
# - "state": Compare multiple states
# - "none": Overall state-level comparison
# Example: State-level comparison
state_comparison <- compare_energy_burden(
dataset = "ami",
states = "NC",
group_by = "none"
)
# Access specific metrics
state_comparison$neb_2018 # 2018 energy burden
state_comparison$neb_2022 # 2022 energy burden
state_comparison$neb_change_pp # Change in percentage points
state_comparison$neb_change_pct # Relative change percentageThis is much simpler than manually loading and aggregating both vintages!
The LEAD Tool data includes detailed housing characteristics that enable analysis of how building attributes affect energy burden. Four key housing dimension columns are available:
These columns preserve granular housing detail through the data aggregation process, allowing you to analyze energy burden patterns across different housing types.
# Load data with housing characteristics
nc_housing <- load_cohort_data(dataset = "ami", states = "NC")
# Analyze energy burden by tenure and heating fuel
housing_analysis <- nc_housing %>%
filter(!is.na(TEN), !is.na(`TEN-HFL`)) %>%
mutate(
mean_income = total_income / households,
mean_energy_spending = (total_electricity_spend +
coalesce(total_gas_spend, 0) +
coalesce(total_other_spend, 0)) / households,
nh = ner_func(mean_income, mean_energy_spending)
) %>%
group_by(TEN, `TEN-HFL`) %>%
summarise(
total_households = sum(households),
nh_mean = weighted.mean(nh, households),
neb = 1 / (1 + nh_mean),
.groups = "drop"
) %>%
arrange(desc(neb))
# View the top 10 tenure-heating fuel combinations with highest burden
head(housing_analysis, 10)# Analyze by building characteristics
building_analysis <- nc_housing %>%
filter(!is.na(`TEN-YBL6`), !is.na(`TEN-BLD`)) %>%
mutate(
mean_income = total_income / households,
mean_energy_spending = (total_electricity_spend +
coalesce(total_gas_spend, 0) +
coalesce(total_other_spend, 0)) / households,
nh = ner_func(mean_income, mean_energy_spending)
) %>%
group_by(`TEN-YBL6`, `TEN-BLD`) %>%
summarise(
total_households = sum(households),
nh_mean = weighted.mean(nh, households),
neb = 1 / (1 + nh_mean),
.groups = "drop"
)
# Identify building age/type combinations with highest burden
high_burden_buildings <- building_analysis %>%
filter(neb > 0.06) %>% # Above 6% burden threshold
arrange(desc(neb))
print(high_burden_buildings)Housing characteristic analysis can reveal:
This granular analysis helps target energy efficiency interventions to the housing types and populations that need them most.
vignette("methodology") for mathematical
detailsNEB_QUICKSTART.md for quick referenceanalysis/scripts/ directory?energy_burden_func,
?ner_func