# 1. load packages
library(tidyverse)
library(scales)
# 2. load data
file_path <- "sgu-solar-installations-2011-to-present-and-totals.csv"
df <- read_csv(file_path)
# 3. Data process
yearly_data <- df %>%
select(matches("Installation Quantity")) %>%
select(-`Total Installation Quantity`, -`Historic Total Installation Quantity (2001 - 2010)`) %>%
summarise(across(everything(), sum, na.rm = TRUE)) %>%
pivot_longer(cols = everything(), names_to = "Period", values_to = "Monthly_Count") %>%
mutate(Year = as.numeric(str_extract(Period, "\\d{4}"))) %>%
group_by(Year) %>%
summarise(Yearly_New_Installations = sum(Monthly_Count)) %>%
arrange(Year) %>%
ungroup()
# 4. Total new installations per year
ggplot(yearly_data, aes(x = factor(Year), y = Yearly_New_Installations)) +
geom_col(fill = "#0072B2") +
geom_text(aes(label = comma(Yearly_New_Installations)),
vjust = -0.5,
size = 3) +
labs(
title = "Annual Rooftop Solar Installations in Australia",
subtitle = "Total new installations per year",
x = "Year",
y = "Annual Installations"
) +
scale_y_continuous(labels = comma) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1)
)

# 5. Number of new installations per year
ggplot(yearly_data, aes(x = Year, y = Yearly_New_Installations)) +
geom_line(color = "#0072B2", linewidth = 1.2) +
geom_point(color = "#0072B2", size = 3) +
geom_text(aes(label = comma(Yearly_New_Installations)),
vjust = -1, size = 3.5) +
labs(
title = "Annual Rooftop Solar Installations in Australia (Trend)",
subtitle = "Number of new installations per year",
x = "Year",
y = "Annual Installations"
) +
scale_x_continuous(breaks = seq(min(yearly_data$Year), max(yearly_data$Year), by = 1)) +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0.1, 0.15))) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor.x = element_blank()
)

