Australia’s migration story is rich and diverse. This site highlights key migration trends over the past decade.
Migrant Arrivals: View the number of arrivals by visa type over 10 years. See which visa categories dominate and how trends have shifted.
NOTE: “Temporary visas – Other” includes working holidays and skilled migrants.
Countries of Birth: Explore the top countries of origin for migrants, selected based on 2022–23 data.
NOTE: “China (c)” excludes Special Administrative Regions and Taiwan.
State and Territories: Examine the distribution of migrants across Australia and compare state-level data. Use the ‘autoscale’ and ‘zoom’ options to focus on specific areas of the country. Enable ‘Compare data on hover’ to view and compare migrant numbers between states.
NOTE: 2023 figures are preliminary, ending in June 2023.
Employment: Discover employment trends among migrants over the past five years by visa group.
Industry: See the most popular job industries for employed migrants (2021–2022)
Data Source: Australian Bureau of Statistics, Arrivals | Migration | State and Territory | Migrant Industry
---
title: "Migration in Australia"
author: "Karen Tscharke"
output:
flexdashboard::flex_dashboard:
social: menu
source_code: embed
---
```{r setup, include=FALSE}
library(ggplot2)
library(plotly)
library(plyr)
library(tidyverse)
library(lubridate)
library(flexdashboard)
library(readr)
library(dplyr)
library(tidyr)
library(sf)
library(scales)
library(dbplyr)
library(rsconnect)
setwd("~/Downloads")
# Load data from CSV file
data <- read_csv("Arrivals.csv")
# Create the dataset
data <- tibble(
`Month-Year` = c("Jun-13", "Sep-13", "Dec-13", "Mar-14", "Jun-14", "Sep-14", "Dec-14", "Mar-15",
"Jun-15", "Sep-15", "Dec-15", "Mar-16", "Jun-16", "Sep-16", "Dec-16", "Mar-17",
"Jun-17", "Sep-17", "Dec-17", "Mar-18", "Jun-18", "Sep-18", "Dec-18", "Mar-19",
"Jun-19", "Sep-19", "Dec-19", "Mar-20", "Jun-20", "Sep-20", "Dec-20", "Mar-21",
"Jun-21", "Sep-21", "Dec-21", "Mar-22", "Jun-22", "Sep-22", "Dec-22", "Mar-23", "Jun-23"),
`Temporary visas - Student` = c(86.21, 95.29, 99.68, 109.22, 114.33, 119.01, 122.49, 123.53, 122.13, 125.04, 125.98,
129.84, 132.13, 136.59, 137.87, 146.81, 149.41, 152.65, 151.94, 153.79, 157.63, 163.24,
166.64, 167.55, 164.34, 155.54, 150.65, 134.53, 110.44, 64.87, 42.57, 0.78, 1.51, 2.08,
29.21, 102.72, 141.42, 215.62, 237.79, 263.4, 282.57),
`Temporary visas - Other` = c(157.85, 154.56, 151.71, 143.17, 138.83, 136.86, 136.03, 137.4, 140.8, 142.27, 144.67,
147.69, 149.63, 153.57, 157.9, 161.96, 165.41, 168.58, 169.17, 169.17, 169.68, 169.5,
171.27, 173.96, 186.33, 204.99, 235.2, 253.08, 203.21, 144.46, 75.71, 19.04, 28.06, 34.91,
48.13, 79.71, 124.79, 177.69, 226.55, 250.29, 270.97),
`Permanent visas` = c(86.76, 91.24, 94.29, 95.68, 94.35, 91.26, 89.29, 90.23, 91.49, 90.67, 89.75, 88.97, 90.59,
97.17, 103.73, 107.41, 106.2, 100.85, 94.47, 90.08, 87.91, 87.1, 85.09, 83.85, 85.39, 86.99,
91.24, 90.84, 70.89, 51.45, 37.35, 27.25, 36.95, 43.18, 55.51, 66.04, 71.1, 78.63, 77.06, 76.04, 79.67),
`NZ citizens` = c(54.12, 50.08, 45.75, 41.09, 37.77, 35.62, 33.78, 32.57, 31.75, 31.28, 31.47, 32.26, 33.7, 34.88,
34.86, 33.79, 32.33, 31.16, 30.39, 30.37, 30.38, 30.57, 30.84, 30.57, 30.54, 30.36, 30.41, 28.73,
22.22, 15.9, 12.03, 11.15, 16.95, 18.99, 19.16, 21.96, 24.12, 30.02, 35.68, 39.42, 41.32),
`Australian citizens` = c(77.1, 76.88, 75.81, 74.51, 72.18, 71.65, 71.3, 71.18, 71.68, 72.03, 73.12, 74.23, 75.8,
77.85, 78.67, 79.64, 79.28, 79.2, 78.81, 78.01, 77.16, 76.5, 75.99, 76.02, 78.9, 82.84, 95.02,
106.04, 96.41, 83.39, 66.66, 54.1, 61.37, 61.09, 61.57, 63.03, 62.48, 66.93, 66.36, 62.47, 59.4)
)
# Convert 'Month-Year' to Date format
data <- data %>%
mutate(Date = my(`Month-Year`))
# Reshape data to long format
data_long <- data %>%
pivot_longer(cols = -c(`Month-Year`, Date),
names_to = "Visa_Type",
values_to = "Arrivals")
# Add the `text` column to your data (this step is still important)
data_long$text <- paste("Visa Type:", data_long$Visa_Type,
"<br>Year:", format(data_long$Date, "%Y"),
"<br>Arrivals:", data_long$Arrivals)
# Define the custom colors with a stronger yellow
custom_colors <- c("#4575b4", "#91bfdb", "#fee090", "#fc8d59", "#d73027")
setwd("/Users/karengyedu/Downloads")
# Read in the dataset
countriesbirth <- read_csv("/Users/karengyedu/Downloads/countriesbirth.csv")
# Remove the ' ('000')' from column names
colnames(countriesbirth) <- gsub(" \\(\\'000\\)", "", colnames(countriesbirth))
# Convert the 'Month-Year' to 'Date' format and extract the 'Year'
countriesbirth <- countriesbirth %>%
mutate(Month_Year_Date = as.Date(paste0("01-", `Month-Year`), format="%d-%b-%y")) %>%
mutate(Year = format(Month_Year_Date, "%Y")) # Extract the year from the date
# Check the structure of the data to ensure the 'Year' is extracted correctly
str(countriesbirth)
# Reshape the data to long format for easier plotting using pivot_longer
countriesbirth_long <- countriesbirth %>%
pivot_longer(cols = `India`:`UK`,
names_to = "Country",
values_to = "Immigrants") %>%
mutate(Year = as.factor(Year)) # Treat 'Year' as a factor to ensure proper ordering
# Check the reshaped data
head(countriesbirth_long)
# Assuming countriesbirth_long is your dataset
# Create a 'text' column for hover text
countriesbirth_long$text <- with(countriesbirth_long,
paste("Country: ", Country,
"<br>Year: ", Year,
"<br>Immigrants: ", Immigrants))
# Set working directory (adjust the path if needed)
setwd("/Users/karengyedu/Downloads")
# Step 1: Read the new shapefile
australia_shapefile <- st_read("GCCSA_2021_AUST_SHP_GDA2020/australian_states.shp")
# Create data for 2013, 2018, and 2023
year_2013_data <- data.frame(
name = c("New South Wales", "Victoria", "Queensland", "Western Australia", "South Australia", "Tasmania", "Northern Territory", "Australian Capital Territory"),
total_migrants = c(203200, 177040, 112530, 106550, 35780, 5220, 11220, 8340),
year = 2013
)
year_2018_data <- data.frame(
name = c("New South Wales", "Victoria", "Queensland", "Western Australia", "South Australia", "Tasmania", "Northern Territory", "Australian Capital Territory"),
total_migrants = c(365760, 350790, 119380, 50440, 52750, 11480, 3160, 17010),
year = 2018
)
year_2023_data <- data.frame(
name = c("New South Wales", "Victoria", "Queensland", "Western Australia", "South Australia", "Tasmania", "Northern Territory", "Australian Capital Territory"),
total_migrants = c(331670, 297630, 136180, 117500, 54490, 8190, 6030, 16980),
year = 2023
)
# Combine all data into one for easier merging
combined_data <- bind_rows(
year_2013_data,
year_2018_data,
year_2023_data
)
# Step 2: Merge combined data with shapefile
merged_data <- australia_shapefile %>%
left_join(combined_data, by = "name")
# Add a new column 'hover_text' for tooltips
merged_data$hover_text <- paste("State: ", merged_data$name,
"<br>Year: ", merged_data$year,
"<br>Total Migrants: ", merged_data$total_migrants)
# Define custom color palette
custom_palette <- c("#f2f0f7", "#cbc9e2", "#9e9ac8", "#6a51a3")
setwd("/Users/karengyedu/Downloads")
# Read in the dataset
Employment <- read_csv("/Users/karengyedu/Downloads/Employment.csv",
col_types = cols(`2018-19` = col_number(),
`2020-21` = col_number(),
`2021-22` = col_number()))
# Transform the data into long format
Employment_long <- Employment %>%
pivot_longer(cols = starts_with("20"),
names_to = "Year",
values_to = "Visa_Count")
# Calculate total Visa Count for each Sub Visa Type
ordering <- Employment_long %>%
group_by(`Sub Visa Type`) %>%
summarise(Total_Visa_Count = sum(Visa_Count, na.rm = TRUE)) %>%
arrange(Total_Visa_Count, decreasing = TRUE) # Arrange from largest to smallest
# Reorder the Sub Visa Type factor levels based on the Total Visa Count
Employment_long <- Employment_long %>%
mutate(`Sub Visa Type` = factor(`Sub Visa Type`,
levels = ordering$`Sub Visa Type`))
# Read the dataset
Jobtype <- read_csv("/Users/karengyedu/Downloads/Jobtype.csv",
skip = 1)
# Reorder the 'Industry' column as a factor with reversed levels (highest to lowest)
Jobtype_sorted <- Jobtype %>%
arrange(desc(`%`)) # Sort by the '%' column in descending order
Jobtype_sorted$Industry <- factor(Jobtype_sorted$Industry, levels = rev(Jobtype_sorted$Industry))
```
# Arrivals
## Row {.tabset .tabset-fade}
### Arrivals
```{r Arrivals, echo=FALSE}
p <- plot_ly(
data_long,
x = ~Date,
y = ~Arrivals,
color = ~Visa_Type,
type = 'scatter',
mode = 'lines', # Ensures lines are plotted
text = ~text, # Use the 'text' column for hover info
hoverinfo = 'text', # Display the hover text
line = list(width = 3), # Set the line width to make the lines thicker
colors = custom_colors # Apply the custom colors
)
# Add layout configuration
# Build the Plotly object
p <- plot_ly(
data_long,
x = ~Date,
y = ~Arrivals,
color = ~Visa_Type,
type = 'scatter',
mode = 'lines', # Ensures lines are plotted
text = ~text, # Use the 'text' column for hover info
hoverinfo = 'text', # Display the hover text
line = list(width = 3), # Set the line width to make the lines thicker
colors = custom_colors # Apply the custom colors
)
# Add layout configuration
p <- p %>% layout(
title = list(
text = "<b>A Decade of Migrant Arrivals in Australia</b>", # Add bold HTML tags
font = list(size = 18, family = "Arial", color = "#333333")
),
xaxis = list(
title = "Year", # Keep x-axis title
showgrid = FALSE, # Remove the gridlines
showline = TRUE, # Keep the axis line
showticklabels = TRUE, # Keep the tick labels
tickvals = seq(2013, 2023, 1), # Specify tick values for every year
tickformat = "%Y" # Ensure the year format is displayed
),
yaxis = list(
title = "Arrivals (Thousands)", # Keep y-axis title
showgrid = FALSE, # Remove the gridlines
showline = TRUE, # Keep the axis line
showticklabels = TRUE, # Keep the tick labels
rangemode = 'tozero' # Set the y-axis range to start from 0
),
legend = list(
title = list(text = 'Visa Type'),
orientation = 'h', # Horizontal orientation for the legend
x = 0.5, # Position the legend in the center horizontally
xanchor = 'center', # Anchor the legend at the center
y = -0.2 # Position the legend below the plot
),
hovermode = 'closest'
)
# Display the plot
p
```
### About This Site
Australia’s migration story is rich and diverse. This site highlights key migration trends over the past decade.
#### **Explore Migration Trends**
[**Migrant Arrivals:**]{.underline} View the number of arrivals by visa type over 10 years. See which visa categories dominate and how trends have shifted.
***NOTE:** "Temporary visas – Other" includes working holidays and skilled migrants.*
[**Countries of Birth**]{.underline}**:** Explore the top countries of origin for migrants, selected based on 2022–23 data.
***NOTE:*** *"China (c)" excludes Special Administrative Regions and Taiwan.*
[**State and Territories**]{.underline}**:** Examine the distribution of migrants across Australia and compare state-level data. Use the 'autoscale' and 'zoom' options to focus on specific areas of the country. Enable 'Compare data on hover' to view and compare migrant numbers between states.
***NOTE:** 2023 figures are preliminary, ending in June 2023.*
[**Employment**]{.underline}: Discover employment trends among migrants over the past five years by visa group.
[**Industry**]{.underline}**:** See the most popular job industries for employed migrants (2021–2022)
**Data Source:** Australian Bureau of Statistics, [Arrivals](https://www.abs.gov.au/statistics/people/population/overseas-migration/latest-release#migrant-arrivals) \| [Migration](https://www.abs.gov.au/media-centre/media-releases/record-high-net-overseas-migration-driven-temporary-visa-holders-2022-23#:~:text=In%202022%2D23%2C%20737%2C000%20migrants,) \| [State and Territory](https://www.abs.gov.au/statistics/people/population/overseas-migration/latest-release#state-and-territory) \| [Migrant Industry](https://www.abs.gov.au/statistics/labour/jobs/jobs-australia/latest-release#employed-migrants)
## Row {.tabset .tabset-fade}
### Birth Nationalities
```{r Countries, echo=FALSE}
# Create the ggplot object
p2 <- ggplot(countriesbirth_long, aes(x = Year, y = Immigrants, fill = Country, text = text)) +
geom_bar(stat = "identity") +
scale_fill_manual(values = c(
"India" = "#d73027", # red
"China(c)" = "#fc8d59", # light orange
"Philippines" = "#fee090", # pale yellow
"Australia" = "#4575b4", # light blue
"UK" = "#91bfdb" # soft blue
)) +
theme_minimal() +
labs(
title = "Top 5 Countries of Birth for Australian Migrants",
x = "Year",
y = "Arrivals (Thousands)"
) +
theme(
axis.text.x = element_text(angle = 0, hjust = 1), # Rotate x-axis labels
panel.grid.major.x = element_blank(), # Remove major gridlines for x-axis
panel.grid.major.y = element_line(color = "#f0f0f0", size = 0.1), # Faint major y-axis gridline
panel.grid.minor = element_blank(), # Remove minor gridlines
panel.background = element_blank(), # Remove panel background
plot.background = element_blank(), # Remove plot background
legend.position = "bottom", # Move the legend to the bottom
legend.justification = "center" # Center-align the legend at the bottom
)
# Convert the ggplot object to a plotly object
p2 <- ggplotly(p2, tooltip = "text") # Add hover tooltips
# Modify the layout to adjust the title font and legend
p2 <- p2 %>% layout(
title = list(
text = "<b>Top 5 Countries of Birth for Australian Migrants</b>", # Make title bold
font = list(size = 18, family = "Arial", color = "#333333") # Customize font properties
),
legend = list(
title = list(text = 'Country'), # Adjust the legend title
orientation = 'h', # Horizontal orientation
x = 0.5, # Center horizontally
xanchor = 'center', # Anchor legend at the center
y = -0.2 # Position below the plot
)
)
# Display the plot
p2
```
### State and Territory
```{r State and Territory, echo=FALSE}
# ggplot code
ggplot_obj <- ggplot(data = merged_data) +
geom_sf(aes(fill = total_migrants, text = hover_text)) +
scale_fill_gradientn(colors = custom_palette,
labels = label_number(),
name = "Total Migrants") +
facet_wrap(~ year, nrow = 3) + # Facet by year, 3 rows
labs(title = "Australian Migration Distribution by State and Territory") +
theme_void() +
theme(
legend.position = "right", # Move legend to the right
plot.title = element_text(hjust = 0.5, size = 18, family = "Arial", color = "#333333", face = "bold"),
plot.margin = margin(t = 20) # Increase the top margin (t = top)
)
# Convert ggplot to plotly for interactivity
p3 <- ggplotly(ggplot_obj, tooltip = "text") %>%
layout(
title = list(
text = "<b>Australian Migration Distribution by State and Territory<b>",
x = 0.5,
font = list(size = 18, family = "Arial", color = "#333333", style = "bold") # Bold title
),
geo = list(showcoastlines = TRUE, coastlinecolor = "black", projection = list(type = 'mercator')),
margin = list(t = 50, b = 50, l = 50, r = 50) # Adjust plot margins
)
# Display the interactive plot
p3
```
# Employment
## Column {data-width="600"}
### Employment
```{r Employment, echo=FALSE}
# ggplot code
ggplot_obj <- ggplot(Employment_long, aes(x = Visa_Count, y = `Sub Visa Type`, fill = Year,
text = paste("Visa Type:", `Sub Visa Type`,
"<br>Year:", Year,
"<br>Count:", comma(Visa_Count)))) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Employment of Migrants by Visa Group from 2018 to 2022",
subtitle = "double-click on the legend to compare years",
x = "Job Count",
y = "Visa Group") +
theme_minimal() +
scale_fill_brewer(palette = "RdYlBu") +
scale_x_continuous(labels = comma) + # Format x-axis values with commas
theme(
# Lighten gridlines
panel.grid.major = element_line(color = "gray90", linewidth = 0.5), # Faint gridlines
panel.grid.minor = element_line(color = "gray95", linewidth = 0.25), # Lighter minor gridlines
# Make axis titles bold
axis.title.x = element_text(face = "bold"),
axis.title.y = element_text(face = "bold")
)
# Convert ggplot to a plotly object to enable hover labels
plotly_obj <- ggplotly(ggplot_obj, tooltip = "text")
# Add a title to the legend and include the subtitle in the layout
p4 <- plotly_obj %>% layout(
legend = list(title = list(text = "Year")),
title = list(
text = "<b>Employment of Migrants by Visa Group from 2018 to 2022<b><br><sup>double-click on the legend to compare years</sup>",
font = list(size = 18, family = "Arial", color = "#333333") # Title font customization
),
subtitle = list(
text = "double-click on the legend to compare years",
font = list(size = 14, family = "Arial", color = "#333333") # Subtitle font customization
)
)
# Display the interactive plot
ggplotly(p4)
```
## Column {data-width="500"}
### Employment Industry
```{r Industry, echo=FALSE}
ggplot_obj <- ggplot(Jobtype_sorted, aes(x = `%`, y = Industry, text = paste("Percentage: ", `%`, "%"))) +
geom_point(size = 3, color = "#E41A1C") + # Red color (for high contrast)
geom_segment(aes(x = 0, xend = `%`, y = Industry, yend = Industry), color = "#E41A1C", linewidth = 1) + # Line color
labs(title = "Employment of Migrants by Industry (2021 - 2022)",
x = "Percentage (%)") + # Removed y axis label
theme(axis.text.y = element_text(angle = 0, hjust = 0)) + # Adjust y-axis labels
theme_minimal() + # Clean theme for the plot
theme(
panel.grid.major = element_line(color = "white", linewidth = 0), # Very light gridlines (almost invisible)
panel.grid.minor = element_line(color = "white", linewidth = 0), # Even lighter minor gridlines
panel.background = element_rect(fill = "white"), # Ensure the background is clean white
axis.title.y = element_blank() # Remove the y-axis title
)
# Convert ggplot to plotly for interactivity
p5 <- ggplotly(ggplot_obj, tooltip = "text")
# Customize title font and layout for plotly
p5 <- p5 %>% layout(
title = list(
text = "<b>Jobs by Industry (2021 - 2022)</b>",
font = list(size = 18, family = "Arial", color = "#333333"),
x = 0, # Position title towards the left (x = 0)
xanchor = "left" # Title starts from the left
),
titlefont = list(
family = "Arial",
size = 18,
color = "#333333",
bold = TRUE # Make the title bold
)
)
# Display the interactive plot with hover effect
p5
```