Structure of consumption expenditure by age of the reference person and COICOP consumption purpose

Data - Eurostat

Info

Last observation: Annual: 2020 (N = 6,838)

First observation: Annual: 1988 (N = 2,168)

Last data update: 11 aoû 2026, 22:24. Last compile: 12 aoû 2026, 00:07

Structure

coicop

France - Compare

2020, HBS

Code
hbs_str_t225 |>
  filter(time == "2020",
         geo == "FR") %>%
  
  select_if(~ n_distinct(.) > 1) |>
  spread(age, values) %>%
  select_if(~ n_distinct(.) > 1) |>
  print_table_conditional()

2015, HBS

All

Code
hbs_str_t225 |>
  filter(time == "2015",
         geo == "FR") %>%
  
  select_if(~ n_distinct(.) > 1) |>
  spread(age, values) %>%
  select_if(~ n_distinct(.) > 1) |>
  print_table_conditional()

2-digit

Code
hbs_str_t225 |>
  filter(time == "2015",
         geo == "FR",
         nchar(coicop) == 4) %>%
  
  select_if(~ n_distinct(.) > 1) |>
  spread(age, values) %>%
  select_if(~ n_distinct(.) > 1) |>
  print_table_conditional()

All quintiles

Sums

2-digit

Code
hbs_str_t225 |>
  filter(time == "2020",
         substr(coicop, 1, 2) == "CP",
         nchar(coicop) == 4) %>%
  
  select_if(~ n_distinct(.) > 1) |>
  group_by(age, geo, Geo) |>
  summarise(values = sum(values)) |>
  spread(age, values) |>
  print_table_conditional()

3-digit

Code
hbs_str_t225 |>
  filter(time == "2020",
         substr(coicop, 1, 2) == "CP",
         nchar(coicop) == 5) %>%
  
  select_if(~ n_distinct(.) > 1) |>
  group_by(age, geo, Geo) |>
  summarise(values = sum(values)) |>
  spread(age, values) |>
  print_table_conditional()
geo Geo UNK Y_GE60 Y_LT30 Y30-44 Y45-59
AT Austria NA 1000 1001 999 1001
BE Belgium NA 998 1002 995 1001
BG Bulgaria NA 1000 1000 998 999
CY Cyprus NA 994 1001 998 996
CZ Czechia NA 1000 1003 998 998
DE Germany NA 996 977 990 986
DK Denmark NA 995 998 1000 1002
EE Estonia NA 983 979 984 989
EL Greece NA 1001 1001 1001 1001
ES Spain NA 1000 1000 1002 999
FI Finland NA 990 973 973 979
FR France NA 986 991 989 983
HR Croatia NA 1000 NA 1000 1003
HU Hungary NA 997 999 999 1004
IE Ireland NA 1002 1002 1003 1000
IT Italy NA 1001 1000 1000 997
LT Lithuania NA 1000 999 1001 999
LU Luxembourg NA 999 998 1000 998
LV Latvia NA 998 1000 996 1000
ME Montenegro NA 985 NA 983 985
MT Malta NA 1002 1001 1001 1000
NL Netherlands NA 1002 1002 1002 998
NO Norway NA 998 981 995 996
PL Poland NA 998 1002 996 999
RS Serbia NA 998 999 1001 998
SI Slovenia NA 1000 1001 1000 1000
SK Slovakia NA 1001 999 998 998
TR Türkiye NA 1001 1001 1000 998

CP041, CP042, CP041_042

2015

France

Code
hbs_str_t225 |>
  filter(coicop %in% c("CP041", "CP042"),
         time == "2015",
         geo %in% c("FR")) |>
  spread(coicop, values) |>
  mutate(CP041_042 = CP041 + CP042) |>
  gather(coicop, values, CP041, CP042, CP041_042) |>
  
  
  left_join(colors, by = c("Geo" = "country")) |>
  mutate(Coicop = ifelse(coicop == "CP041_042", "Imputed rentals plus actual rentals", Coicop),
         age = ifelse(age == "Y_GE60", "Y60+", age),
         age = ifelse(age == "Y_LT30", "Y30-", age)) |>
  ggplot() + geom_line(aes(x = age, y = values/1000, color = Coicop, group = Coicop)) +
  theme_minimal() +
  xlab("") + ylab("Weight in CPI") +
  scale_y_continuous(breaks = 0.01*seq(-30, 50, 2),
                     labels = percent_format(accuracy = 1)) +
  theme(legend.position = c(0.2, 0.9),
        legend.title = element_blank())

France

Actual + Imputed

Code
hbs_str_t225 |>
  filter(coicop %in% c("CP041", "CP042"),
         time == "2015",
         geo %in% c("FR")) |>
  mutate(Coicop = factor(coicop, levels = c("CP042", "CP041"), labels = c("Loyers imputés (propriétaires)", "Loyers réels (locataires)")),
         age = ifelse(age == "Y_GE60", "Y60+", age),
         age = ifelse(age == "Y_LT30", "Y30-", age)) |>
  ggplot() + geom_col(aes(x = age, y = values/1000, fill = Coicop)) +
  theme_minimal() +
  xlab("") + ylab("Poids dans l'Indice des Prix") +
  scale_y_continuous(breaks = 0.01*seq(-30, 50, 5),
                     labels = percent_format(accuracy = 1)) +
  theme(legend.position = "top",
        legend.direction = "horizontal",
        legend.title = element_blank())