# Growth of total installed units over time (2010 - Present)
historic_total <- df %>%
pull(`Historic Total Installation Quantity (2001 - 2010)`) %>%
sum(na.rm = TRUE)
yearly_cumulative_data <- df %>%
select(matches("Installation Quantity")) %>%
select(-`Total Installation Quantity`, -`Historic Total Installation Quantity (2001 - 2010)`) %>%
summarise(across(everything(), sum, na.rm = TRUE)) %>%
pivot_longer(cols = everything(), names_to = "Period", values_to = "Monthly_Count") %>%
mutate(Year = as.numeric(str_extract(Period, "\\d{4}"))) %>%
group_by(Year) %>%
summarise(Yearly_New = sum(Monthly_Count)) %>%
arrange(Year) %>%
ungroup() %>%
mutate(Total_Cumulative = historic_total + cumsum(Yearly_New))
start_point <- tibble(
Year = 2010,
Yearly_New = 0,
Total_Cumulative = historic_total
)
final_plot_data <- bind_rows(start_point, yearly_cumulative_data)
ggplot(final_plot_data, aes(x = Year, y = Total_Cumulative)) +
geom_line(color = "#D55E00", linewidth = 1.2) +
geom_point(color = "#D55E00", size = 3) +
geom_text(aes(label = comma(Total_Cumulative)),
vjust = -1, size = 3, check_overlap = TRUE) +
labs(
title = "Total Cumulative Rooftop Solar Installations in Australia",
subtitle = "Growth of total installed units over time (2010 - Present)",
x = "Year",
y = "Total Cumulative Installations (Units)"
) +
scale_x_continuous(breaks = seq(2010, max(final_plot_data$Year), by = 1)) +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0.05, 0.15))) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.minor.x = element_blank()
)

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KIyBTZWN0aW9uIDMuICBUaGUgUmFwaWQgR3Jvd3RoIG9mIFJvb2Z0b3AgU29sYXIgaW4gQXVzdHJhbGlhIA0KIyBMaW5lIGNoYXJ0IHNob3dpbmcgdG90YWwgcm9vZnRvcCBzb2xhciBpbnN0YWxsYXRpb25zIG92ZXIgdGltZXMgDQoNCiMgMS4gbG9hZCBwYWNrYWdlcw0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCg0KIyAyLiBsb2FkIGRhdGENCmZpbGVfcGF0aCA8LSAic2d1LXNvbGFyLWluc3RhbGxhdGlvbnMtMjAxMS10by1wcmVzZW50LWFuZC10b3RhbHMuY3N2Ig0KZGYgPC0gcmVhZF9jc3YoZmlsZV9wYXRoKQ0KDQojIDMuIERhdGEgcHJvY2Vzcw0KeWVhcmx5X2RhdGEgPC0gZGYgJT4lDQogIHNlbGVjdChtYXRjaGVzKCJJbnN0YWxsYXRpb24gUXVhbnRpdHkiKSkgJT4lDQogIHNlbGVjdCgtYFRvdGFsIEluc3RhbGxhdGlvbiBRdWFudGl0eWAsIC1gSGlzdG9yaWMgVG90YWwgSW5zdGFsbGF0aW9uIFF1YW50aXR5ICgyMDAxIC0gMjAxMClgKSAlPiUNCiAgc3VtbWFyaXNlKGFjcm9zcyhldmVyeXRoaW5nKCksIHN1bSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gZXZlcnl0aGluZygpLCBuYW1lc190byA9ICJQZXJpb2QiLCB2YWx1ZXNfdG8gPSAiTW9udGhseV9Db3VudCIpICU+JQ0KICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoc3RyX2V4dHJhY3QoUGVyaW9kLCAiXFxkezR9IikpKSAlPiUNCiAgZ3JvdXBfYnkoWWVhcikgJT4lDQogIHN1bW1hcmlzZShZZWFybHlfTmV3X0luc3RhbGxhdGlvbnMgPSBzdW0oTW9udGhseV9Db3VudCkpICU+JQ0KICBhcnJhbmdlKFllYXIpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyA0LiBUb3RhbCBuZXcgaW5zdGFsbGF0aW9ucyBwZXIgeWVhcg0KZ2dwbG90KHllYXJseV9kYXRhLCBhZXMoeCA9IGZhY3RvcihZZWFyKSwgeSA9IFllYXJseV9OZXdfSW5zdGFsbGF0aW9ucykpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICIjMDA3MkIyIikgKyANCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvbW1hKFllYXJseV9OZXdfSW5zdGFsbGF0aW9ucykpLCANCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgDQogICAgICAgICAgICBzaXplID0gMykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkFubnVhbCBSb29mdG9wIFNvbGFyIEluc3RhbGxhdGlvbnMgaW4gQXVzdHJhbGlhIiwNCiAgICBzdWJ0aXRsZSA9ICJUb3RhbCBuZXcgaW5zdGFsbGF0aW9ucyBwZXIgeWVhciIsDQogICAgeCA9ICJZZWFyIiwNCiAgICB5ID0gIkFubnVhbCBJbnN0YWxsYXRpb25zIg0KICApICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpIA0KICApDQoNCiMgNS4gTnVtYmVyIG9mIG5ldyBpbnN0YWxsYXRpb25zIHBlciB5ZWFyDQpnZ3Bsb3QoeWVhcmx5X2RhdGEsIGFlcyh4ID0gWWVhciwgeSA9IFllYXJseV9OZXdfSW5zdGFsbGF0aW9ucykpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gIiMwMDcyQjIiLCBsaW5ld2lkdGggPSAxLjIpICsgDQogIGdlb21fcG9pbnQoY29sb3IgPSAiIzAwNzJCMiIsIHNpemUgPSAzKSArICAgDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBjb21tYShZZWFybHlfTmV3X0luc3RhbGxhdGlvbnMpKSwgDQogICAgICAgICAgICB2anVzdCA9IC0xLCBzaXplID0gMy41KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQW5udWFsIFJvb2Z0b3AgU29sYXIgSW5zdGFsbGF0aW9ucyBpbiBBdXN0cmFsaWEgKFRyZW5kKSIsDQogICAgc3VidGl0bGUgPSAiTnVtYmVyIG9mIG5ldyBpbnN0YWxsYXRpb25zIHBlciB5ZWFyIiwNCiAgICB4ID0gIlllYXIiLA0KICAgIHkgPSAiQW5udWFsIEluc3RhbGxhdGlvbnMiDQogICkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbih5ZWFybHlfZGF0YSRZZWFyKSwgbWF4KHllYXJseV9kYXRhJFllYXIpLCBieSA9IDEpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBjb21tYSwgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMSwgMC4xNSkpKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSANCiAgKQ0KDQojIEdyb3d0aCBvZiB0b3RhbCBpbnN0YWxsZWQgdW5pdHMgb3ZlciB0aW1lICgyMDEwIC0gUHJlc2VudCkNCmhpc3RvcmljX3RvdGFsIDwtIGRmICU+JQ0KICBwdWxsKGBIaXN0b3JpYyBUb3RhbCBJbnN0YWxsYXRpb24gUXVhbnRpdHkgKDIwMDEgLSAyMDEwKWApICU+JQ0KICBzdW0obmEucm0gPSBUUlVFKQ0KDQp5ZWFybHlfY3VtdWxhdGl2ZV9kYXRhIDwtIGRmICU+JQ0KICBzZWxlY3QobWF0Y2hlcygiSW5zdGFsbGF0aW9uIFF1YW50aXR5IikpICU+JQ0KICBzZWxlY3QoLWBUb3RhbCBJbnN0YWxsYXRpb24gUXVhbnRpdHlgLCAtYEhpc3RvcmljIFRvdGFsIEluc3RhbGxhdGlvbiBRdWFudGl0eSAoMjAwMSAtIDIwMTApYCkgJT4lDQogIHN1bW1hcmlzZShhY3Jvc3MoZXZlcnl0aGluZygpLCBzdW0sIG5hLnJtID0gVFJVRSkpICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiUGVyaW9kIiwgdmFsdWVzX3RvID0gIk1vbnRobHlfQ291bnQiKSAlPiUNCiAgbXV0YXRlKFllYXIgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KFBlcmlvZCwgIlxcZHs0fSIpKSkgJT4lDQogIGdyb3VwX2J5KFllYXIpICU+JQ0KICBzdW1tYXJpc2UoWWVhcmx5X05ldyA9IHN1bShNb250aGx5X0NvdW50KSkgJT4lDQogIGFycmFuZ2UoWWVhcikgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgbXV0YXRlKFRvdGFsX0N1bXVsYXRpdmUgPSBoaXN0b3JpY190b3RhbCArIGN1bXN1bShZZWFybHlfTmV3KSkNCg0Kc3RhcnRfcG9pbnQgPC0gdGliYmxlKA0KICBZZWFyID0gMjAxMCwNCiAgWWVhcmx5X05ldyA9IDAsDQogIFRvdGFsX0N1bXVsYXRpdmUgPSBoaXN0b3JpY190b3RhbA0KKQ0KDQpmaW5hbF9wbG90X2RhdGEgPC0gYmluZF9yb3dzKHN0YXJ0X3BvaW50LCB5ZWFybHlfY3VtdWxhdGl2ZV9kYXRhKQ0KDQpnZ3Bsb3QoZmluYWxfcGxvdF9kYXRhLCBhZXMoeCA9IFllYXIsIHkgPSBUb3RhbF9DdW11bGF0aXZlKSkgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAiI0Q1NUUwMCIsIGxpbmV3aWR0aCA9IDEuMikgKyANCiAgZ2VvbV9wb2ludChjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvbW1hKFRvdGFsX0N1bXVsYXRpdmUpKSwgDQogICAgICAgICAgICB2anVzdCA9IC0xLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJUb3RhbCBDdW11bGF0aXZlIFJvb2Z0b3AgU29sYXIgSW5zdGFsbGF0aW9ucyBpbiBBdXN0cmFsaWEiLA0KICAgIHN1YnRpdGxlID0gIkdyb3d0aCBvZiB0b3RhbCBpbnN0YWxsZWQgdW5pdHMgb3ZlciB0aW1lICgyMDEwIC0gUHJlc2VudCkiLA0KICAgIHggPSAiWWVhciIsDQogICAgeSA9ICJUb3RhbCBDdW11bGF0aXZlIEluc3RhbGxhdGlvbnMgKFVuaXRzKSINCiAgKSArDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAxMCwgbWF4KGZpbmFsX3Bsb3RfZGF0YSRZZWFyKSwgYnkgPSAxKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEsIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjA1LCAwLjE1KSkpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgDQogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpIA0KICApDQpgYGANCg0K