Code
library(tidyverse)
library(lubridate)
grafiques_dir <- "../output/grafiques"
dir.create(grafiques_dir, showWarnings = FALSE, recursive = TRUE)library(tidyverse)
library(lubridate)
grafiques_dir <- "../output/grafiques"
dir.create(grafiques_dir, showWarnings = FALSE, recursive = TRUE)Importem tots els fitxers CSV i els fusionem en un sol dataframe. També gestionem els valors “..” que representen recomptes de població petits (emmascarament per privadesa), tractant-los com a 2.
# Llista de tots els fitxers CSV
files <- list.files(path = "../data", pattern = "20.*_pad_mdbas_edat-1.csv", full.names = TRUE)
# Lectura i fusió
data_raw <- files %>%
map_df(function(f) {
read_csv(f, col_types = cols(.default = "c")) %>%
mutate(Source_File = f)
})
# Neteja de dades
data <- data_raw %>%
mutate(
# Convertim Valor a numèric, tractant ".." com a 2 (comú en els datasets de BCN)
Valor = as.numeric(ifelse(Valor == "..", "2", Valor)),
EDAT_1 = as.numeric(EDAT_1),
Year = year(as.Date(Data_Referencia)),
Nom_Districte = factor(Nom_Districte),
Codi_Districte = as.numeric(Codi_Districte)
) %>%
filter(!is.na(Valor))
# Població total per any i districte per a normalització
poblacio_total <- data %>%
group_by(Year, Codi_Districte, Nom_Districte) %>%
summarize(Poblacio_Total = sum(Valor), .groups = "drop")
# Resum de la població total per any
poblacio_total %>%
group_by(Year) %>%
summarize(Poblacio_Barcelona = sum(Poblacio_Total)) %>%
knitr::kable()| Year | Poblacio_Barcelona |
|---|---|
| 2015 | 1601223 |
| 2016 | 1606819 |
| 2017 | 1621571 |
| 2018 | 1625427 |
| 2019 | 1646810 |
| 2020 | 1662668 |
| 2021 | 1656181 |
| 2022 | 1635478 |
| 2023 | 1655903 |
| 2024 | 1698181 |
| 2025 | 1727268 |
pyramid_data <- data %>%
group_by(Year, Nom_Districte, EDAT_1) %>%
summarize(Total = sum(Valor), .groups = "drop")
selected_years <- c(2015, 2020, 2022, 2025)
p <- ggplot(pyramid_data %>% filter(Year %in% selected_years),
aes(x = EDAT_1, y = Total)) +
geom_bar(stat = "identity", fill = "steelblue", alpha = 0.8) +
facet_grid(Nom_Districte ~ Year, scales = "free_x") +
theme_minimal(base_size = 9) +
labs(title = "Distribució de la població per edat i districte",
x = "Edat",
y = "Nombre de persones",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(strip.text.y = element_text(angle = 0),
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "piramides_districtes.png"), p, width = 12, height = 15)trends_data <- data %>%
mutate(Grup_Edat = case_when(
EDAT_1 <= 12 ~ "12 anys o menys",
EDAT_1 >= 65 ~ "Majors de 65",
TRUE ~ "13-64"
)) %>%
group_by(Year, Nom_Districte, Grup_Edat) %>%
summarize(Count = sum(Valor), .groups = "drop") %>%
group_by(Year, Nom_Districte) %>%
mutate(Percentatge = (Count / sum(Count)) * 100) %>%
filter(Grup_Edat %in% c("12 anys o menys", "Majors de 65"))
p <- ggplot(trends_data, aes(x = Year, y = Percentatge, color = Grup_Edat)) +
geom_line(size = 1) +
geom_point() +
facet_wrap(~Nom_Districte, ncol = 2) +
scale_x_continuous(breaks = seq(2015, 2025, 2)) +
theme_minimal() +
labs(title = "Percentatge de població de 12 anys o menys i major de 65 per districte",
x = "Any",
y = "Percentatge (%)",
color = "Grup d'edat",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "tendencies_demografiques.png"), p, width = 10, height = 10)En aquesta secció comparem el nombre d’animals de companyia i d’infants de 5 anys o menys per cada 1000 habitants.
pet_files <- list.files(path = "../data/animals2", pattern = "*.csv", full.names = TRUE)
pets_raw <- pet_files %>%
map_df(function(f) {
any_fitxer <- as.numeric(str_extract(basename(f), "^[0-9]{4}"))
df <- read_csv(f, col_types = cols(.default = "c")) %>% mutate(Year = any_fitxer)
if ("DISTRICTE" %in% names(df)) df <- rename(df, Nom_Districte = DISTRICTE)
if ("NOM_DISTRICTE" %in% names(df)) df <- rename(df, Nom_Districte = NOM_DISTRICTE)
if ("NUM_ANIMALS" %in% names(df)) df <- rename(df, Num_Animals = NUM_ANIMALS)
if ("NUM_ANIMAL" %in% names(df)) df <- rename(df, Num_Animals = NUM_ANIMAL)
df %>% select(Year, Codi_Districte = CODI_DISTRICTE, Num_Animals) %>% mutate(Num_Animals = as.numeric(Num_Animals))
})
pets_yearly <- pets_raw %>%
group_by(Year, Codi_Districte) %>%
summarize(Animals_Companyia = mean(Num_Animals, na.rm = TRUE), .groups = "drop") %>%
mutate(Codi_Districte = as.numeric(Codi_Districte))
kids_yearly <- data %>%
filter(EDAT_1 <= 5) %>%
group_by(Year, Codi_Districte) %>%
summarize(Infants_5 = sum(Valor), .groups = "drop")
comparison_data <- poblacio_total %>%
left_join(kids_yearly, by = c("Year", "Codi_Districte")) %>%
left_join(pets_yearly, by = c("Year", "Codi_Districte")) %>%
filter(Year >= 2018) %>%
mutate(
Infants_per_1000 = (Infants_5 / Poblacio_Total) * 1000,
Animals_per_1000 = (Animals_Companyia / Poblacio_Total) * 1000
) %>%
pivot_longer(cols = c(Infants_per_1000, Animals_per_1000),
names_to = "Categoria",
values_to = "Ràtio") %>%
mutate(Categoria = recode(Categoria,
"Infants_per_1000" = "Infants (≤5 anys)",
"Animals_per_1000" = "Animals de companyia"))comparison_city <- comparison_data %>%
group_by(Year, Categoria) %>%
summarize(Ràtio = sum(Ràtio * Poblacio_Total) / sum(Poblacio_Total), .groups = "drop")
p <- ggplot(comparison_city, aes(x = Year, y = Ràtio, color = Categoria)) +
geom_line(size = 1.2) +
geom_point(size = 3) +
scale_x_continuous(breaks = seq(2018, 2025, 1)) +
theme_minimal() +
labs(title = "Evolució Animals de companyia vs. Infants a Barcelona (Per 1000 hab.)",
x = "Any",
y = "Nombre per cada 1000 habitants",
color = "Categoria",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "animals_infants_ciutat.png"), p, width = 10, height = 6)p <- ggplot(comparison_data, aes(x = Year, y = Ràtio, color = Categoria)) +
geom_line() +
geom_point(size = 1) +
facet_wrap(~Nom_Districte, scales = "free_y", ncol = 2) +
scale_x_continuous(breaks = seq(2018, 2025, 2)) +
theme_minimal() +
labs(title = "Animals de companyia vs. Infants per districte (Per 1000 hab.)",
x = "Any",
y = "Nombre per cada 1000 habitants",
color = "Categoria",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "animals_infants_districtes.png"), p, width = 10, height = 12)edats_clau_districtes <- data %>%
filter(EDAT_1 %in% c(3, 12)) %>%
group_by(Year, Nom_Districte, EDAT_1) %>%
summarize(Total = sum(Valor), .groups = "drop") %>%
mutate(Edat = factor(paste(EDAT_1, "anys")))
p <- ggplot(edats_clau_districtes, aes(x = Year, y = Total, color = Edat, group = Edat)) +
geom_line(size = 1) +
geom_point(size = 2) +
facet_wrap(~Nom_Districte, ncol = 2, scales = "free_y") +
scale_x_continuous(breaks = seq(2015, 2025, 2)) +
theme_minimal() +
labs(title = "Evolució de la població de 3 i 12 anys per districte",
x = "Any",
y = "Nombre d'habitants",
color = "Edat",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "edats_clau_districtes.png"), p, width = 12, height = 14)edats_clau_ciutat <- data %>%
filter(EDAT_1 %in% c(3, 12)) %>%
group_by(Year, EDAT_1) %>%
summarize(Total = sum(Valor), .groups = "drop") %>%
mutate(Edat = factor(paste(EDAT_1, "anys")))
p <- ggplot(edats_clau_ciutat, aes(x = Year, y = Total, color = Edat, group = Edat)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_text(aes(label = Total), vjust = -1, size = 3, show.legend = FALSE) +
scale_x_continuous(breaks = seq(2015, 2025, 1)) +
theme_minimal() +
labs(title = "Evolució de la població de 3 i 12 anys a Barcelona",
x = "Any",
y = "Nombre d'habitants",
color = "Edat",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "edats_clau_ciutat.png"), p, width = 10, height = 5)Analitzem la relació entre la renda disponible de les llars per persona (2022, agregada per barri com a mitjana de les seccions censals) i la proporció d’infants de 12 anys o menys i de 5 anys o menys sobre la població total del barri (2025). Cada punt representa un barri, i el color indica el districte.
income_raw <- read_csv("../data/2022_renda_disponible_llars_per_persona.csv",
col_types = cols(.default = "c")) %>%
mutate(Import_Euros = as.numeric(Import_Euros),
Codi_Barri = as.numeric(Codi_Barri))
income_barri <- income_raw %>%
group_by(Codi_Barri, Nom_Barri, Codi_Districte, Nom_Districte) %>%
summarize(Renda_Mitjana = mean(Import_Euros, na.rm = TRUE), .groups = "drop") %>%
mutate(Codi_Districte = as.numeric(Codi_Districte))
pop_barri_2025 <- read_csv("../data/2025_pad_mdbas_edat-1.csv",
col_types = cols(.default = "c")) %>%
mutate(Valor = as.numeric(ifelse(Valor == "..", "2", Valor)),
EDAT_1 = as.numeric(EDAT_1),
Codi_Barri = as.numeric(Codi_Barri)) %>%
filter(!is.na(Valor)) %>%
group_by(Codi_Barri, Nom_Barri, Codi_Districte, Nom_Districte) %>%
summarize(
Poblacio_Total = sum(Valor),
Infants_12 = sum(Valor[EDAT_1 <= 12]),
Infants_5 = sum(Valor[EDAT_1 <= 5]),
.groups = "drop"
) %>%
mutate(
Prop_Infants_12 = Infants_12 / Poblacio_Total * 100,
Prop_Infants_5 = Infants_5 / Poblacio_Total * 100,
Codi_Districte = as.numeric(Codi_Districte)
)
renda_infants <- income_barri %>%
inner_join(pop_barri_2025, by = c("Codi_Barri", "Codi_Districte")) %>%
select(Codi_Barri, Nom_Barri = Nom_Barri.x, Nom_Districte = Nom_Districte.x,
Renda_Mitjana, Prop_Infants_12, Prop_Infants_5) %>%
pivot_longer(cols = c(Prop_Infants_12, Prop_Infants_5),
names_to = "Grup",
values_to = "Proporcio") %>%
mutate(Grup = recode(Grup,
"Prop_Infants_12" = "Infants ≤12 anys",
"Prop_Infants_5" = "Infants ≤5 anys"))p <- ggplot(renda_infants, aes(x = Renda_Mitjana, y = Proporcio, color = Nom_Districte)) +
geom_point(alpha = 0.7, size = 2) +
geom_smooth(method = "lm", formula = y ~ poly(x, 2), se = TRUE, color = "grey30", linewidth = 0.8) +
facet_wrap(~Grup, scales = "free_y") +
scale_x_continuous(labels = scales::comma) +
theme_minimal() +
labs(title = "Renda de les llars i proporció d'infants per barri (Barcelona)",
subtitle = "Renda: 2022 (mitjana per seccions censals) · Població: 2025",
x = "Renda disponible mitjana per persona (€)",
y = "Proporció sobre la població del barri (%)",
color = "Districte",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
legend.text = element_text(size = 7),
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "renda_infants_barri.png"), p, width = 12, height = 8)Les dades classifiquen les llars per tipologia de convivència, no pel nombre exacte de fills. Usem la classificació documentada (codis 1–12) agrupada en quatre categories: llars sense cap menor de 18 anys, llars monoparentals amb menors, llars biparentals amb menors, i altres llars amb menors. Els codis addicionals (>12) no estan documentats i representen un volum marginal, per la qual cosa s’exclouen.
dom_raw <- read_csv("../data/2025_pad_dom_mdbas_tipus-domicili.csv",
col_types = cols(.default = "c")) %>%
mutate(Valor = as.numeric(Valor),
TIPUS_DOMICILI = as.integer(TIPUS_DOMICILI),
Codi_Barri = as.numeric(Codi_Barri),
Codi_Districte = as.numeric(Codi_Districte)) %>%
filter(!is.na(Valor), TIPUS_DOMICILI %in% 1:12) %>%
mutate(Grup_Llar = case_when(
TIPUS_DOMICILI %in% 1:8 ~ "Sense menors",
TIPUS_DOMICILI %in% 9:10 ~ "Monoparental amb menors",
TIPUS_DOMICILI == 11 ~ "Biparental amb menors",
TIPUS_DOMICILI == 12 ~ "Altres amb menors"
))
llars_barri <- dom_raw %>%
group_by(Codi_Barri, Nom_Barri, Codi_Districte, Nom_Districte, Grup_Llar) %>%
summarize(Llars = sum(Valor), .groups = "drop") %>%
group_by(Codi_Barri) %>%
mutate(Total_Llars = sum(Llars),
Proporcio = Llars / Total_Llars * 100) %>%
ungroup() %>%
mutate(Grup_Llar = factor(Grup_Llar, levels = c(
"Sense menors", "Monoparental amb menors",
"Biparental amb menors", "Altres amb menors")))barri_order <- llars_barri %>%
filter(Grup_Llar == "Sense menors") %>%
arrange(Proporcio) %>%
pull(Nom_Barri)
p <- llars_barri %>%
mutate(Nom_Barri = factor(Nom_Barri, levels = barri_order)) %>%
ggplot(aes(x = Proporcio, y = Nom_Barri, fill = Grup_Llar)) +
geom_col(alpha = 0.9) +
scale_fill_brewer(palette = "Set2") +
theme_minimal(base_size = 9) +
labs(title = "Composició de les llars per barri (Barcelona, 2025)",
x = "% sobre el total de llars del barri",
y = NULL,
fill = "Tipologia",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
legend.text = element_text(size = 8),
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "llars_tipus_barri.png"), p, width = 10, height = 18)llars_renda <- llars_barri %>%
inner_join(income_barri %>% select(Codi_Barri, Renda_Mitjana),
by = "Codi_Barri")
p <- ggplot(llars_renda, aes(x = Renda_Mitjana, y = Proporcio, color = Nom_Districte)) +
geom_point(alpha = 0.7, size = 2) +
geom_smooth(method = "lm", formula = y ~ poly(x, 2), se = TRUE,
color = "grey30", linewidth = 0.8) +
facet_wrap(~Grup_Llar, scales = "free_y", ncol = 2) +
scale_x_continuous(labels = scales::comma) +
theme_minimal() +
labs(title = "Renda de les llars i tipologia de llar per barri (Barcelona)",
subtitle = "Renda: 2022 · Llars: 2025",
x = "Renda disponible mitjana per persona (€)",
y = "% sobre el total de llars del barri",
color = "Districte",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
legend.text = element_text(size = 7),
strip.text = element_text(face = "bold"),
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "llars_renda_barri.png"), p, width = 12, height = 9)gracia_data <- data %>% filter(Nom_Districte == "Gràcia")
anys_interes <- c(2015, 2018, 2021, 2025)
p <- ggplot(gracia_data %>% filter(Year %in% anys_interes),
aes(x = EDAT_1, y = Valor)) +
geom_bar(stat = "identity", fill = "darkorange", alpha = 0.7) +
coord_flip() +
facet_wrap(~Year, ncol = 2) +
theme_minimal() +
labs(title = "Piràmides d'edat al districte de Gràcia",
x = "Edat",
y = "Població",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "piramides_gracia.png"), p, width = 12, height = 10)gracia_clau <- gracia_data %>%
filter(EDAT_1 %in% c(3, 12)) %>%
group_by(Year, EDAT_1) %>%
summarize(Total = sum(Valor), .groups = "drop") %>%
mutate(Edat = factor(paste(EDAT_1, "anys")))
p <- ggplot(gracia_clau, aes(x = Year, y = Total, color = Edat, group = Edat)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_text(aes(label = Total), vjust = -1, size = 3, show.legend = FALSE) +
scale_x_continuous(breaks = seq(2015, 2025, 1)) +
theme_minimal() +
labs(title = "Evolució de la població de 3 i 12 anys a Gràcia",
x = "Any",
y = "Nombre d'infants",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "edats_clau_gracia.png"), p, width = 10, height = 6)kids5_gracia <- gracia_data %>%
filter(EDAT_1 <= 5) %>%
group_by(Year) %>%
summarize(Infants_5 = sum(Valor), .groups = "drop")
poblacio_gracia <- poblacio_total %>% filter(Nom_Districte == "Gràcia")
gracia_comp <- poblacio_gracia %>%
left_join(kids5_gracia, by = "Year") %>%
left_join(pets_yearly %>% filter(Codi_Districte == 6), by = "Year") %>%
filter(Year >= 2018) %>%
mutate(
Infants_per_1000 = (Infants_5 / Poblacio_Total) * 1000,
Animals_per_1000 = (Animals_Companyia / Poblacio_Total) * 1000
) %>%
pivot_longer(cols = c(Infants_per_1000, Animals_per_1000), names_to = "Categoria", values_to = "Ràtio") %>%
mutate(Categoria = recode(Categoria,
"Infants_per_1000" = "Infants (≤5 anys)",
"Animals_per_1000" = "Animals de companyia"))
p <- ggplot(gracia_comp, aes(x = Year, y = Ràtio, color = Categoria)) +
geom_line(size = 1.2) +
geom_point() +
scale_x_continuous(breaks = seq(2018, 2025, 1)) +
theme_minimal() +
labs(title = "Gràcia: Animals de companyia vs. Infants (≤5 anys) per 1000 hab.",
x = "Any",
y = "Ràtio per 1000 habitants",
color = "Categoria",
caption = "Font: https://opendata-ajuntament.barcelona.cat") +
theme(legend.position = "bottom",
plot.caption = element_text(size = 7, color = "grey50"))
print(p)ggsave(file.path(grafiques_dir, "animals_infants_gracia.png"), p, width = 10, height = 6)