diff --git a/.github/workflows/quarto-publish.yml b/.github/workflows/quarto-publish.yml index a830174..2533531 100644 --- a/.github/workflows/quarto-publish.yml +++ b/.github/workflows/quarto-publish.yml @@ -7,6 +7,9 @@ name: Render and Publish jobs: build-deploy: runs-on: ubuntu-latest + concurrency: + group: pages-deploy + cancel-in-progress: true steps: - name: Check out repository uses: actions/checkout@v4 diff --git a/_citations.qmd b/_citations.qmd index 8d2d466..3277416 100644 --- a/_citations.qmd +++ b/_citations.qmd @@ -15,7 +15,7 @@ day_2digit = date.getDate().toString().padStart(2, "0"); currentDate = `${month} ${day}, ${year}` // build a button -button = (blob, filename = 'test.bib', displayname) => { +citation_button = (blob, filename = 'test.bib', displayname) => { const button = DOM.download( blob, filename, @@ -49,7 +49,7 @@ biblatex_blob = new Blob([biblatexContent], { type: 'text/plain' }); ris_blob = new Blob([risContent], { type: 'text/plain' }); // Insert blobs into buttons -button(biblatex_blob, 'aetr_web_book_2024.bib', 'BibLaTeX'); -button(ris_blob, 'aetr_web_book_2024.ris', 'RIS'); +citation_button(biblatex_blob, 'aetr_web_book_2024.bib', 'BibLaTeX'); +citation_button(ris_blob, 'aetr_web_book_2024.ris', 'RIS'); ``` diff --git a/_quarto-pdf.yml b/_quarto-pdf.yml index e9826a8..fb1f702 100644 --- a/_quarto-pdf.yml +++ b/_quarto-pdf.yml @@ -6,8 +6,16 @@ book: chapters: - index.qmd + - methods.qmd + - consumption.qmd + - prices.qmd + - conclusions.qmd + - data.qmd appendices: - about.qmd + - historic_reports.qmd + - acronyms.qmd + - credits.qmd # These change page titles https://quarto.org/docs/books/book-structure.html#parts-appendices # but not in the sidebar navigation or in cross-references diff --git a/consumption.qmd b/consumption.qmd index 704484b..40d0728 100644 --- a/consumption.qmd +++ b/consumption.qmd @@ -7,40 +7,84 @@ output: quarto::quarto_html: pre_processor: quarto::observable echo: false +warning: false cap-location: top --- ```{r, echo=FALSE,warning=FALSE,message=FALSE} # Import packages +library(readr) library(dplyr) library(tidyr) +library(stringr) +library(ggplot2) +library(ggiraph) +library(scales) # Import the consumption data consumption_data <- read.csv(file = "data/final_data/consumption.csv") -# Regionalized consumption data +# Function declarations +source("scripts/inline_functions/consumption_inline_functions.R") + +``` + +```{r} +# Data transformations + +# Regionalized consumption transform regional_consumption_data <- consumption_data %>% group_by(acep_region, year, class) %>% summarise( - "revenue" = sum(revenue, na.rm = TRUE), - "sales" = sum(sales, na.rm = TRUE), - "customers" = sum(customers, na.rm = TRUE) + revenue = sum(revenue, na.rm = TRUE), + sales = sum(sales, na.rm = TRUE), + customers = sum(customers, na.rm = TRUE) ) %>% mutate( sales_per_capita = sales / customers ) -# Statewide consumption data +# Statewide consumption transform statewide_consumption_data <- consumption_data %>% group_by(year, class) %>% summarise( - "revenue" = sum(revenue, na.rm = TRUE), - "sales" = sum(sales, na.rm = TRUE), - "customers" = sum(customers, na.rm = TRUE) + revenue = sum(revenue, na.rm = TRUE), + sales = sum(sales, na.rm = TRUE), + customers = sum(customers, na.rm = TRUE) ) -# Function declarations -source("scripts/inline_functions/consumption_inline_functions.R") +# Statewide change transform +statewide_delta <- consumption_data %>% + group_by(year, class) %>% + summarize( + revenue = sum(revenue, na.rm = TRUE), + sales = sum(sales, na.rm = TRUE), + customers = sum(customers, na.rm = TRUE), + .groups = 'drop' + ) %>% + filter((year == 2011 | year == 2019) & class != "Total") %>% + arrange(year) %>% + group_by(class) %>% + mutate( + sales_2011 = lag(sales, default = 0), + customers_2011 = lag(customers, default = 0) + ) %>% + ungroup() %>% + mutate( + sales_delta = (sales - sales_2011) / sales_2011, + customers_delta = (customers - customers_2011) / customers_2011, + sales_delta_percent = sales_delta * 100 + ) %>% + filter(year == 2019) + +# Sales per capita transform +sales_per_capita_data <- + regional_consumption_data %>% + filter(class == "Residential") %>% + group_by(acep_region, year) %>% + mutate(sales_per_capita = (sales/customers) * 1000) %>% + ungroup() + ``` ## General Overview {#sec-consumption} @@ -57,509 +101,710 @@ Statewide electricity consumption growth for the residential sector was `r state -```{ojs} -// Import required libraries (condense later) -import {tidy, groupBy, rename, summarize, sum, mutate, select, n, nDistinct, mean, filter, pivotWider, pivotLonger, leftJoin, slice, fullJoin, lag, TMath, rowNumber,mutateWithSummary, arrange, asc} from "@pbeshai/tidyjs" - -// Import the consumption data -consumption_data = FileAttachment("data/final_data/consumption.csv").csv({ typed: true }) - -// Condense the data for regional plotting -regional_consumption_data = tidy( - consumption_data, - groupBy([ - "acep_region", "year", "class" - ], - [ - summarize({ - revenue: sum('revenue'), - sales: sum('sales'), - customers: sum('customers') - }) - ]) -).map((d) => ({...d, "Customer Class": d.class})).map((d) => ({...d, "ACEP Region": d.acep_region})) - -// Change in statewide totals -statewide_delta = tidy( - consumption_data, - groupBy( - ["year","class"], - summarize({ - revenue: sum("revenue"), - sales: sum("sales"), - customers: sum("customers") - }) - ), - filter((d) => (d.year === 2011 || d.year === 2019) && d.class !== "Total"), - arrange(["year", asc("year")]), - groupBy( - ["class"], - mutateWithSummary({ - sales_2011: lag("sales", {default: 0}), - customers_2011: lag("customers", {default: 0}), - }) - ), - mutate({ - sales_delta: (d) => (d.sales - d.sales_2011) / d.sales_2011, - customers_delta: (d) => (d.customers - d.customers_2011) / d.customers_2011, - }), - filter((d) => d.year === 2019) -).map((d) => ({...d, "Customer Class": d.class})) -``` -```{ojs} -//| label: fig-change-customer-sales -//| fig-cap: "Change in Sales by Customer Class, Statewide, from 2011 to 2019" - -Plot.plot({ - - //title: "Change in sales by customer class, statewide, from 2011 to 2019", - height: 500, - marginLeft: 70, - width: width, - - y: { - label:"", - grid: true, - domain: ["Residential","Commercial","Other"] - }, - - x: { - transform: (d) => d * 100, - domain: [-12,0], - label:"Percent Change" - }, - - marks: [ - Plot.frame(), - Plot.ruleX([0]), - Plot.barX(statewide_delta, - { - x: "sales_delta", - y: "Customer Class", - fill: "Customer Class", - tip: { - format: { - x: (d) => `${(d).toLocaleString(undefined, {maximumFractionDigits: 2})}%`, - y: false - } - } - } +```{r, eval=knitr::is_html_output()} +#| label: fig-change-customer-sales +#| fig-cap: "Change in Sales by Customer Class, Statewide, from 2011 to 2019" + +sales_html <- + sales_plot + + geom_bar_interactive( + stat = "identity", + aes( + tooltip = paste0( + round(sales_delta * 100, 1), + "% ", + "Change in Sales", + "
", + class, + " Customers")) ) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + +girafe( + code = print(sales_html)) +``` + +```{r, eval=knitr::is_latex_output()} +# code for static pdf plot +sales_pdf <- + sales_plot + + geom_bar(stat = "identity") + + labs( + title = "Change in Sales by Customer Class", + subtitle = "Statewide, from 2011 to 2019") + + theme( + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5)) + +print(sales_pdf) + ``` We also examine the change in the number of customer accounts across the state. The total number of customer accounts in the state increased `r statewide_consumption_delta("Total","customers",pct=TRUE)`% from approximately `r statewide_consumption("Total","customers",2011,decimals=0)` to `r statewide_consumption("Total","customers",2019,decimals=0)`. We plot the percentage increases in customer accounts by category in @fig-change-customer-accounts. Residential accounts across the state increased `r statewide_consumption_delta("Residential","customers",pct=TRUE)`% from approximately `r statewide_consumption("Residential","customers",2011,decimals=0)` to `r statewide_consumption("Residential","customers",2019,decimals=0)`. The number of commercial accounts across the state increased `r statewide_consumption_delta("Commercial","customers",pct=TRUE)`% from `r statewide_consumption("Commercial","customers",2011,decimals=0)` to `r statewide_consumption("Commercial","customers",2019,decimals=0)`. Finally, the number of other accounts across the state has increased `r statewide_consumption_delta("Other","customers",pct=TRUE)`% from approximately `r statewide_consumption("Other","customers",2011,decimals=0)` to `r statewide_consumption("Other","customers",2019,decimals=0)`. -```{ojs} -//| label: fig-change-customer-accounts -//| fig-cap: "Change in Customer Accounts by Class, Statewide, from 2011 to 2019" -Plot.plot({ - - //title: "Change in customer accounts by class, statewide, 2011 to 2019", - height: 500, - marginLeft: 70, - width: width, - - y: { - label:"", - grid: true, - domain: ["Residential","Commercial","Other"] - }, - - x: { - transform: (d) => d * 100, - domain: [0, 16], - label:"Percent Change" - }, - - marks: [ - Plot.frame(), - Plot.ruleX([0]), - Plot.barX(statewide_delta, - { - x: "customers_delta", - y: "Customer Class", - fill: "Customer Class", - tip: { - format: { - x: (d) => `${(d).toLocaleString(undefined, {maximumFractionDigits: 2})}%`, - y: false - } - } - } +```{r} +# statewide increase in customer accounts +# code for both html and pdf + +customers_plot <- + ggplot( + statewide_delta, + aes( + x = customers_delta * 100, + y = reorder(class, desc(customers_delta)), + fill = class)) + + + scale_x_continuous( + name = "Percent Change", + breaks = seq(0, 16, 2), + expand = c(0, 0.1)) + + + scale_y_discrete( + name = "", + expand = c(0, 0.5)) + + + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900")) + + + theme_minimal() + + theme( + legend.position = "none", + panel.grid.major.y = element_blank(), + panel.grid.minor = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + +``` + +```{r, eval=knitr::is_html_output()} +#| label: fig-change-customer-accounts +#| fig-cap: "Change in Customer Accounts by Class, Statewide, from 2011 to 2019" + +customers_html <- + customers_plot + + geom_bar_interactive( + stat = "identity", + aes( + tooltip = paste0( + round(customers_delta * 100, 1), + "% ", + "Change in Accounts", + "
", + class, + " Customers" + )) ) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + +girafe(code = print(customers_html)) + +``` + +```{r, eval=knitr::is_latex_output()} +# code for static pdf plot +customers_pdf <- + customers_plot + + geom_bar(stat = "identity") + + labs( + title = "Change in Customer Accounts by Class", + subtitle = "Statewide, from 2011 to 2019") + + +print(customers_pdf) + ``` @fig-sales_per_capita shows the average annual electricity consumption for each of the regions. The Coastal region led the state in consumption per capita, with an average of `r regional_consumption_per_capita("Coastal","Residential")` kWh per customer per year. This was followed by the Railbelt region with `r regional_consumption_per_capita("Railbelt","Residential")` kWh per capita and the Rural Remote region with `r regional_consumption_per_capita("Rural Remote","Residential")` kWh per capita. Overall, each region has seen reductions in consumption per capita, which may reflect improvements in energy efficient technologies and energy efficiency/conservation behaviors. -```{ojs} -sales_per_capita_data = tidy(regional_consumption_data.filter((d) => d.class === "Residential"), - groupBy( - ['ACEP Region','year'], - [ - mutate({ - sales_per_capita: (d) => (d.sales / d.customers) * 1000 - }) - ] - ) -) +```{r} +# code for both html and pdf + +# filter the last year for each region for the text labels +last_year_data <- sales_per_capita_data %>% + group_by() %>% + filter(year == max(year)) + +sales_per_capita_plot <- + ggplot( + sales_per_capita_data, + aes( + x = year, + y = sales_per_capita, + color = acep_region, + group = acep_region)) + + + geom_text( + data = last_year_data, + aes(label = acep_region), + hjust = 1.1, + vjust = 2.5) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1), + expand = c(0, 0.1)) + + + scale_y_continuous( + name = "Kilowatt Hours (kWh)", + limits = c(3000, 10000), + breaks = seq(3000, 10000, 1000), + labels = scales::comma, + expand = c(0, 0.2)) + + + scale_color_manual(values = c("#8CBBDA", "#97CD93", "#F28D8C")) + + theme_minimal() + + theme( + legend.position = "none", + panel.grid.minor = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + ``` -```{ojs} -//| label: fig-sales_per_capita -//| fig-cap: "Average Residential Sales per Customer" -//caption_include = "Note: For EIA reported data, the Other customer class includes industrial and transportation customers. For PCE reported data, it includes community and government customers. No industrial customers were reported in the PCE data." +```{r, eval=knitr::is_html_output()} +#| label: fig-sales_per_capita +#| fig-cap: "Average Residential Sales per Customer" +caption_include = "Note: For EIA reported data, the Other customer class includes industrial and transportation customers. For PCE reported data, it includes community and government customers. No industrial customers were reported in the PCE data." + +sales_per_capita_html <- + sales_per_capita_plot + + geom_line_interactive(linewidth = 2) + + geom_point_interactive( + aes( + tooltip = paste( + comma(round(sales_per_capita, 0)), + "kWh per Customer", + "
Year", year + ) + ), + size = 10, color = "transparent") + +girafe(code = print(sales_per_capita_html)) -Plot.plot({ +``` - // Plot setup - //title: "Average Residential Sales per Customer", +```{r, eval=knitr::is_latex_output()} +sales_per_capita_pdf <- + sales_per_capita_plot + + geom_line(linewidth = 2) + + ggtitle("Average Residential Sales per Customer") + +print(sales_per_capita_pdf) - // Configure the x-axis - x: { - domain: [2011, 2019], - tickFormat: "d", - label: "Year", - grid: true - }, - - // Configure the y-axis - y: { - domain: [3000, 10000], - ticks: 6, - label: "kWh", - grid: true - }, - - width: width, - - marks: [ - Plot.line(sales_per_capita_data, { - x: "year", - y: "sales_per_capita", - stroke: "ACEP Region", - strokeWidth: 5, - tip: {format: {x: "d"}} - } - ), - Plot.ruleY([3000]) - ], - - color: { - domain: ["Coastal", "Railbelt", "Rural Remote"], - range: ["#8CBBDA", "#97CD93", "#F28D8C"], - legend: true - } -}) ``` + + ## Coastal To estimate the average yearly growth rate in each customer class, we calculate the cumulative compound average growth rate (CAGR). From 2011 to 2019, the coastal region saw an average yearly growth rate of `r cagr("Coastal", "Residential", "sales")`% for residential sales, `r cagr("Coastal", "Commercial", "sales")`% for commercial sales, and `r cagr("Coastal", "Other", "sales")`% for all other sales. @fig-delivered-by-class-coastal shows these sales in GWh for each year. -```{ojs} -//| label: fig-delivered-by-class-coastal -//| fig-cap: "Delivered Electricity by Customer Class, Coastal region" -Plot.plot({//| - - // Plot setup - //title: "Delivered electricity by customer class, Coastal Region", - //caption: caption_include, +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Coastal") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + round((sales / 1000), 0), "GWh Delivered", + "
", class, "Customers", + "
Year", year + ) + ) - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +# Create plot +coastal_consumption_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = sales / 1000, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + - // Configure the y-axis - y: { - transform: (y) => y / 1000, - domain: [0, 1200], - label: "GWh", - grid: true - }, + scale_y_continuous( + name = "Gigawatt Hours (GWh)", + limits = c(0, 1200), + breaks = seq(0, 1200, 200), + expand = c(0, 0), + labels = scales::comma) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Coastal"), - { - x: "year", - y: "sales", - fill: "Customer Class", - tip: {format: {x: "d"}} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + + + theme_minimal() + + theme( + plot.title = element_text(hjust = 0.5), + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank() + ) + + + guides(fill = guide_legend(title = NULL)) + + + + ``` +```{r, eval=knitr::is_html_output()} +#| label: fig-delivered-by-class-coastal +#| fig-cap: "Delivered Electricity by Customer Class, Coastal Region" -While customer sales fell overall, customer accounts in the Coastal region increased for all customer classes. @fig-accounts-coastal shows the trend in customer accounts by class for the Coastal region. The average yearly growth rate in customer accounts was `r cagr("Coastal", "Residential", "customers")`% for the residential class, `r cagr("Coastal", "Commercial", "customers")`% for the commercial class, and `r cagr("Coastal", "Other", "customers")`% for the other class. +coastal_consumption_html <- + coastal_consumption_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) + +girafe(code = print(coastal_consumption_html)) + + +``` + +```{r, eval=knitr::is_latex_output()} +coastal_consumption_pdf <- + coastal_consumption_plot + + geom_bar(stat = "identity", position = "stack") + + labs( + title = "Delivered Electricity by Customer Class, Coastal Region") + +print(coastal_consumption_pdf) + +``` -```{ojs} -//| label: fig-accounts-coastal -//| fig-cap: "Number of Customer Accounts, Coastal region" -Plot.plot({ +While customer sales fell overall, customer accounts in the Coastal region increased for all customer classes. @fig-accounts-coastal shows the trend in customer accounts by class for the Coastal region. The average yearly growth rate in customer accounts was `r cagr("Coastal", "Residential", "customers")`% for the residential class, `r cagr("Coastal", "Commercial", "customers")`% for the commercial class, and `r cagr("Coastal", "Other", "customers")`% for the other class. - // Plot setup - //title: "Number of customer accounts, Coastal region", - //caption: caption_include, +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Coastal") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + comma(round((customers), 0)), "Accounts", + "
", class, "Class", + "
Year", year + ) + ) - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +# Create plot +coastal_customers_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = customers, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + + + scale_y_continuous( + name = "Accounts", + limits = c(0, 60000), + breaks = seq(0, 60000, 10000), + expand = c(0, 0), + labels = scales::comma) + - // Configure the y-axis - y: { - label: "Accounts", - domain: [0, 60000], - grid: true - }, + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Coastal"), - { - x: "year", - y: "customers", - fill: "Customer Class", - tip: {format: {x: "d"}} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + theme_minimal() + + theme( + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + + + guides(fill = guide_legend(title = NULL)) + +``` + +```{r, eval=knitr::is_html_output()} +#| label: fig-accounts-coastal +#| fig-cap: "Number of Customer Accounts, Coastal region" + +coastal_customers_html <- + coastal_customers_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) + +girafe(code = print(coastal_customers_html)) + +``` + +```{r, eval=knitr::is_latex_output()} +coastal_customers_pdf <- + coastal_customers_plot + + geom_bar(stat = "identity", position = "stack") + + labs( + title = "Number of Customer Accounts, Coastal Region") + +print(coastal_customers_pdf) + ``` ## Railbelt From 2011 to 2019, the Railbelt region saw an average yearly growth rate of `r cagr("Railbelt", "Residential", "sales")`% for residential sales, `r cagr("Railbelt", "Commercial", "sales")`% for commercial sales, and `r cagr("Railbelt", "Other", "sales")`% for all other sales. @fig-delivered-by-class-railbelt shows these sales in GWh for each year. -```{ojs} -//| label: fig-delivered-by-class-railbelt -//| fig-cap: "Delivered Electricity by Customer Class, Railbelt Region" -Plot.plot({//| - - // Plot setup - //title: "Delivered electricity by customer class, Railbelt region", - //caption: caption_include, +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Railbelt") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + round((sales / 1000), 0), "GWh", + "
Year:", year + ) + ) - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +# Create plot +railbelt_consumption_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = sales / 1000, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + + + scale_y_continuous( + name = "Gigawatt Hours (GWh)", + limits = c(0, 5000), + breaks = seq(0, 5000, 500), + expand = c(0, 0), + labels = scales::comma) + - // Configure the y-axis - y: { - transform: (y) => y / 1000, - domain: [0, 5000], - label: "GWh", - grid: true - }, + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Railbelt"), - { - x: "year", - y: "sales", - fill: "Customer Class", - tip: {format: {x: "d"}} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + theme_minimal() + + theme( + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + + + guides(fill = guide_legend(title = NULL)) + + + ``` -The trends in the number of customer accounts by class are visualized in @fig-accounts-railbelt. The average yearly growth rate in customer accounts on the Railbelt was `r cagr("Railbelt", "Residential", "customers")`% for the residential class, `r cagr("Railbelt", "Commercial", "customers")`% for the commercial class, and `r cagr("Railbelt", "Other", "customers")`% for the other class. +```{r, eval=knitr::is_html_output()} +#| label: fig-delivered-by-class-railbelt +#| fig-cap: "Delivered Electricity by Customer Class, Railbelt Region" + +railbelt_consumption_html <- + railbelt_consumption_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) -```{ojs} -//| label: fig-accounts-railbelt -//| fig-cap: "Number of Customer Accounts, Railbelt Region" -Plot.plot({ +girafe(code = print(railbelt_consumption_html)) - // Plot setup - //title: "Number of customer accounts, Railbelt region", - //caption: caption_include, - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +``` + +```{r, eval=knitr::is_latex_output()} +railbelt_consumption_pdf <- + railbelt_consumption_plot + + geom_bar(stat = "identity") + + labs( + title = "Delivered Electricity by Customer Class, Railbelt Region") + +print(railbelt_consumption_pdf) + +``` + +The trends in the number of customer accounts by class are visualized in @fig-accounts-railbelt. The average yearly growth rate in customer accounts on the Railbelt was `r cagr("Railbelt", "Residential", "customers")`% for the residential class, `r cagr("Railbelt", "Commercial", "customers")`% for the commercial class, and `r cagr("Railbelt", "Other", "customers")`% for the other class. + +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Railbelt") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + comma(round((customers), 0)), "Accounts", + "
", class, "Class", + "
Year", year + ) + ) + +# Create plot +railbelt_customers_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = customers, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + + + scale_y_continuous( + name = "Accounts", + limits = c(0, 280000), + breaks = seq(0, 280000, 50000), + expand = c(0, 0), + labels = scales::comma) + - // Configure the y-axis - y: { - transform: (y) => y / 1000, - label: "Accounts (000s)", - domain: [0, 260], - grid: true - }, + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Railbelt"), - { - x: "year", - y: "customers", - fill: "Customer Class", - tip: {format: { - x: "d", - y: (y) => `${(y).toLocaleString(undefined, {maximumFractionDigits: 2})}` - }} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + theme_minimal() + + theme( + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + + + guides(fill = guide_legend(title = NULL)) + +``` + +```{r, eval=knitr::is_html_output()} +#| label: fig-accounts-railbelt +#| fig-cap: "Number of Customer Accounts, Railbelt Region" + +railbelt_customers_html <- + railbelt_customers_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) + +girafe(code = print(railbelt_customers_html)) + +``` + +```{r, eval=knitr::is_latex_output()} +railbelt_customers_pdf <- + railbelt_customers_plot + + geom_bar(stat = "identity", position = "stack") + + labs( + title = "Number of Customer Accounts, Railbelt Region") + +print(railbelt_customers_pdf) + ``` ## Rural Remote From 2011 to 2019, the Rural Remote region saw an average yearly growth rate of `r cagr("Rural Remote", "Residential", "sales")`% for residential sales, `r cagr("Rural Remote", "Commercial", "sales")`% for commercial sales, and `r cagr("Rural Remote", "Other", "sales")`% for all other sales. Positive growth rates for the commercial and other customer classes are unique to the rural remote energy region as all other regions saw average yearly declines in sales. @fig-delivered-by-class-rural shows these sales in GWh for each year. -```{ojs} -//| label: fig-delivered-by-class-rural -//| fig-cap: "Delivered Electricity by Customer Class, Rural Remote Region" -//| fig-cap-location: top -Plot.plot({ - - // Plot setup - //title: "Delivered electricity by customer class, Rural Remote region", - //caption: caption_include, - - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Rural Remote") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + round((sales / 1000), 0), "GWh Delivered", + "
", class, "Customers", + "
Year", year + ) + ) + +# Create plot +rural_remote_consumption_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = sales / 1000, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + - // Configure the y-axis - y: { - transform: (y) => y / 1000, - domain: [0, 500], - label: "GWh", - grid: true - }, + scale_y_continuous( + name = "Gigawatt Hours (GWh)", + limits = c(0, 500), + breaks = seq(0, 500, 50), + expand = c(0, 0), + labels = scales::comma) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Rural Remote"), - { - x: "year", - y: "sales", - fill: "Customer Class", - tip: {format: {x: "d"}} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + + + theme_minimal() + + theme( + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + + + guides(fill = guide_legend(title = NULL)) + + + + ``` -The trends in the number of customer accounts by class are visualized in @fig-accounts-rural. The average yearly growth rate in customer accounts in the Rural Remote region was `r cagr("Rural Remote", "Residential", "customers")`% for the residential class, `r cagr("Rural Remote", "Commercial", "customers")`% for the commercial class, and `r cagr("Rural Remote", "Other", "customers")`% for the other class. +```{r, eval=knitr::is_html_output()} +#| label: fig-delivered-by-class-rural +#| fig-cap: "Delivered Electricity by Customer Class, Rural Remote Region" + +rural_remote_consumption_html <- + rural_remote_consumption_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) + +girafe(code = print(rural_remote_consumption_html)) + + +``` + +```{r, eval=knitr::is_latex_output()} +rural_remote_consumption_pdf <- + rural_remote_consumption_plot + + geom_bar(stat = "identity", position = "stack") + + labs( + title = "Delivered Electricity by Customer Class, Rural Remote Region") -```{ojs} -//| label: fig-accounts-rural -//| fig-cap: "Number of Customer Accounts, Rural Remote Region" -Plot.plot({ +print(rural_remote_consumption_pdf) - // Plot setup - //title: "Number of customer accounts, Rural Remote region", - //caption: caption_include, +``` + +The trends in the number of customer accounts by class are visualized in @fig-accounts-rural. The average yearly growth rate in customer accounts in the Rural Remote region was `r cagr("Rural Remote", "Residential", "customers")`% for the residential class, `r cagr("Rural Remote", "Commercial", "customers")`% for the commercial class, and `r cagr("Rural Remote", "Other", "customers")`% for the other class. + +```{r} +# Filter data +filtered_data <- regional_consumption_data %>% + filter(class != "Total" & acep_region == "Rural Remote") %>% + mutate( + class = factor(class, levels = c("Residential", "Commercial", "Other")), + tooltip = paste( + comma(round((customers), 0)), "Accounts", + "
", class, "Class", + "
Year", year + ) + ) - // Configure the x-axis - x: { - tickFormat: "d", - label: "Year" - }, +# Create plot +rural_remote_customers_plot <- + ggplot( + filtered_data, + aes( + x = year, + y = customers, + fill = reorder(class, sales))) + + + scale_x_continuous( + name = "", + breaks = seq(2011, 2019, 1)) + + + scale_y_continuous( + name = "Customers", + limits = c(0, 40000), + breaks = seq(0, 40000, 5000), + expand = c(0, 0), + labels = scales::comma) + - // Configure the y-axis - y: { - //transform: (y) => y / 1000, - label: "Accounts", - domain: [0, 37500], - grid: true - }, + scale_fill_manual( + values = c( + "Residential" = "#0084c1", + "Commercial" = "#e29617", + "Other" = "#fad900"), + name = "Customer Class" + ) + - width: width, - - marks: [ - Plot.barY(regional_consumption_data.filter((d) => d.class !== "Total" && d.acep_region == "Rural Remote"), - { - x: "year", - y: "customers", - fill: "Customer Class", - tip: {format: { - x: "d", - y: (y) => `${(y).toLocaleString(undefined, {maximumFractionDigits: 2})}` - }} - } - ), - Plot.ruleY([0]) - ], - - color: { - domain: ["Residential","Commercial","Other"], - range: ["#0084c1","#e29617","#fad900"], - legend: true - } -}) + theme_minimal() + + theme( + legend.position = "top", + panel.grid.minor = element_blank(), + panel.grid.major.x = element_blank(), + plot.title = element_text(hjust = 0.5), + plot.subtitle = element_text(hjust = 0.5) + ) + + + guides(fill = guide_legend(title = NULL)) + +``` + +```{r, eval=knitr::is_html_output()} +rural_remote_customers_html <- + rural_remote_customers_plot + + geom_bar_interactive( + tooltip = filtered_data$tooltip, + stat = "identity", + position = "stack" + ) + +girafe(code = print(rural_remote_customers_html)) + +``` + +```{r, eval=knitr::is_latex_output()} +rural_remote_customers_pdf <- + rural_remote_customers_plot + + geom_bar(stat = "identity", position = "stack") + + labs( + title = "Number of Customer Accounts, Rural Remote Region") + +print(rural_remote_customers_pdf) + ``` \ No newline at end of file diff --git a/data.qmd b/data.qmd index 153eac2..c70ee62 100644 --- a/data.qmd +++ b/data.qmd @@ -9,6 +9,24 @@ output: echo: false --- +::: {.content-visible when-format="pdf"} +## Data Overview +The data used in this web-book is derived from federal, state, commercial, and local sources, as well as direct communications with utilities and state program managers. More information about data sources can be found on the web book version of this report at: + +https://acep-uaf.github.io/aetr-web-book-2024/methods.html + + +## Download Individual Tables +To download the data itself, please visit this report's corresponding web-book at: + + https://acep-uaf.github.io/aetr-web-book-2024/data.html + +::: + + +::: {.content-visible when-format="html"} +## How to Cite +{{< include _citations.qmd >}} ## Data Overview The data used in this web-book is derived from federal, state, commercial, and local sources, as well as direct communications with utilities and state program managers. More information about [data sources](https://acep-uaf.github.io/ak-energy-statistics-2011_2021/) can be found on the [methods page](./methods.html) of this web-book. @@ -274,3 +292,4 @@ db_button = (database, filename = 'data.csv') => { db_button(database, `${dbTable}`) ``` +::: \ No newline at end of file diff --git a/index.qmd b/index.qmd index 1940d28..7ca52d8 100644 --- a/index.qmd +++ b/index.qmd @@ -4,18 +4,44 @@ subtitle: "An Analysis of Electricity in Alaska, Data Years 2011-2021" author: "Alaska Center for Energy and Power" #date-modified: "2024-03-25T17:22:00-08:00" #date-format: "MMM D, YYYY [at] HH:mm z" +output: + quarto::quarto_html: + pre_processor: quarto::observable +cap-location: top +echo: false --- ## Welcome {#welcome .unnumbered} -This interactive report summarizes electricity data gathered from federal, state, and utility sources and presented in the form of a web book. It provides an overview of electricity capacity, generation, consumption, and price trends from 2011 to 2021. A comprehensive report highlighting these trends has not been produced for the state of Alaska since 2013's _Alaska Energy Statistics Report_. +This report summarizes electricity data gathered from federal, state, and utility sources. It provides an overview of electricity capacity, generation, consumption, and price trends from 2011 to 2021. A comprehensive report highlighting these trends has not been produced for the state of Alaska since 2013's _Alaska Energy Statistics Report_. This web book is designed as 'best available' document for the 2011-2021 energy trends data and reports. This website will be updated when updates to the underlying 2011-2021 data or fixes become available. Future year trends reports will be tackled in a different context and reporting structure. Please explore the data using the chapter navigation links in the left sidebar and the section navigation links in the right sidebar. -### How to Cite -{{< include _citations.qmd >}} +## How to Cite +::: {.content-visible when-format="html"} +##### Mystery format: +Alaska Center for Energy and Power. "2024 Alaska Energy Trends Report Web Book." Accessed `{ojs} currentDate`. https://acep-uaf.github.io/aetr-web-book-2024 +::: + + +::: {.content-visible when-format="pdf"} +##### Mystery format: +Alaska Center for Energy and Power. "2024 Alaska Energy Trends Report." Accessed `r Sys.Date()`. [PDF version]. Available at: https://acep-uaf.github.io/aetr-web-book-2024/report2024.pdf +::: + +###### BibLaTeX format: +```{r, eval=FALSE, echo=TRUE} +@online{aetr_web_book_2024, + author = {{Alaska Center for Energy and Power}}, + title = {{2024 Alaska Electricity Trends Report}}, + year = 2024, + url = {https://acep-uaf.github.io/aetr-web-book-2024/}, + urldate = {2024-07-23} +} +``` + ## Executive Summary {.unnumbered} @@ -26,3 +52,5 @@ Please explore the data using the chapter navigation links in the left sidebar a {{< include _key_takeaways.qmd >}} + + diff --git a/methods.qmd b/methods.qmd index 888371d..16c01d2 100644 --- a/methods.qmd +++ b/methods.qmd @@ -59,7 +59,147 @@ We note that the Coastal and Rural Remote regions include mixtures of Power Cost

-{{< include _regions_map.qmd >}} +::: {.content-visible when-format="html"} +```{ojs} +// The OJS chunks below build the interactive map for the HTML version +// These chunks will not render for the PDF version, use PNG instead + +stdlib = require("@observablehq/stdlib") +d3 = require("d3@7") + +L = require('leaflet@1.9.4') +html`` + +bootstrap=require("bootstrap") +css=html`` +``` + +```{ojs} +aea_regions = FileAttachment("data/working/regions/aea_regions.geojson").json() +acep_regions = FileAttachment("data/working/regions/acep_regions.geojson").json() + +coords_json = FileAttachment("data/working/regions/coordinates.geojson").json() + +// coords_csv = FileAttachment("data/working/regions/coordinates_pce.csv").csv({typed: true}) + +``` + +```{ojs} +aea_regions_input = L.geoJSON(aea_regions, { + style: function(feature) { + switch (feature.properties.NAME) { + case 'Aleutians': return {color: "#FF5733"}; + case 'Bering Straits': return {color: "#FF1493"}; + case 'Bristol Bay': return {color: "#20B2AA"}; + case 'Copper River Chugach': return {color: "#7D3C98"}; + case 'Kodiak': return {color: "#C70039"}; + case 'Lower Yukon Kuskokwim': return {color: "#00B4D8"}; + case 'North Slope': return {color: "#4682B4"}; + case 'Northwest Arctic': return {color: "#6A5ACD"}; + case 'Railbelt': return {color: "#228B22"}; + case 'Southeast': return {color: "#FFC300"}; + case 'Yukon-Koyukuk Upper Tanana': return {color: "#FF8C00"}; + } + } + }).bindTooltip(function (layer) { + return layer.feature.properties.NAME; + }, + { + sticky: true, + offset: [10, 0], + direction: "right", + opacity: 0.75 + }); + + +acep_regions_input = L.geoJSON(acep_regions, { + style: function(feature) { + switch (feature.properties.NAME) { + case 'Rural Remote': return {color: "#FF0000"}; + case 'Coastal': return {color: "#0000FF"}; + case 'Railbelt': return {color: "#228B22"}; + } + } + }).bindTooltip(function (layer) { + return layer.feature.properties.NAME; + }, + { + sticky: true, + offset: [10, 0], + direction: "right", + opacity: 0.75 + }); + + +``` + + +```{ojs} +// Code below builds community location points +points = L.geoJSON(coords_json, { + pointToLayer: function (feature, latlng) { + return L.circleMarker(latlng, + {radius: 5, + fillColor: "#808080", + color: "#000", + weight: 1, + opacity: 1, + fillOpacity: 0.8 + }); + } +}).bindTooltip(function (layer) { + return layer.feature.properties.name; + }, + { + sticky: true, + offset: [10, 0], + direction: "right", + opacity: 0.75 + }); + +``` + +```{ojs} +//| label: fig-regions-map +//| fig-cap: "Cartographic Relationship between Energy Regions as defined by AEA and ACEP" + +viewof region_input = Inputs.select(new Map([ + ["AEA Regions", aea_regions_input], + ["ACEP Regions", acep_regions_input]]), + {value: aea_regions_input, label: "Display below:"} + ); + + +``` + +```{ojs} +// the order of the container calls is important, do first, don't mess with +map = { + let container = DOM.element('div', { style: `width:${width}px;height:${width/1.2}px` }); + yield container; + + // create map object + let map = L.map(container).setView([62.945279601222396, -155.5946697727831], 4); + + // add basemap + var basemap = L.tileLayer('https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}', { + maxZoom: 20, + attribution: 'Tiles courtesy of the U.S. Geological Survey' + }); + basemap.addTo(map); + + // // add dropdown input selection + region_input.addTo(map); + + // add community points + points.addTo(map); + + +} + +``` + +:::

diff --git a/prices.qmd b/prices.qmd index 400e334..0755514 100644 --- a/prices.qmd +++ b/prices.qmd @@ -15,13 +15,39 @@ echo: false library(readr) library(dplyr) +library(tidyr) library(stringr) library(ggplot2) library(ggiraph) +library(see) # slices violin plots in half +library(ggridges) # mountains beyond mountains +library(ggrepel) # labels on ends of lines +library(ggdist) # raincloud plots +library(ggrain) # other raincloud package + +weighted_prices <- read_csv("./data/working/prices/weighted_prices.csv") +prices <- read_csv("./data/working/prices/prices.csv") + +# Function declaration +source("scripts/inline_functions/price_inline_functions.R") + weighted_prices <- read_csv("./data/final_data/weighted_prices.csv") +``` + +::: {.content-visible when-format="html"} +```{ojs} +// load libraries +stdlib = require("@observablehq/stdlib") +d3 = require("d3@7") +import {tidy, groupBy, rename, summarize, sum, mutate, select, n, nDistinct, mean, filter, pivotWider, pivotLonger, leftJoin, slice} from "@pbeshai/tidyjs" + +// load data +prices = FileAttachment("data/working/prices/prices.csv").csv({typed: true}); +weighted_prices = FileAttachment("data/working/prices/weighted_prices.csv").csv({typed: true}); ``` +::: ## General Overview {#sec-prices} @@ -33,6 +59,7 @@ Note that all prices in this section have been adjusted for inflation over time ### Regional Overview +::: {.content-visible when-format="html"} @fig-price-regions-classes shows the distribution of prices across a selected customer class. The three classes used in this analysis can be selected from the dropdown menu. Hover your pointer over the dot to display utility information. Most notably, the dramatic effects of the PCE subsidy can be seen by comparing the price distribution of the residential customer class against the price distribution of the commercial/other customer classes in the Rural Remote and Coastal regions. @@ -40,10 +67,390 @@ Most notably, the dramatic effects of the PCE subsidy can be seen by comparing t - {{< include _prices_raincloud.qmd >}} +```{r} +# desired future inputs: +# community size +# sector +# year +# weighted/unweighted +``` + +```{ojs} +// active inputs + +viewof dimension = Inputs.select(new Map([ + ["Residential", 'residential_price'], + ["Commercial", 'commercial_price'], + ["Other", 'other_price']]), + {value: "Residential", label: "Customer Class:"} + ); + + +// viewof flipCoords = Inputs.toggle({ label: 'Flip', value: false }) + +// Inputs.table(customers_pivot) +``` + +```{ojs} +// hardcoded inputs here + +// viewof thresholds = Inputs.select([10, 20, 60], { label: 'Bins', value: 60 }) +thresholds = 40 + +// viewof seed = Inputs.range([1, 100], { step: 1, label: 'Raw Data Seed', value: 1 }) +seed = 1 + +// viewof rawDataSize = Inputs.range([10, 100], { value: 40, step: 10, label: 'Raw Data Size (%)' }) +rawDataSize = 20 + +// viewof rawDataOffset = Inputs.range([0, 50], { value: 5, step: 5, label: 'Raw Data Offset (%)' }) +rawDataOffset = 5 + +``` + +```{ojs} +//| label: fig-price-regions-classes +//| fig-cap: "Prices by Region and Customer Class" +//| class: raincloud-custom +Plot.plot(rainCloudX) + +``` + +```{ojs} +rainCloudX = ({ + grid: true, + label: null, + width: width, + marks: [ + Plot.ruleX([0]), + halfViolinX, + rawDataX + ], + facet: { + data: data, + y: 'acep_energy_region', + marginRight: 80 + }, + x: { + label: "Cents per Kilowatt Hour" + }, + y: { + ticks: 0, + tickFormat: d => d < 0 ? '' : d + }, + color: { + domain: ["Coastal", "Railbelt", "Rural Remote"], + range: ["#8CBBDA", "#97CD93", "#F28D8C"] + } +}) +``` + +```{ojs} +halfViolinX = Plot.areaY( + data, + Plot.binX( + { + y: 'count' + }, + { + x: dimension, + fill: 'acep_energy_region', + thresholds: thresholds, + curve: 'basis' + } + ) +) +``` + +```{ojs} +rawDataX = Plot.dot( + data, + { + x: dimension, + y: jitter(data, seed), + fill: 'acep_energy_region', + r: 1.5, + channels: {Name: "reporting_name", Year: "year"}, + tip: {format: {fill: false, + fy: false, + y: false + }} + + } +) + +// tip = Plot.tip( +// data, Plot.pointer( +// { +// x: dimension, +// y: 'acep_energy_region', +// format: { +// year: true, +// reporting_name: true, +// dimension: true, +// filter: (d) => d.reporting_name, +// title: (d) => [d.reporting_name, d.year].join("\n\n") +// stroke: false +// } +// } +// ) +// ) + +``` + +```{ojs} +//| echo: false +// appendix + +jitter = (data, seed) => { + const rng = seedrandom(seed); + return data.map(() => -(rng() * rawDataSize + rawDataOffset) * maxTotal / 100); +} + +maxTotal = d3.max( + Array.from( + d3 + .group(data, d => d.aea_energy_region) + .values() + ) + .flatMap(g => bins(g.map(d => d[dimension]))) + .map(bin => bin.length) +) + +bins = d3 + .bin() + .domain(d3.extent(data, d => d[dimension])) + .thresholds(thresholds) + + +seedrandom = require('seedrandom') +``` + +```{ojs} + +prices_tidy = tidy( + prices, + rename({ + 'residential_price_kwh_2021_dollars': 'residential_price', + 'commercial_price_kwh_2021_dollars': 'commercial_price', + 'other_price_kwh_2021_dollars': 'other_price', + }), + // pivotLonger({ + // cols: ['residential', 'commercial', 'other'], + // namesTo: 'sector', + // valuesTo: 'price' + // }), + select([ + 'year', + 'reporting_name', + 'acep_energy_region', + 'residential_price', + 'commercial_price', + 'other_price' + ]) +) + +customers_pivot = tidy( + prices, + rename({ + 'residential_price_kwh_2021_dollars': 'residential_price', + 'commercial_price_kwh_2021_dollars': 'commercial_price', + 'other_price_kwh_2021_dollars': 'other_price', + }), + rename({ + 'residential_customers': 'residential', + 'commercial_customers': 'commercial', + 'other_customers': 'other', + }), + pivotLonger({ + cols: ['residential', 'commercial', 'other'], + namesTo: 'sector', + valuesTo: 'customers' + }), + select([ + 'year', + 'reporting_name', + 'acep_energy_region', + 'residential_price', + 'commercial_price', + 'other_price', + 'customers', + 'total_customers' + ]) +) + +// prices_customers_long = tidy( +// prices_pivot, +// leftJoin(customers_pivot, +// { by: ['year', 'aea_sales_reporting_id', 'reporting_name', 'sector'] }), +// select([ +// 'year', +// 'reporting_name', +// 'acep_energy_region', +// 'sector', +// 'price', +// 'customers', +// 'total_customers' +// ]) +// ) + +data = tidy( + prices_tidy, + mutate({ + residential_price: (d) => d.residential_price === 0 ? null : d.residential_price, + commercial_price: (d) => d.commercial_price === 0 ? null : d.commercial_price, + other_price: (d) => d.other_price === 0 ? null : d.other_price, + }), + filter((d) => d.year < 2020), + filter((d) => d.reporting_name != "Lime Village"), + filter((d) => d.reporting_name != "Healy Lake") +); + + +``` + +::: + + +::: {.content-visible when-format="pdf"} +```{r} +p_prices <- prices %>% + rename(c("residential" = "residential_price_kwh_2021_dollars", + "commercial" = "commercial_price_kwh_2021_dollars", + "other" = "other_price_kwh_2021_dollars")) %>% + pivot_longer( + cols = c("residential", + "commercial", + "other"), + names_to ="sector", + values_to = "price") + +long_price <- p_prices %>% + mutate(customers = NA) %>% + mutate(customers = ifelse(sector == "residential", residential_customers, customers)) %>% + mutate(customers = ifelse(sector == "commercial", commercial_customers, customers)) %>% + mutate(customers = ifelse(sector == "other", other_customers, customers)) %>% + mutate(customers = round(customers, 0)) %>% + + select("year", + "reporting_name", + "acep_energy_region", + "sector", + "price", + "customers", + "total_customers") +``` + +```{r warning=FALSE, eval=knitr::is_latex_output()} +raincloud <- function(sector_input="residential", start_year=2011, end_year=2019, x_axis_max=65){ + d <- long_price %>% + filter(sector == sector_input) %>% + filter(price > 0) %>% + filter(year >= start_year & year <= end_year) %>% + left_join(weighted_prices, join_by(year, sector, acep_energy_region)) + + output <- + ggplot(d) + + + geom_violinhalf( + aes(x=acep_energy_region, + y=price, + fill=acep_energy_region), + position = position_nudge(x=.1, y=0)) + + + geom_jitter( + aes(x=acep_energy_region, y=price), + color="black", + alpha=0.25, + width = .05, + height = 0) + + + scale_fill_manual(values = c("#98BAD6", "#A4CD9A", "#E3918F")) + + scale_color_manual(values = c("#98BAD6", "#A4CD9A", "#E3918F")) + + + scale_y_continuous( + breaks = seq(0, x_axis_max, 20), + limits = c(0, x_axis_max), + expand = c(0, 0.1)) + + + theme_classic() + + theme(legend.position = "none", + # plot.title = element_text(size=16, hjust = 0.5), + # plot.subtitle = element_text(size=14, hjust = 0.5), + plot.caption = element_text(size = 8), + panel.grid.major.x = element_line(color = "grey80", size = 0.5), + plot.margin = unit(c(t=5, r=15, b=5, l=0), "pt")) + + + labs(title = paste(str_to_title(sector_input), "Sector Prices,", start_year, "-", end_year), + x = "", + y = "Cents per kWh") + + + # ylim(c(0,x_axis_max)) + #remember the coord_flip, y axis is now the x axis + coord_flip() + + + #E3918F Rural Remote + #98BAD6 Coastal + #A4CD9A Railbelt + #F1BF42 State + + print(output) + +} +``` +::: + +Below are three raincloud plots to show the distribution of prices across the three customer classes. Each dot represents the average annual price of a community for a single year in the range. For this report, data is displayed for 9 years, 2011-2019, therefore each community will render 9 points on the plot. Communities are grouped by the three regions, and the half-violin shows distribution of the prices. -
+::: {.content-visible when-format="pdf"} +\vspace{3ex} +::: + +```{r warning=FALSE, eval=knitr::is_latex_output()} +raincloud( + sector_input="residential", + start_year=2011, + end_year=2019, + x_axis_max=120) + +``` + +::: {.content-visible when-format="pdf"} +\vspace{3ex} +::: + +Most notably, the dramatic effects of the PCE subsidy can be seen by comparing the price distribution of the residential customer class against the price distribution of the commercial/other customer classes in the Rural Remote and Coastal regions. + +::: {.content-visible when-format="pdf"} +\vspace{3ex} +::: + +```{r warning=FALSE, eval=knitr::is_latex_output()} +raincloud( + sector_input="commercial", + start_year=2011, + end_year=2019, + x_axis_max=120) + +``` + +::: {.content-visible when-format="pdf"} +\vspace{3ex} +::: + +```{r warning=FALSE, eval=knitr::is_latex_output()} +raincloud( + sector_input="other", + start_year=2011, + end_year=2019, + x_axis_max=120) + +``` + +::: {.content-visible when-format="pdf"} +\vspace{3ex} +::: ### Regional Averages @@ -95,6 +502,7 @@ regions_plot <- ``` + ```{r, eval=knitr::is_html_output()} #| label: fig-price-over-time #| fig-cap: "Residential Price Over Time" @@ -131,7 +539,7 @@ print(regions_pdf) @fig-price-sector-coastal shows the average price of electricity in the Coastal region for each customer class and year. Between 2011 and 2019, the region experienced decreasing prices for Commercial and Other customers, while Residential customers have seen a slight increase in price. -The average real price (in 2021 dollars) of electricity for Residential customers in the Coastal region rose `{ojs} coastal_res_change`% from `{ojs} coastal_res_2011` cents/kWh in 2011 to `{ojs} coastal_res_2019` cents/kWh in 2019. The average price of electricity for Commercial customers in the Coastal region fell `{ojs} coastal_com_change`% from `{ojs} coastal_com_2011` cents/kWh in 2011 to `{ojs} coastal_com_2019` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Coastal region fell `{ojs} coastal_other_change`% from `{ojs} coastal_other_2011` cents/kWh in 2011 to `{ojs} coastal_other_2019` cents/kWh in 2019. +The average real price (in 2021 dollars) of electricity for Residential customers in the Coastal region rose `r price_delta(region="Coastal", sector="residential", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Coastal", sector="residential", year=2011)` cents/kWh in 2011 to `r price(region="Coastal", sector="residential", year=2019)` cents/kWh in 2019. The average price of electricity for Commercial customers in the Coastal region fell `r price_delta(region="Coastal", sector="commercial", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Coastal", sector="commercial", year=2011)` cents/kWh in 2011 to `r price(region="Coastal", sector="commercial", year=2019)` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Coastal region fell `r price_delta(region="Coastal", sector="other", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Coastal", sector="other", year=2011)` cents/kWh in 2011 to `r price(region="Coastal", sector="other", year=2019)` cents/kWh in 2019. Residential customers in the Coastal region saw increases in the price of electricity while commercial and other customers saw decreases. However, the residential customer class continues to pay the lowest per kWh in the region due to a combination of low prices in high population areas and PCE subsidies in eligible communities. @@ -214,7 +622,7 @@ print(coastal_pdf) @fig-price-sector-railbelt shows the average price of electricity in the Railbelt region for each customer class and each year of the report. Between 2011 and 2019, Other customers saw a large decrease in price, followed by a gradual increase. Residential and Commercial customers experienced slight decreases in price until 2013 when prices reversed and rose dramatically. -The average real price of electricity for Residential customers in the Railbelt rose `{ojs} railbelt_res_change`% from `{ojs} railbelt_res_2011` cents/kWh in 2011 to `{ojs} railbelt_res_2019` cents/kWh in 2019. The average price of electricity for Commercial customers in the Railbelt rose `{ojs} railbelt_com_change`% from `{ojs} railbelt_com_2011` cents/kWh in 2011 to `{ojs} railbelt_com_2019` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Railbelt fell `{ojs} railbelt_other_change`% from `{ojs} railbelt_other_2011` cents/kWh in 2011 to `{ojs} railbelt_other_2019` cents/kWh in 2019. +The average real price of electricity for Residential customers in the Railbelt rose `r price_delta(region="Railbelt", sector="residential", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Railbelt", sector="residential", year=2011)` cents/kWh in 2011 to `r price(region="Railbelt", sector="residential", year=2019)` cents/kWh in 2019. The average price of electricity for Commercial customers in the Railbelt rose `r price_delta(region="Railbelt", sector="commercial", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Railbelt", sector="commercial", year=2011)` cents/kWh in 2011 to `r price(region="Railbelt", sector="commercial", year=2019)` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Railbelt fell `r price_delta(region="Railbelt", sector="other", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Railbelt", sector="other", year=2011)` cents/kWh in 2011 to `r price(region="Railbelt", sector="other", year=2019)` cents/kWh in 2019. This region differs significantly from the Coastal and Rural Remote regions in that residential customers pay more for electricity than the Commercial or Other customer classes. @@ -296,7 +704,7 @@ print(railbelt_pdf) ## Rural Remote @fig-price-sector-rural shows the average price of electricity in the Rural Remote region for each customer class and year of the report. Between 2011 and 2019, Residential customers experienced a gradual increase in rates, while Commercial and Other customers experienced a gradual decrease in rates. -The average price of electricity for the Residential customers in the Rural Remote region rose `{ojs} rural_res_change`% from `{ojs} rural_res_2011` cents/kWh in 2011 to `{ojs} rural_res_2019` cents/kWh in 2019. The average price of electricity for Commercial customers in the Rural Remote region fell `{ojs} rural_com_change`% from `{ojs} rural_com_2011` cents/kWh in 2011 to `{ojs} rural_com_2019` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Rural Remote region fell `{ojs} rural_other_change`% from `{ojs} rural_other_2011` cents/kWh in 2011 to `{ojs} rural_other_2019` cents/kWh in 2019. +The average price of electricity for the Residential customers in the Rural Remote region rose `r price_delta(region="Rural Remote", sector="residential", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Rural Remote", sector="residential", year=2011)` cents/kWh in 2011 to `r price(region="Rural Remote", sector="residential", year=2019)` cents/kWh in 2019. The average price of electricity for Commercial customers in the Rural Remote region fell `r price_delta(region="Rural Remote", sector="commercial", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Rural Remote", sector="commercial", year=2011)` cents/kWh in 2011 to `r price(region="Rural Remote", sector="commercial", year=2019)` cents/kWh in 2019. Finally, the average price of electricity for Other customers in the Rural Remote region fell `r price_delta(region="Rural Remote", sector="other", pct=TRUE, numeric_out=TRUE)`% from `r price(region="Rural Remote", sector="other", year=2011)` cents/kWh in 2011 to `r price(region="Rural Remote", sector="other", year=2019)` cents/kWh in 2019. ```{r} rural_remote_weighted_prices <- @@ -376,97 +784,3 @@ print(rural_remote_pdf) ``` -```{ojs} -// price extraction function - -function extract_price(region, year, sector) { - const filteredData = weighted_prices.filter( - d => d.year === year && - d.sector === sector && - d.acep_energy_region === region); - - const extractedPrice = Math.round(filteredData.map(d => d.weighted_price)); - - return extractedPrice; -}; - -``` - -```{ojs} -// percentage function - -function percent_change(region, start_year, end_year, sector){ - const start_price = extract_price(region, start_year, sector); - const end_price = extract_price(region, end_year, sector); - - const rawPercent = (((start_price - end_price)/start_price) * 100); - const percent = Math.abs(Math.round(rawPercent)); - - return percent; -} - -``` - -```{ojs} -// starting prices - -rural_res_2011 = extract_price("Rural Remote", 2011, 'residential'); -railbelt_res_2011 = extract_price("Railbelt", 2011, 'residential'); -coastal_res_2011 = extract_price("Coastal", 2011, 'residential'); - -rural_com_2011 = extract_price("Rural Remote", 2011, 'commercial'); -railbelt_com_2011 = extract_price("Railbelt", 2011, 'commercial'); -coastal_com_2011 = extract_price("Coastal", 2011, 'commercial'); - -rural_other_2011 = extract_price("Rural Remote", 2011, 'other'); -railbelt_other_2011 = extract_price("Railbelt", 2011, 'other'); -coastal_other_2011 = extract_price("Coastal", 2011, 'other'); - -``` - -```{ojs} -// ending prices - -rural_res_2019 = extract_price("Rural Remote", 2019, 'residential'); -railbelt_res_2019 = extract_price("Railbelt", 2019, 'residential'); -coastal_res_2019 = extract_price("Coastal", 2019, 'residential'); - -rural_com_2019 = extract_price("Rural Remote", 2019, 'commercial'); -railbelt_com_2019 = extract_price("Railbelt", 2019, 'commercial'); -coastal_com_2019 = extract_price("Coastal", 2019, 'commercial'); - -rural_other_2019 = extract_price("Rural Remote", 2019, 'other'); -railbelt_other_2019 = extract_price("Railbelt", 2019, 'other'); -coastal_other_2019 = extract_price("Coastal", 2019, 'other'); - -``` - -```{ojs} -// percent changes - -coastal_res_change = percent_change("Coastal", 2011, 2019, 'residential'); -coastal_com_change = percent_change("Coastal", 2011, 2019, 'commercial'); -coastal_other_change = percent_change("Coastal", 2011, 2019, 'other'); - -railbelt_res_change = percent_change("Railbelt", 2011, 2019, 'residential'); -railbelt_com_change = percent_change("Railbelt", 2011, 2019, 'commercial'); -railbelt_other_change = percent_change("Railbelt", 2011, 2019, 'other'); - -rural_res_change = percent_change("Rural Remote", 2011, 2019, 'residential'); -rural_com_change = percent_change("Rural Remote", 2011, 2019, 'commercial'); -rural_other_change = percent_change("Rural Remote", 2011, 2019, 'other'); - -``` - - -```{ojs} -// load libraries -stdlib = require("@observablehq/stdlib") -d3 = require("d3@7") -import {tidy, groupBy, rename, summarize, sum, mutate, select, n, nDistinct, mean, filter, pivotWider, pivotLonger, leftJoin, slice} from "@pbeshai/tidyjs" - -// load data -prices = FileAttachment("data/final_data/prices.csv").csv({typed: true}); -weighted_prices = FileAttachment("./data/final_data/weighted_prices.csv").csv({typed: true}); - -``` diff --git a/renv.lock b/renv.lock index b59b263..8f3e483 100644 --- a/renv.lock +++ b/renv.lock @@ -122,6 +122,22 @@ ], "Hash": "543776ae6848fde2f48ff3816d0628bc" }, + "bayestestR": { + "Package": "bayestestR", + "Version": "0.14.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "71e7da5d38487173de67a1f0d763ceef" + }, "bit": { "Package": "bit", "Version": "4.0.5", @@ -238,6 +254,22 @@ ], "Hash": "f20c47fd52fae58b4e377c37bb8c335b" }, + "correlation": { + "Package": "correlation", + "Version": "0.8.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "datasets", + "datawizard", + "insight", + "parameters", + "stats" + ], + "Hash": "0995955fd59a01caf80918913bc5066c" + }, "cpp11": { "Package": "cpp11", "Version": "0.4.7", @@ -270,6 +302,19 @@ ], "Hash": "411ca2c03b1ce5f548345d2fc2685f7a" }, + "datawizard": { + "Package": "datawizard", + "Version": "0.12.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "insight", + "stats", + "utils" + ], + "Hash": "4070785c656b9ded5d0ed5db387a96d5" + }, "digest": { "Package": "digest", "Version": "0.6.35", @@ -281,6 +326,22 @@ ], "Hash": "698ece7ba5a4fa4559e3d537e7ec3d31" }, + "distributional": { + "Package": "distributional", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "generics", + "lifecycle", + "numDeriv", + "rlang", + "stats", + "utils", + "vctrs" + ], + "Hash": "3bad76869f2257ea4fd00a3c08c2bcce" + }, "dplyr": { "Package": "dplyr", "Version": "1.1.4", @@ -304,6 +365,23 @@ ], "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" }, + "effectsize": { + "Package": "effectsize", + "Version": "0.8.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "insight", + "parameters", + "performance", + "stats", + "utils" + ], + "Hash": "7aceb5e07b6d48171c6b56714cc305ea" + }, "evaluate": { "Package": "evaluate", "Version": "0.23", @@ -375,6 +453,44 @@ ], "Hash": "15e9634c0fcd294799e9b2e929ed1b86" }, + "ggdist": { + "Package": "ggdist", + "Version": "3.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "Rcpp", + "cli", + "distributional", + "ggplot2", + "glue", + "grid", + "gtable", + "numDeriv", + "quadprog", + "rlang", + "scales", + "tibble", + "vctrs", + "withr" + ], + "Hash": "86ebb3543cdad6520be9bf8863167a9a" + }, + "gghalves": { + "Package": "gghalves", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "ggplot2", + "grDevices", + "grid", + "gtable" + ], + "Hash": "141e061a5a68d463f11a4b5819ef0357" + }, "ggiraph": { "Package": "ggiraph", "Version": "0.8.10", @@ -421,6 +537,81 @@ ], "Hash": "44c6a2f8202d5b7e878ea274b1092426" }, + "ggpp": { + "Package": "ggpp", + "Version": "0.5.8-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "MASS", + "R", + "dplyr", + "ggplot2", + "glue", + "grDevices", + "grid", + "gridExtra", + "lubridate", + "magrittr", + "polynom", + "rlang", + "scales", + "stats", + "stringr", + "tibble", + "vctrs", + "xts", + "zoo" + ], + "Hash": "85f25ea0bb52935bd33d30b2c6c8f0a6" + }, + "ggrain": { + "Package": "ggrain", + "Version": "0.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "gghalves", + "ggplot2", + "ggpp", + "grid", + "rlang", + "vctrs" + ], + "Hash": "2461326311e1358903b3115cb489e853" + }, + "ggrepel": { + "Package": "ggrepel", + "Version": "0.9.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "Rcpp", + "ggplot2", + "grid", + "rlang", + "scales", + "withr" + ], + "Hash": "cc3361e234c4a5050e29697d675764aa" + }, + "ggridges": { + "Package": "ggridges", + "Version": "0.5.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "ggplot2", + "grid", + "scales", + "withr" + ], + "Hash": "66488692cb8621bc78df1b9b819497a6" + }, "glue": { "Package": "glue", "Version": "1.7.0", @@ -432,6 +623,20 @@ ], "Hash": "e0b3a53876554bd45879e596cdb10a52" }, + "gridExtra": { + "Package": "gridExtra", + "Version": "2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "graphics", + "grid", + "gtable", + "utils" + ], + "Hash": "7d7f283939f563670a697165b2cf5560" + }, "gtable": { "Package": "gtable", "Version": "0.3.5", @@ -518,6 +723,19 @@ ], "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" }, + "insight": { + "Package": "insight", + "Version": "0.20.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods", + "stats", + "utils" + ], + "Hash": "74a0751aafb4d4bc140531e46deda4ab" + }, "isoband": { "Package": "isoband", "Version": "0.2.7", @@ -676,6 +894,25 @@ ], "Hash": "18e9c28c1d3ca1560ce30658b22ce104" }, + "modelbased": { + "Package": "modelbased", + "Version": "0.8.8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "effectsize", + "graphics", + "insight", + "parameters", + "performance", + "stats", + "utils" + ], + "Hash": "be0465e9a8078f1c5a15344a2c130266" + }, "munsell": { "Package": "munsell", "Version": "0.5.1", @@ -701,6 +938,16 @@ ], "Hash": "a623a2239e642806158bc4dc3f51565d" }, + "numDeriv": { + "Package": "numDeriv", + "Version": "2016.8-1.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "df58958f293b166e4ab885ebcad90e02" + }, "openssl": { "Package": "openssl", "Version": "2.2.0", @@ -711,6 +958,38 @@ ], "Hash": "2bcca3848e4734eb3b16103bc9aa4b8e" }, + "parameters": { + "Package": "parameters", + "Version": "0.22.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "graphics", + "insight", + "methods", + "stats", + "utils" + ], + "Hash": "d54adeaf90f744bd8a342a46153a3fe5" + }, + "performance": { + "Package": "performance", + "Version": "0.12.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "datawizard", + "insight", + "stats", + "utils" + ], + "Hash": "6d0d9762077b82869a0ea9b17787b01e" + }, "pillar": { "Package": "pillar", "Version": "1.9.0", @@ -745,6 +1024,17 @@ "Repository": "CRAN", "Hash": "09eb987710984fc2905c7129c7d85e65" }, + "polynom": { + "Package": "polynom", + "Version": "1.4-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "ceb5c2a59ba33d42d051285a3e8a5118" + }, "prettyunits": { "Package": "prettyunits", "Version": "1.2.0", @@ -808,6 +1098,16 @@ ], "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" }, + "quadprog": { + "Package": "quadprog", + "Version": "1.5-8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5f919ae5e7f83a6f91dcf2288943370d" + }, "quarto": { "Package": "quarto", "Version": "1.4", @@ -968,6 +1268,28 @@ ], "Hash": "c19df082ba346b0ffa6f833e92de34d1" }, + "see": { + "Package": "see", + "Version": "0.8.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bayestestR", + "correlation", + "datawizard", + "effectsize", + "ggplot2", + "grDevices", + "graphics", + "insight", + "modelbased", + "parameters", + "performance", + "stats" + ], + "Hash": "bf62c13d7444a645fa6cfb7a54cdcdd3" + }, "stringi": { "Package": "stringi", "Version": "1.8.4", @@ -1201,12 +1523,39 @@ ], "Hash": "317a0538d32f4a009658bcedb7923f4b" }, + "xts": { + "Package": "xts", + "Version": "0.14.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods", + "zoo" + ], + "Hash": "288bc0fd02bb4e1489f37831d8803b2b" + }, "yaml": { "Package": "yaml", "Version": "2.3.8", "Source": "Repository", "Repository": "CRAN", "Hash": "29240487a071f535f5e5d5a323b7afbd" + }, + "zoo": { + "Package": "zoo", + "Version": "1.8-12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "5c715954112b45499fb1dadc6ee6ee3e" } } } diff --git a/scripts/inline_functions/price_inline_functions.R b/scripts/inline_functions/price_inline_functions.R new file mode 100644 index 0000000..ce7cb24 --- /dev/null +++ b/scripts/inline_functions/price_inline_functions.R @@ -0,0 +1,133 @@ +################################################################################ +# Regional and statewide price by year +# +# Attributes +# - region: ACEP region (string), of ["Coastal","Railbelt","Rural Remote"], default=NULL +# NULL returns average of all regions, specifying returns only that region +# - sector: Sector of interest (string), of ["commercial", "residential", "other"], default=NULL +# NULL returns average of all sectors +# - year: Calendar year of interest (integer), of [2011:2021] +# - decimals: Number of decimals for rounding (integer), default=2 +# - numeric_out: Output the value as a number instead of a string (boolean), default=FALSE +################################################################################ +## +# + +price <- function(region=NULL, sector=NULL, year, decimals=2, pct=FALSE, numeric_out=FALSE) { + + # Dataframe declaration + df = weighted_prices + + # Initialize result + result <- NA + + # Statewide capacity + if (is.null(region)) { + if (is.null(sector)) { + result = mean(df$weighted_price[df$year == year], na.rm = TRUE) + } + else if (!is.null(sector)) { + result = mean(df$weighted_price[df$sector == sector & df$year == year], na.rm = TRUE) + } + } + + # Regional capacity + if (!is.null(region)) { + if (is.null(sector)) { + result = mean(df$weighted_price[df$acep_energy_region == region & df$year == year], na.rm = TRUE) + } + else if (!is.null(sector)) { + result = mean(df$weighted_price[df$acep_energy_region == region & df$sector == sector & df$year == year], na.rm = TRUE) + } + } + +return(round(result, digits = decimals)) +} + + +test <- price(region="Railbelt", sector="residential", year=2017) + + +################################################################################ +# Regional price changes by year +# +# Attributes +# - region: ACEP region (string), of ["Coastal","Railbelt","Rural Remote"] +# - sector: Sector of interest (string), of ["commercial", "residential", "other"], default=NULL +# NULL returns average of all sectors +# - year1: First year of comparison (integer), default=2011 +# - year2: Second year of comparison (integer), default=2021 +# - decimals: Number of decimals for rounding (integer), default=2 +# - pct: Returns percentage change if TRUE (boolean), default=FALSE +################################################################################ +## +# + +price_delta <- function(region, sector=NULL, year1=2011, year2=2019, decimals=2, pct=FALSE, numeric_out=FALSE) { + + # Dataframe declaration + df = weighted_prices + + # All price in a region + if (is.null(sector)) { + price_2 <- price(region = region, + year = year2, + decimals = decimals, + numeric_out = TRUE) + price_1 <- price(region = region, + year = year1, + numeric_out = TRUE) + } + + # price in a region for a specific sector + else if (!is.null(sector)) { + price_2 <- price(region = region, + sector = sector, + year = year2, + decimals = decimals, + numeric_out = TRUE) + price_1 <- price(region = region, + sector = sector, + year = year1, + decimals = decimals, + numeric_out = TRUE) + } + + # Calculating the difference + result <- price_2 - price_1 + + + # Output as a percentage (Optional) + if (pct==TRUE) { + result <- (result / abs(price_1))*100 + + if (numeric_out==TRUE){ + # Output the result as a number + round(result,0) + } + else { + # Output the result as a string if percentage + formatC(round(result,0), format="g") + } + + } + + # Output the result + else { + if (numeric_out==TRUE){ + # Output the result as a number + round(result,0) + } + else { + # Output the result as a string if difference + formatC(round(result,0), format="g", big.mark = ",") + } + } +} + +price(region="Rural Remote", sector="commercial", year=2011) +price(region="Rural Remote", sector="other", year=2019) + +price_delta(region="Rural Remote", sector="other", pct=TRUE, numeric_out=TRUE) + +