Tous

Code
deg_urb <- read_parquet("deg_urb_fr.parquet")
data <- hbs_str_t225 |>
  rename(category = age) |>
  mutate(type = "age") |>
  bind_rows(hbs_str_t223 |>
              rename(category = quantile) |>
              mutate(type = "quantile")) |>
  bind_rows(hbs_str_t226 |>
              rename(category = deg_urb) |>
              mutate(type = "deg_urb")) |>
  filter(coicop %in% c("CP041", "CP042"),
         time == "2020",
         geo == "FR") %>%
  select_if(~ n_distinct(.) > 1) %>%
  select(type, everything(.)) |>
  arrange(coicop)

data |>
  spread(coicop, values) |>
  mutate(CP041_042 = CP041 + CP042) |>
  print_table_conditional()
type category Age Coicop Quant_inc Deg_urb CP041 CP042 CP041_042
age Y_GE60 60 years or over Actual rentals for housing NA NA 44 NA NA
age Y_GE60 60 years or over Imputed rentals for housing NA NA NA 190 NA
age Y_LT30 Less than 30 years Actual rentals for housing NA NA 144 NA NA
age Y_LT30 Less than 30 years Imputed rentals for housing NA NA NA 56 NA
age Y30-44 From 30 to 44 years Actual rentals for housing NA NA 73 NA NA
age Y30-44 From 30 to 44 years Imputed rentals for housing NA NA NA 132 NA
age Y45-59 From 45 to 59 years Actual rentals for housing NA NA 55 NA NA
age Y45-59 From 45 to 59 years Imputed rentals for housing NA NA NA 149 NA
deg_urb DEG1 NA Actual rentals for housing NA Cities 85 NA NA
deg_urb DEG1 NA Imputed rentals for housing NA Cities NA 138 NA
deg_urb DEG2 NA Actual rentals for housing NA Towns and suburbs 62 NA NA
deg_urb DEG2 NA Imputed rentals for housing NA Towns and suburbs NA 148 NA
deg_urb DEG3 NA Actual rentals for housing NA Rural areas 33 NA NA
deg_urb DEG3 NA Imputed rentals for housing NA Rural areas NA 168 NA
quantile QU1 NA Actual rentals for housing First quintile NA 175 NA NA
quantile QU1 NA Imputed rentals for housing First quintile NA NA 69 NA
quantile QU2 NA Actual rentals for housing Second quintile NA 112 NA NA
quantile QU2 NA Imputed rentals for housing Second quintile NA NA 125 NA
quantile QU3 NA Actual rentals for housing Third quintile NA 71 NA NA
quantile QU3 NA Imputed rentals for housing Third quintile NA NA 154 NA
quantile QU4 NA Actual rentals for housing Fourth quintile NA 41 NA NA
quantile QU4 NA Imputed rentals for housing Fourth quintile NA NA 167 NA
quantile QU5 NA Actual rentals for housing Fifth quintile NA 25 NA NA
quantile QU5 NA Imputed rentals for housing Fifth quintile NA NA 169 NA

Graph

Code
data_1 <- data |>
  mutate(Coicop = factor(coicop, levels = c("CP042", "CP041"), labels = c("Loyers imputés (propriétaires occupants)", "Loyers réels (locataires)")),
         Category = factor(category, levels = c("Y_LT30", "Y30-44", "Y45-59", "Y_GE60",
                                                "DEG1", "DEG2", "DEG3",
                                                "QUINTILE1", "QUINTILE2", "QUINTILE3", "QUINTILE4", "QUINTILE5"),
                           labels = c("- de 30 ans", "De 30 à 44 ans", "De 45 à 59 ans", "+ de 60 ans",
                                      "Villes", "Villes - peuplées\net banlieues", "Zones rurales",
                                      "1er\n(+ pauvres)", "2è", "3è", "4è", "5è\n(+ riches)")),
         Type = factor(type, levels = c("age", "deg_urb", "quantile"),
                       labels = c("Âge", "Commune de résidence", "Cinquième de niveau de vie"))) |>
  arrange(Coicop) |>
  mutate(values = values/1000) |>
  select(type, Type, category, Category, coicop, Coicop, values)
write.csv(data_1, file = "~/Desktop/graphique5.csv")

data_1 |>
  ggplot() + geom_col(aes(x = Category, y = values, fill = Coicop)) +
  theme_minimal() +
  xlab("") + ylab("Poids budgétaire des loyers (%)") +
  scale_y_continuous(breaks = 0.01*seq(-30, 50, 2),
                     labels = percent_format(accuracy = 1)) +
  theme(legend.position = "bottom",
        legend.title = element_blank(),
        legend.margin=margin(t=-35),
        axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  scale_fill_manual(values = c("#005DA4", "#F59C00")) +
  facet_wrap(~ Type, scales = "free")