Skip to content
This repository was archived by the owner on Nov 29, 2024. It is now read-only.

Commit 019c676

Browse files
committed
Add SVG outputs; save final plots; move repayment rate data
1 parent 9efe72e commit 019c676

18 files changed

+1398
-44
lines changed

.devcontainer/devcontainer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
/* add apt packages (eg. system requirements for r packages) here.
1919
note that they are not frozen */
2020
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
21-
"packages": "libudunits2-dev,libxtst6,libxt6,libmagick++-dev,librsvg2-dev"
21+
"packages": "libudunits2-dev,libxtst6,libxt6,libmagick++-dev,librsvg2-dev,libproj-dev"
2222
},
2323
/* add additional r packages here */
2424
"ghcr.io/rocker-org/devcontainer-features/r-packages:1": {
25-
"packages": "github::rstudio/renv,tidyverse,here,httpgd,janitor,github::360-info/themes360info"
25+
"packages": "github::rstudio/renv,tidyverse,here,httpgd,janitor,ggalt,github::360-info/themes360info"
2626
}
2727
},
2828

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Thumbs.db
1616
/.quarto/
1717

1818
# no raw data (this cannot be shared!)
19-
/data/raw
19+
/data/raw/*
20+
!/data/raw/repayment-*.csv
2021

2122
# no exploratory plots that may expose individuals
2223
/out/explore

README.md

+85-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,94 @@
1-
# 360info Quarto scaffold
21

3-
Use this repo as a template to quickly start a 360info project in [Quarto](https://quarto.org).
42

5-
This template is designed to be used as a [dev container](https://containers.dev). You can work inside the container [locally using Docker and VScode](https://code.visualstudio.com/docs/devcontainers/containers), or you can open the project in GitHub Codespaces:
3+
# HELP debts
64

7-
![Screenshot of the code menu on a GitHub repository, showing the Codespaces tab](https://github.com/360-info/quarto-scaffold/assets/6520659/dc1afe15-2c1a-4a5a-8861-e3e131dacc02)
5+
### [📋 Add graphic to your story](blob/main/out/synth-heatmap.png?edshare)[📊 Get the data](data)[💻 Reproduce the analysis](#-reproduce-the-analysis)
86

9-
Add dependencies, such as R package or other tools, using the `.devcontainer/devcontainer.json` file.
7+
Visualises the impact of changing repayment rates and indexation on
8+
Australian student debt
109

11-
The project's `README.md` will be generated from `README.qmd`, not this file. Fill the frontmatter in there to customise the README. When the project is ready for publication, overwrite this file with the rendered `out/README.md`.
10+
## ♻️ Use + Remix rights
1211

13-
## Adding analyses or embeds
12+
![[Creative Commons Attribution
13+
4.0](https://creativecommons.org/licenses/by/4.0)](https://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png)
1414

15-
This template just includes the project scaffolding to et started. To create an analysis or embed document, use [`360-info/quarto-templates`](https://github.com/360-info/quarto-templates):
15+
These charts, as well as the analyses that underpin them, are available
16+
under a Creative Commons Attribution 4.0 licence. This includes
17+
commercial reuse and derivates.
1618

17-
```bash
18-
quarto use templaye 360-info/quarto-templates/360-embed
19+
<!-- Do any of the data sources fall under a different licence? If so, describe the licence and which parts of the data fall under it here! if most of it does, change the above and replace LICENCE.md too -->
20+
21+
Data in these charts comes from:
22+
23+
<ul>
24+
<li>
25+
<a href="https://www.ato.gov.au/about-ato/research-and-statistics/in-detail/taxation-statistics/taxation-statistics-previous-editions/taxation-statistics-2016-17/statistics/individuals/individuals-sample-files">Australian
26+
Taxation Office</a>
27+
</li>
28+
</ul>
29+
30+
**Please attribute 360info and the data sources when you use and remix
31+
these visualisations.**
32+
33+
> [!WARNING]
34+
>
35+
> Please note that the source data for this analysis is not included
36+
> with this repository. It is available from the ATO at the above link
37+
> on request and upon submission of a confidentiality deed.
38+
39+
## 💻 Reproduce the analysis
40+
41+
### Quickstart: use the dev container
42+
43+
This project comes with a ready-to-use [dev
44+
container](https://code.visualstudio.com/docs/remote/containers) that
45+
includes everything you need to reproduce the analysis (or do a similar
46+
one of your own!), including [R](https://r-project.org) and
47+
[Quarto](https://quarto.org).
48+
49+
[![Open in GitHub
50+
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/360-info/report-helpdebt?quickstart=1)
51+
52+
If you have Docker installed, you can build and run the container
53+
locally:
54+
55+
- Download or clone the project
56+
- Open it in [Visual Studio Code](https://code.visualstudio.com)
57+
- Run the **Remote-Containers: Reopen in Container** command
58+
59+
Once the container has launched (it might take a few minutes to set up
60+
the first time), you can run the analysis scripts with:
61+
62+
``` sh
63+
quarto render
1964
```
65+
66+
Or look for the `.qmd` files to modify the analysis.
67+
68+
### Manual setup
69+
70+
To setup a development environment manually,
71+
72+
You’ll need to:
73+
74+
- [Download and install Quarto](https://quarto.org/docs/get-started)
75+
- [Download the install R](https://www.r-project.org)
76+
- Satisfy the R package dependencies. In R:
77+
- Install the [`renv`](https://rstudio.github.io/renv) package with
78+
`install.packages("renv")`,
79+
- Then run `renv::restore()` to install the R package dependencies.
80+
- (For problems satisfying R package dependencies, refer to [Quarto’s
81+
documentation on virtual
82+
environments](https://quarto.org/docs/projects/virtual-environments.html).)
83+
84+
Now, render the `.qmd` files to the `/out` directory with:
85+
86+
``` sh
87+
quarto render
88+
```
89+
90+
## ❓ Help
91+
92+
If you find any problems with our analysis or charts, please feel free
93+
to [create an
94+
issue](https://github.com/360-info/report-helpdebt/issues/new)!

README.qmd

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
---
22
format: gfm
33
360readme:
4-
title: Title here
5-
summary: One line summary here
6-
repo: report-example
7-
share-url: https://example.360visuals.org/example
4+
title: HELP debts
5+
summary: Visualises the impact of changing repayment rates and indexation on Australian student debt
6+
repo: report-helpdebt
7+
share-url: blob/main/out/synth-heatmap.png
88
data-sources: |
99
<ul>
10-
<li><a href="https://example.com">Example 1</a></li>
11-
<li><a href="https://example.com">Example 2</a></li>
10+
<li><a href="https://www.ato.gov.au/about-ato/research-and-statistics/in-detail/taxation-statistics/taxation-statistics-previous-editions/taxation-statistics-2016-17/statistics/individuals/individuals-sample-files">Australian Taxation Office</a></li>
1211
</ul>
1312
---
1413

@@ -31,6 +30,10 @@ Data in these charts comes from:
3130

3231
**Please attribute 360info and the data sources when you use and remix these visualisations.**
3332

33+
:::{.callout-warning}
34+
Please note that the source data for this analysis is not included with this repository. It is available from the ATO at the above link on request and upon submission of a confidentiality deed.
35+
:::
36+
3437
## 💻 Reproduce the analysis
3538

3639
### Quickstart: use the dev container

analysis/help/index.qmd

+109-25
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ code-fold: true
1414
#| label: setup
1515
library(tidyverse)
1616
library(RColorBrewer)
17+
library(ggalt)
1718
library(here)
1819
dir.create(here("out", "explore"), showWarnings = FALSE, recursive = TRUE)
1920
```
@@ -193,7 +194,7 @@ Let's tidy up the repayment rate tables. Note that the top rate for each year is
193194

194195
```{r}
195196
#| label: get-repayment-rates
196-
here("data", "repayment-rates-2004-2019.csv") |>
197+
here("data", "raw", "repayment-rates-2004-2019.csv") |>
197198
read_csv(col_types = "ccc") |>
198199
pivot_longer(-Year, names_to = "rate", values_to = "threshold") |>
199200
mutate(
@@ -208,7 +209,7 @@ here("data", "repayment-rates-2004-2019.csv") |>
208209
filter(!is.na(threshold)) ->
209210
repayment_rates_oldest
210211
211-
here("data", "repayment-rates-2019-2021.csv") |>
212+
here("data", "raw", "repayment-rates-2019-2021.csv") |>
212213
read_csv(col_types = "ccc") |>
213214
pivot_longer(-Rate, names_to = "Year", values_to = "threshold") |>
214215
mutate(
@@ -248,7 +249,7 @@ tidy_ratetables <- function(path, suffix = c("*", "+")) {
248249
}
249250
250251
tibble(
251-
path = list.files(here("data"),
252+
path = list.files(here("data", "raw"),
252253
pattern = glob2rx("repayment-rates-FY20??.csv"),
253254
full.names = TRUE)) ->
254255
rate_table_files_newest
@@ -275,7 +276,8 @@ repayment_rates_oldest |>
275276
rename(repay_rate = rate, repay_threshold = threshold) |>
276277
group_by(year_end) |>
277278
mutate(repay_threshold =
278-
if_else(repay_rate == max(repay_rate, na.rm = TRUE), Inf, repay_threshold)) ->
279+
if_else(repay_rate == max(repay_rate, na.rm = TRUE), Inf, repay_threshold)) |>
280+
write_csv(here("data", "repayment-rates.csv"))->
279281
repayment_rates
280282
```
281283

@@ -945,6 +947,8 @@ stats_alldebtors_plot_scaled
945947
946948
save_360plot(stats_alldebtors_plot_scaled,
947949
here("out", "stats-alldebtors-scaled-final.png"))
950+
save_360plot(stats_alldebtors_plot_scaled,
951+
here("out", "stats-alldebtors-scaled-final.svg"))
948952
```
949953

950954
### Wide for Datawrapper/Flourish
@@ -972,32 +976,24 @@ I'd like to make a heatmap that really shows where these categories lie. Instead
972976
```{r}
973977
#| label: synthetic-data
974978
expand_grid(
975-
year_end = c("2023*", "2023+"),
979+
year_end = "2018",
976980
income = seq(0, 150000, by = 1000),
977981
help_debt = seq(0, 100000, by = 500)) ->
978982
synthetic
979983
980984
# get the repayment rates under both scenarios for just 2024
981985
982-
repayment_rates_new |>
983-
filter(year_end == "2023*") |>
986+
repayment_rates_oldest |>
987+
filter(year_end == "2018") |>
984988
mutate(repay_threshold =
985989
if_else(rate == max(rate, na.rm = TRUE), Inf, threshold)) |>
986990
select(year_end, repay_rate = rate, repay_threshold) ->
987991
latest_repayment_rates_nopolicy
988992
989-
repayment_rates_new_alppolicy |>
990-
filter(year_end == "2023+") |>
991-
mutate(repay_threshold =
992-
if_else(rate == max(rate, na.rm = TRUE), Inf, threshold)) |>
993-
select(year_end, repay_rate = rate, repay_threshold) ->
994-
latest_repayment_rates_alppolicy
995-
996-
latest_repayment_rates <-
997-
bind_rows(latest_repayment_rates_nopolicy, latest_repayment_rates_alppolicy)
993+
latest_repayment_rates <- latest_repayment_rates_nopolicy
998994
999995
indexation_rates |>
1000-
filter(str_detect(year_end, "2023")) ->
996+
filter(str_detect(year_end, "2018")) ->
1001997
latest_indexation_rates
1002998
1003999
# now join them all
@@ -1019,18 +1015,15 @@ synthetic |>
10191015
repay_amount < 1 ~ "No repayment (low income)",
10201016
net_reduction < -200 ~ "Debt grew despite payment",
10211017
between(net_reduction, -200, 200) ~ "Indexation and repayment balanced",
1022-
net_reduction > 200 ~ "Debt reduced"),
1023-
scenario = case_match(year_end,
1024-
"2023*" ~ "Before 2024 pre-budget policy: 7.1% indexation",
1025-
"2023+" ~ "With 2024 pre-budget policy: 3.2% indexation")) ->
1018+
net_reduction > 200 ~ "Debt reduced")) ->
10261019
synthetic_categories
10271020
10281021
# visualise
10291022
10301023
ggplot(synthetic_categories) +
10311024
aes(x = income, y = help_debt) +
10321025
geom_raster(aes(fill = help_category)) +
1033-
facet_wrap(vars(scenario)) +
1026+
# facet_wrap(vars(scenario)) +
10341027
scale_fill_manual(
10351028
values = c(
10361029
"Debt grew despite payment" = "#c7321c",
@@ -1058,15 +1051,106 @@ ggplot(synthetic_categories) +
10581051
x = "Income",
10591052
y = "HELP loan balance",
10601053
fill = NULL,
1061-
title = "HELP loans going backwards in 2023",
1062-
subtitle = "Debts that \"go backwards\" to remain last year for some people earning $50,000–70,000 despite new policy",
1054+
title = "HELP loans didn't go backwards before 2020",
1055+
subtitle = "Before 2020, the combination of repayment rates and indexation levels ensured that if you were making mandatory payments, your balance never rose.",
1056+
# subtitle = "Debts that \"go backwards\" to remain last year for some people earning $50,000–70,000 despite new policy",
10631057
caption = paste(
10641058
"**CHART:** James Goldie, 360info",
10651059
"**DATA:** Australian Taxation Office",
10661060
sep = "<br>")) ->
10671061
synthetic_heatmap
10681062
10691063
save_360plot(synthetic_heatmap,
1070-
here("out", "synth-heatmap.png"), shape = "sdtv-landscape")
1064+
here("out", "synth-heatmap-2018.png"), shape = "sdtv-landscape")
10711065
```
10721066

1067+
### Repayment rates over time
1068+
1069+
Although indexation is a big part of this, the changing repayment rates are also a big component. Let's visualise those too.
1070+
1071+
1072+
```{r}
1073+
repayment_rates |>
1074+
filter(!str_detect(year_end, fixed("+"))) |>
1075+
rename(threshold_upper = repay_threshold) |>
1076+
arrange(year_end, repay_rate) |>
1077+
group_by(year_end) |>
1078+
mutate(
1079+
year_end = as.integer(str_remove(year_end, fixed("*"))),
1080+
threshold_lower = lag(threshold_upper, 1)) |>
1081+
replace_na(list(threshold_lower = 0)) ->
1082+
repayment_ranges
1083+
1084+
pal_YlGnBu <- brewer.pal(7, "YlGnBu") |> colorRampPalette()
1085+
year_count <- repayment_ranges |> pull(repay_rate) |> unique() |> length()
1086+
repay_rate_pal <- pal_YlGnBu(year_count)
1087+
1088+
repayment_ranges |>
1089+
ungroup() |>
1090+
mutate(
1091+
repay_rate_fct = factor(repay_rate,
1092+
levels = seq(0, 0.1, by = 0.005),
1093+
labels = seq(0, 0.1, by = 0.005) |> scales::percent()),
1094+
repay_rate_fct = fct_drop(repay_rate_fct),
1095+
threshold_upper =
1096+
if_else(is.infinite(threshold_upper), 200000, threshold_upper)
1097+
) |>
1098+
ggplot() +
1099+
aes(x = year_end, fill = repay_rate_fct) +
1100+
geom_ribbon(aes(ymin = threshold_lower, ymax = threshold_upper),
1101+
colour = "#00000044",
1102+
stat = "stepribbon") +
1103+
scale_fill_manual(values = c("white", repay_rate_pal)) +
1104+
scale_x_continuous(expand = expansion()) +
1105+
scale_y_continuous(expand = expansion(), labels = scales::label_currency()) +
1106+
coord_cartesian(ylim = c(NA, 160000)) +
1107+
annotate_360_glasslight(
1108+
x = 2006.5, y = 20000, hjust = 0,
1109+
label = paste(
1110+
"Until 2019, HELP loan repayments",
1111+
"**started at 4%.** This meant anyone",
1112+
"repaying a debt would see their",
1113+
"balance go down.",
1114+
sep = "<br>"
1115+
),
1116+
size = 3
1117+
) +
1118+
annotate_360_glasslight(
1119+
x = 2023.5, y = 25000, hjust = 1,
1120+
label = paste(
1121+
"The **lower rates** introduced since",
1122+
"then have meant people making small",
1123+
"payments end up going backwards,",
1124+
"as indexation overtakes their repayment.",
1125+
sep = "<br>"
1126+
),
1127+
size = 3
1128+
) +
1129+
theme_360(base_size = 14) +
1130+
theme(
1131+
panel.ontop = TRUE,
1132+
panel.grid.major.x = element_blank(),
1133+
panel.grid.minor.x = element_blank(),
1134+
panel.grid.major.y = element_line(colour = "#00000022"),
1135+
panel.grid.minor.y = element_blank(),
1136+
) +
1137+
labs(
1138+
x = NULL, y = "HELP loan balance",
1139+
fill = "Repayment rate",
1140+
title = "HELP loan repayment rates",
1141+
subtitle = paste(
1142+
"The introduction of lower repayment rates in recent years has produced a new class of people",
1143+
"whose **debt repayments are overshadowed by indexation**",
1144+
sep = "<br>"),
1145+
caption = paste(
1146+
"**CHART:** James Goldie, 360info",
1147+
"**DATA:** Australian Parliament House, Australian Taxation Office",
1148+
sep = "<br>")) ->
1149+
repayment_rates_plot
1150+
1151+
save_360plot(repayment_rates_plot,
1152+
here("out", "repayment-rates.png"), shape = "sdtv-landscape")
1153+
save_360plot(repayment_rates_plot,
1154+
here("out", "repayment-rates.svg"), shape = "sdtv-landscape")
1155+
1156+
```

0 commit comments

Comments
 (0)