Code
source (here:: here ("_rinit.R" ))
invisible (Sys.setlocale ("LC_TIME" , "fr_FR.UTF-8" ))
# cd ~/iCloud/website/data/cnam; /usr/local/bin/R -e 'quarto::quarto_render("lpp_2016_2025.qmd")'
# (données : Rscript --vanilla cnam.R)
knitr:: opts_chunk$ set (echo = TRUE , message = FALSE , warning = FALSE ,
fig.width = 9 , fig.height = 5.5 , dpi = 150 )
library (dplyr); library (tidyr); library (ggplot2); library (stringr)
path <- here:: here ("data" , "cnam" , "lpp_2016_2025.parquet" )
d <- arrow:: read_parquet (path)
mdd <- scales:: label_number (scale = 1e-9 , suffix = " Md€" , accuracy = 0.1 , big.mark = " " , decimal.mark = "," )
mde <- scales:: label_number (scale = 1e-6 , suffix = " M€" , accuracy = 1 , big.mark = " " , decimal.mark = "," )
pct <- scales:: label_percent (accuracy = 0.1 , decimal.mark = "," )
nb <- scales:: label_number (big.mark = " " , decimal.mark = "," )
theme_cnam <- theme_minimal (base_size = 12 ) +
theme (plot.title = element_text (face = "bold" , size = 13 ), plot.title.position = "plot" ,
plot.subtitle = element_text (colour = "grey35" ),
panel.grid.minor = element_blank (), legend.position = "bottom" )
col1 <- "#1b7f79" ; col2 <- "#c0392b"
# barres horizontales triées
barh <- function (df, lab, val, fmt = mdd, fill = col1, ...) {
df |>
mutate (.l = forcats:: fct_reorder ({{ lab }}, {{ val }})) |>
ggplot (aes (.l, {{ val }})) +
geom_col (fill = fill, ...) +
geom_text (aes (label = fmt ({{ val }})), hjust = - 0.08 , size = 3 ) +
coord_flip () +
scale_y_continuous (labels = fmt, expand = expansion (mult = c (0 , 0.2 ))) +
labs (x = NULL , y = NULL ) + theme_cnam
}
Code
lpp <- d
nat <- lpp |> group_by (annee) |>
summarise (qte = sum (quantite, na.rm = TRUE ), remb = sum (montant_rembourse, na.rm = TRUE ),
base = sum (montant_remboursable, na.rm = TRUE ), .groups = "drop" )
Dépenses de l’Assurance maladie (tous régimes, France entière) pour les dispositifs médicaux de la LPP : pour chaque ligne de la nomenclature (code LPP), la quantité remboursée , le montant remboursable (base) et le montant remboursé , de 2016 à 2025 (en date de remboursement). Le champ est limité aux dispositifs médicaux codés (les appareils générateurs d’aérosol, orthoprothèses et orthèses non codés en sont exclus ; ils figurent dans l’onglet NAT_PREST — voir la page « lpp_agregats »). Le codage des dispositifs n’est pas stable d’une année à l’autre (décret 2019-571 sur l’obligation de code individuel), ce qui peut créer des ruptures de série. 35 736 lignes LPP, 15 chapitres (TS1), 182 sous-sections (TS3).
Dépense totale
Code
nat |> ggplot (aes (annee, remb)) +
geom_col (fill = col1) + geom_text (aes (label = mdd (remb)), vjust = - 0.4 , size = 3.3 ) +
scale_x_continuous (breaks = 2016 : 2025 ) + scale_y_continuous (labels = mdd, expand = expansion (mult = c (0 , .12 ))) +
labs (x = NULL , y = NULL , title = "Dispositifs médicaux : montant remboursé par an" ) + theme_cnam
Code
cagr <- (nat$ remb[nat$ annee == 2025 ] / nat$ remb[nat$ annee == 2016 ])^ (1 / 9 ) - 1
Le montant remboursé passe de 6,7 Md€ (2016) à 10,4 Md€ (2025), soit 5,0% par an en moyenne (54,7% sur la période).
Par chapitre de la nomenclature (TS1)
Code
lpp |> group_by (annee, ts1, libelle_ts1) |> summarise (remb = sum (montant_rembourse, na.rm = TRUE ), .groups = "drop" ) |>
mutate (l = paste0 (ts1, " — " , str_to_sentence (str_trunc (libelle_ts1, 40 )))) |>
ggplot (aes (annee, remb, fill = l)) + geom_area (colour = "white" , linewidth = 0.2 ) +
scale_x_continuous (breaks = 2016 : 2025 ) + scale_y_continuous (labels = mdd) +
labs (x = NULL , y = NULL , fill = NULL , title = "Montant remboursé par chapitre TS1" ) +
theme_cnam + guides (fill = guide_legend (ncol = 2 ))
Sous-sections qui tirent la croissance (TS3)
Code
lpp |> group_by (ts3, libelle_ts3, annee) |> summarise (remb = sum (montant_rembourse, na.rm = TRUE ), .groups = "drop" ) |>
filter (annee %in% c (2016 , 2025 )) |> pivot_wider (names_from = annee, values_from = remb, names_prefix = "a" ) |>
mutate (delta = a2025 - a2016) |> slice_max (delta, n = 15 ) |>
mutate (l = paste0 (ts3, " — " , str_to_sentence (str_trunc (libelle_ts3, 45 )))) |>
barh (l, delta, fill = col2) +
labs (title = "Sous-sections dont le remboursé a le plus augmenté, 2016 → 2025" )
Code
lpp |> filter (annee == 2025 ) |> group_by (ts3, libelle_ts3) |>
summarise (remb = sum (montant_rembourse, na.rm = TRUE ), qte = sum (quantite, na.rm = TRUE ),
base = sum (montant_remboursable, na.rm = TRUE ), .groups = "drop" ) |>
arrange (desc (remb)) |> slice_head (n = 25 ) |>
transmute (Code = ts3, Libellé = libelle_ts3, ` Remboursé 2025 ` = remb, Quantité = qte,
` Prix moyen remboursable ` = base / qte, ` Taux de remb. ` = remb / base) |>
gt:: gt () |>
gt:: fmt_number (c (` Remboursé 2025 ` , Quantité), decimals = 0 , sep_mark = " " ) |>
gt:: fmt_number (` Prix moyen remboursable ` , decimals = 2 ) |>
gt:: fmt_percent (` Taux de remb. ` , decimals = 1 ) |> gt:: tab_options (table.width = "100%" )
R20A
Pression positive continue pour apnée du sommeil, prestation seule
1 100 482 588
111 670 566
13.73
71.8%
H60B
Autocontrôle du glucose interstitiel, consommable dont capteurs et transmetteurs
583 063 926
14 132 818
42.32
97.5%
A10B
Nutriments pour supplémentation orale, adulte
405 457 787
48 652 452
9.67
86.2%
S40B
Audioprothèses, plus 20 ans
400 262 437
1 541 536
400.64
64.8%
D10A
Pansements hydrocellulaires
380 859 975
14 916 924
32.53
78.5%
T10A
Perfusion, diffuseurs portables et divers
332 849 777
3 811 667
103.12
84.7%
T30A
Lits médicaux, location
312 774 049
25 032 150
13.31
93.9%
G30B
Génito-urinaire, matériel pour sondage vésical
277 814 149
3 990 558
74.74
93.1%
R10A
Oxygénothérapie seule, long terme gazeux
272 953 163
4 825 742
61.15
92.5%
M20
Implants orthopédiques du genou
237 598 429
386 703
616.04
99.7%
R30B
Traitements respiratoires, prestations avec oxygène
233 526 217
3 446 365
73.20
92.6%
K20A
VPH Achat neuf
206 744 951
476 078
438.03
99.1%
H20B
Autotraitement du diabète, pompes externes sans tubulure
202 859 279
28 584 469
7.16
99.1%
H10E
Autocontrôle de la glycémie/corps cétoniques, bandelettes et autres
197 472 339
6 021 747
34.54
94.9%
O20A
Attelles (correction orthopédique)
185 265 139
5 139 740
55.64
64.8%
H50B
Boucle semi-fermée, capteurs, transmetteurs, algorithme
178 122 806
30 710 620
5.84
99.3%
R30A
Traitements respiratoires, autres prestations seules (ventilation)
173 600 929
3 433 363
56.46
89.6%
T20B
Perfusion, pompes externes, sauf insuline, consommables
170 370 162
1 591 582
109.75
97.5%
M30
Implants orthopédiques de la hanche
169 185 407
389 628
434.63
99.9%
A30A
Matériel de stomie digestive
142 096 463
5 797 405
25.55
95.9%
K20C
VPH Location courte durée (dont option d'achat)
138 486 550
10 272 015
15.31
88.0%
H20A
Autotraitement du diabète, pompes externes avec tubulure
133 852 023
18 841 072
7.16
99.3%
D20A
Bandes élastiques de contention
131 915 517
9 235 642
16.94
84.3%
H50C
Boucle semi-fermée, pompe à insuline
129 741 116
19 359 896
6.75
99.3%
K10
Dispositifs d'aide à la vie dont béquilles, déambulateurs
128 256 732
8 487 370
17.47
86.5%
Concentration : lignes les plus dépensières
Code
lpp |> filter (annee == 2025 ) |> group_by (code_lpp, libelle_lpp) |>
summarise (remb = sum (montant_rembourse, na.rm = TRUE ), .groups = "drop" ) |>
arrange (desc (remb)) |> mutate (cum = cumsum (remb) / sum (remb), rang = row_number ()) -> lig
top <- lig |> slice_head (n = 15 ) |> mutate (l = str_to_sentence (str_trunc (libelle_lpp, 60 )))
barh (top, l, remb, fill = col2) + labs (title = "Les 15 lignes LPP les plus remboursées en 2025" )
Les 100 premières lignes (sur 35 736) représentent 55,4% du remboursé 2025 ; les 1 000 premières 89,2% .
Source
Caisse nationale de l’Assurance Maladie (Cnam) — Cnam — LPP-AM (liste des produits et prestations remboursables), séries annuelles 2016-2025. Conversion Excel → Parquet : cnam.R (dossier data/cnam).