For imports and data cleaning, I set the code to not be visible so that you don’t get bored right from the first lines.
Basic type conversions:
## 'data.frame': 97 obs. of 10 variables:
## $ dateOp : Date, format: "2024-03-28" "2024-03-27" ...
## $ dateVal : Date, format: "2024-03-28" "2024-03-27" ...
## $ label : chr "CARTE 27/03/24 NYX*FDADISTRIBUTI CB*8014" "CARTE 26/03/24 CARREFOUR CITY CB*8014" "CARTE 25/03/24 CARREFOUR CITY CB*8014" "CARTE 25/03/24 L ATELIER DE MON CB*8014" ...
## $ category : chr "Hébergement (hôtels, camping…)" "Alimentation" "Alimentation" "Contraventions" ...
## $ categoryParent: chr "Voyages & Transports" "Vie quotidienne" "Vie quotidienne" "Auto & Moto" ...
## $ amount : num 0.5 6.74 6.81 3.8 2.88 ...
## $ comment : logi NA NA NA NA NA NA ...
## $ accountNum : int 40356809 40356809 40356809 40356809 40356809 40356809 40356809 40356809 40356809 40356809 ...
## $ accountLabel : chr "Compte de Fonctionnement" "Compte de Fonctionnement" "Compte de Fonctionnement" "Compte de Fonctionnement" ...
## $ accountbalance: num 538 538 545 545 545 ...
## NULL
Creating a new variable for the budget category of each spending:
mapping <- c("Carburant"="leisure", "Club / association (sport, hobby, art…)"="leisure", "Livres, CD/DVD, bijoux, jouets…"="leisure", "Vêtements et accessoires"="leisure", "Bien-être et soins (coiffeur, parfums…)"="leisure", "Agences de voyages"="leisure", "Restaurants, bars, discothèques…"="leisure", "Equipements sportifs et artistiques"="leisure",
"Hébergement (hôtels, camping…)" = "needs", "Alimentation" = "needs", "
Contraventions" = "needs", "Transports quotidiens (métro, bus…)" = "needs", "Vie Quotidienne - Autres"= "needs", "Pharmacie et laboratoire"="needs", "Non catégorisé"="needs")
# the savings variable can not be created for now given that I don't save anything lol ; so my spendings either fall in the leisure or the needs category
data <- data %>%
mutate(budget_category = case_when(
category %in% names(mapping) ~ mapping[category],
TRUE ~ "other"
))
Filtering to exclude incoming money:
# A df of spendings only for further use
spendings <- data %>% filter(!categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations"))
# Basic descriptive stats
summary(spendings)
## dateOp dateVal label
## Min. :2024-03-01 Min. :2024-03-01 Length:93
## 1st Qu.:2024-03-08 1st Qu.:2024-03-08 Class :character
## Median :2024-03-14 Median :2024-03-14 Mode :character
## Mean :2024-03-15 Mean :2024-03-15
## 3rd Qu.:2024-03-22 3rd Qu.:2024-03-22
## Max. :2024-03-28 Max. :2024-03-28
## category categoryParent amount comment
## Length:93 Length:93 Min. : 0.500 Mode:logical
## Class :character Class :character 1st Qu.: 1.200 NA's:93
## Mode :character Mode :character Median : 5.000
## Mean : 7.901
## 3rd Qu.:10.500
## Max. :70.070
## accountNum accountLabel accountbalance budget_category
## Min. :40356809 Length:93 Min. : -11.19 Length:93
## 1st Qu.:40356809 Class :character 1st Qu.: 558.26 Class :character
## Median :40356809 Mode :character Median : 757.96 Mode :character
## Mean :40356809 Mean : 732.66
## 3rd Qu.:40356809 3rd Qu.: 927.06
## Max. :40356809 Max. :1064.67
all_spendings <- spendings %>%
arrange(dateOp) %>%
mutate(cumsum_amount = cumsum(amount))
ggplot(all_spendings, aes(x=dateOp)) +
geom_line(aes(y = cumsum_amount), size=1.2, color="pink") +
geom_line(aes(y=accountbalance), size=1.2, color="brown") +
labs(title="Monthly evolution of cumulative spendings VS account balance", x="Date", y="Amount") +
my_theme()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# For each parent category of spending
grouped_amount_data <- data %>%
filter(!categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations")) %>%
group_by(categoryParent) %>%
summarise(mean_amount=mean(amount), sum_amount=sum(amount))
# Plotting mean spending per parent category of spending, per month
mean_amount_plot <- ggplot(grouped_amount_data, aes(x=categoryParent, y=mean_amount)) +
geom_bar(stat="identity", aes(fill=categoryParent)) +
labs(title="Mean monthly spending per parent category", x="Parent category", y="Mean monthly spending") +
theme_minimal() +
theme(axis.text.x=element_text(angle=45, hjust=1)) +
my_theme()
# Plotting sum of spendings per parent category of spending, per month
sum_amount_plot <- ggplot(grouped_amount_data, aes(x=categoryParent, y=sum_amount), group=categoryParent, fill=categoryParent) +
geom_bar(stat="identity", aes(fill=categoryParent)) +
labs(title="Sum of monthly spendings per parent category", x="Parent category", y="Sum of monthly spendings") +
theme_minimal() +
theme(axis.text.x=element_text(angle=45, hjust=1)) +
my_theme()
sum_amount_plot
mean_amount_plot
# For each parent category of spending
grouped_amount_data_cat <- data %>%
filter(!categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations")) %>%
group_by(category) %>%
summarise(mean_amount=mean(amount), sum_amount=sum(amount))
# Plotting mean spending per parent category of spending, per month
mean_amount_plot_cat <- ggplot(grouped_amount_data_cat, aes(x=category, y=mean_amount)) +
geom_bar(stat="identity", aes(fill=category)) +
labs(title="Mean monthly spending per category", x="Category", y="Mean monthly spending") +
theme_minimal() +
theme(axis.text.x=element_text(angle=45, hjust=1)) +
my_theme()
# Plotting sum of spendings per parent category of spending, per month
sum_amount_plot_cat <- ggplot(grouped_amount_data_cat, aes(x=category, y=sum_amount)) +
geom_bar(stat="identity", aes(fill=category)) +
labs(title="Sum of monthly spendings per category", x="Category", y="Sum of monthly spendings") +
theme_minimal() +
theme(axis.text.x=element_text(angle=45, hjust=1)) +
my_theme()
mean_amount_plot_cat
sum_amount_plot_cat
# Data wrangling
grouped_amount_per_date <- data %>%
filter(!categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations")) %>%
group_by(categoryParent, dateOp) %>%
summarise(mean_amount=mean(amount), sum_amount=sum(amount)) %>%
replace_na(replace=list(dateOp=0L))
## `summarise()` has grouped output by 'categoryParent'. You can override using
## the `.groups` argument.
# Plots
mean_parent_spending_per_date_plot <- ggplot(grouped_amount_per_date, aes(x=dateOp, y=mean_amount, group=categoryParent, color=categoryParent)) +
geom_line() +
labs(title="Monthly evolution of spendings per parent category", x="Date", y="Mean spending") +
my_theme()
mean_parent_spending_per_date_plot
# Data wrangling
grouped_amount_per_date_cat <- data %>%
filter(!categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations")) %>%
group_by(category, dateOp) %>%
summarise(mean_amount=mean(amount), sum_amount=sum(amount)) %>%
replace_na(replace=list(dateOp=0L))
## `summarise()` has grouped output by 'category'. You can override using the
## `.groups` argument.
# Plots
mean_cat_spending_per_date_plot <- ggplot(grouped_amount_per_date_cat, aes(x=dateOp, y=mean_amount, group=category, color=category)) +
geom_line() +
labs(title="Monthly evolution of spendings per category", x="Date", y="Mean spending") +
my_theme()
mean_cat_spending_per_date_plot
mean_cat_spending_per_date_plot2 <- ggplot(spendings, aes(x=dateOp, y=amount, group=category, color=category)) +
geom_line() +
labs(title="Monthly evolution of spendings per category", x="Date", y="Mean spending") +
my_theme()
mean_cat_spending_per_date_plot
cumsum_spendings <- spendings %>%
group_by(category) %>%
arrange(dateOp) %>%
mutate(cumsum_amount = cumsum(amount), week = lubridate::week(dateOp))
cum_spendings_plot <- ggplot(cumsum_spendings, aes(x=dateOp, y=cumsum_amount, color=category)) +
geom_line() +
labs(title="Cumulative sum of spendings per date, per category", x="Date", y="Amount") +
my_theme()
cum_spendings_plot
Plotting my spendings according to the 50/30/20 budget rule categories:
# Data filtering
data_piechart <- spendings %>%
group_by(budget_category) %>%
mutate(sum_amount=sum(amount)) %>%
ungroup() %>%
mutate(perc=sum_amount/sum(amount)) %>%
mutate(labels=scales::percent(perc)) %>%
distinct(budget_category, perc, labels, .keep_all = TRUE)
# Plotting
library(RColorBrewer)
colors <- brewer.pal(n = 5, name = "Pastel1")
ggplot(data_piechart, aes(x = "", y = perc, group=budget_category, fill = budget_category)) +
geom_col() +
geom_text(aes(label = labels),
position = position_stack(vjust = 0.5)) +
coord_polar(theta="y") +
scale_fill_manual(values = setNames(colors, unique(data_piechart$budget_category))) +
my_theme()
Plotting the repartition of incoming money sources:
data_piechart_income <- data %>%
filter(categoryParent %in% c("Mouvements internes créditeurs", "Virements reçus", "Allocations")) %>%
group_by(categoryParent) %>%
mutate(sum_amount=sum(amount)) %>%
ungroup() %>%
mutate(perc=sum_amount/sum(amount)) %>%
mutate(labels=scales::percent(perc))
ggplot(data_piechart_income, aes(x = "", y = perc, group=label, fill = label)) +
geom_col() +
geom_text(aes(label = labels),
position = position_stack(vjust = 0.5)) +
coord_polar(theta="y") +
scale_fill_manual(values = setNames(colors, unique(data_piechart_income$label))) +
my_theme()