{"id":111,"date":"2024-08-01T17:56:37","date_gmt":"2024-08-01T15:56:37","guid":{"rendered":"https:\/\/huguesg.fr\/site\/?page_id=111"},"modified":"2025-10-19T19:48:25","modified_gmt":"2025-10-19T17:48:25","slug":"budget-national-transports","status":"publish","type":"page","link":"https:\/\/huguesg.fr\/site\/index.php\/budget-national-transports\/","title":{"rendered":"Le budget national des transports"},"content":{"rendered":"\n<p>Le budget des transports est un sujet central dans les finances publiques fran\u00e7aises, englobant une vari\u00e9t\u00e9 de projets allant de la mobilit\u00e9 quotidienne \u00e0 la modernisation des infrastructures. Dans cet article, nous allons explorer en d\u00e9tail l&#8217;\u00e9volution du budget national des transports au fil des ann\u00e9es. Nous aborderons les pr\u00e9visions et les r\u00e9alisations, la composition du budget par cat\u00e9gorie, ainsi que la r\u00e9partition de ces ressources par mode de transport. Pour compl\u00e9ter l&#8217;analyse, nous pr\u00e9senterons \u00e9galement des tableaux r\u00e9capitulatifs d\u00e9taillant les montants et la nature des lignes budg\u00e9taires.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. \u00c9volution du budget national des transports : pr\u00e9visions et r\u00e9alisations<\/h2>\n\n\n\n<p>Le premier graphique que nous analysons montre l&#8217;\u00e9volution dans le temps du total des budgets des transports, avec une distinction claire entre les pr\u00e9visions et les r\u00e9alisations. Ce graphique met en lumi\u00e8re les \u00e9carts potentiels entre ce qui est pr\u00e9vu au d\u00e9but de chaque ann\u00e9e et ce qui est r\u00e9ellement d\u00e9pens\u00e9.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Observation des tendances<\/strong> : On remarque une tendance \u00e0 la hausse, avec des \u00e9carts parfois significatifs entre les pr\u00e9visions budg\u00e9taires et les r\u00e9alisations, particuli\u00e8rement pour les ann\u00e9es 2021 et 2022. Cela peut refl\u00e9ter des ajustements en cours d&#8217;ann\u00e9e en fonction des besoins r\u00e9els, des projets suppl\u00e9mentaires, ou des r\u00e9allocations budg\u00e9taires.<\/li>\n<\/ul>\n\n\n\n<div id=\"chart_div-depenses-total\"><\/div>\n\n<script type=\"text\/javascript\" src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n<script type=\"text\/javascript\">\n  google.charts.load('current', {packages: ['corechart', 'bar']});\n  google.charts.setOnLoadCallback(drawChart);\n\n  function drawChart() {\n    fetch('https:\/\/huguesg.fr\/docs\/depenses-categories.csv')\n      .then(response => response.text())\n      .then(data => {\n        const rows = data.split('\\n').map(row => row.split(';'));\n        const headers = rows[0].slice(2); \/\/ Exclude the first column header\n        const totalRelance = rows[rows.length - 3].slice(2).map(parseFloat); \/\/ Second last row\n        const totalHorsRelance = rows[rows.length - 2].slice(2).map(parseFloat); \/\/ Last row\n\n        const dataTable = new google.visualization.DataTable();\n        dataTable.addColumn('string', 'Ann\u00e9e');\n      dataTable.addColumn('number', 'Total Hors Relance');\n      dataTable.addColumn({type: 'string', role: 'style'});  \/\/ Style column for Total Hors Relance\n      dataTable.addColumn('number', 'Total Relance');\n      dataTable.addColumn({type: 'string', role: 'style'});  \/\/ Style column for Total Relance\n\n      for (let i = 0; i < headers.length; i++) {\n        const relanceColor = headers[i].includes('Pr\u00e9vision') ? 'color: #FFCCCC' : 'color: red';\n        const horsRelanceColor = headers[i].includes('Pr\u00e9vision') ? 'color: lightblue' : 'color: blue';\n        dataTable.addRow([headers[i], totalHorsRelance[i], horsRelanceColor, totalRelance[i], relanceColor]);\n      }\n\n      const options = {\n        chart: {\n          title: 'Budget des Transports',\n          subtitle: 'Pr\u00e9visions et R\u00e9alisations',\n        },\n        bars: 'vertical',\n        isStacked: true,\n      };\n\n        const chart = new google.visualization.ColumnChart(document.getElementById('chart_div-depenses-total'));\n        chart.draw(dataTable, options);\n      })\n      .catch(error => console.error('Error fetching CSV data:', error));\n  }\n<\/script>\n\n\n\n<h2 class=\"wp-block-heading\">2. \u00c9volution des diff\u00e9rentes cat\u00e9gories du budget des transports<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">2.1) Toutes cat\u00e9gories<\/h3>\n\n\n\n<p>Le second graphique montre l&#8217;\u00e9volution des diff\u00e9rentes cat\u00e9gories budg\u00e9taires sur plusieurs ann\u00e9es. Chaque barre repr\u00e9sente un montant allou\u00e9 \u00e0 une cat\u00e9gorie sp\u00e9cifique, et l&#8217;\u00e9volution de ces montants au fil du temps nous permet de mieux comprendre les priorit\u00e9s budg\u00e9taires de l&#8217;\u00c9tat dans le domaine des transports.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u00c9l\u00e9ments notables<\/strong> : On observe une forte croissance des montants allou\u00e9s \u00e0 des cat\u00e9gories telles que le financement de l&#8217;AFITF, les taxes affect\u00e9es aux Voies Navigables de France (VNF), et l&#8217;acquisition de v\u00e9hicules propres. <\/li>\n<\/ul>\n\n\n\n<div id=\"chart_div-depenses-categories\" style=\"height: 600px;\"><\/div>\n\n<script type=\"text\/javascript\" src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n<script type=\"text\/javascript\">\n  google.charts.load('current', {packages: ['corechart', 'bar']});\n  google.charts.setOnLoadCallback(drawChart);\n\n  function drawChart() {\n    fetch('https:\/\/huguesg.fr\/docs\/depenses-categories.csv')\n      .then(response => response.text())\n      .then(data => {\n        const rows = data.split('\\n').map(row => row.split(';'));\n        const headers = rows[0]; \/\/ Include the first column header\n        const dataTable = new google.visualization.DataTable();\n        dataTable.addColumn('string', 'Category');\n        \n        headers.slice(1).forEach(header => {\n          dataTable.addColumn('number', header);\n          dataTable.addColumn({type: 'string', role: 'style'});\n        });\n        rows.slice(1,-3).forEach(row => {\n          const rowData = [row[1]];\n          row.slice(1).forEach((cell, index) => {\n            const color = headers[index + 1].includes('Pr\u00e9vision') ? 'lightblue' : 'blue';\n            rowData.push(parseFloat(cell));\n            rowData.push(`color: ${color}`);\n          });\n          dataTable.addRow(rowData);\n        });\n\n        const options = {\n          title: 'Budget des Transports',\n          subtitle: 'Pr\u00e9visions et R\u00e9alisations',\n          isStacked: false,\n          bars: 'vertical',\n          legend: { position: 'none' }, \/\/ Remove legend\n          hAxis: {\n            title: 'Cat\u00e9gories'\n          },\n          vAxis: {\n            title: 'Montant (M\u20ac)',\n            minValue: 0\n          }\n        };\n\n        const chart = new google.visualization.ColumnChart(document.getElementById('chart_div-depenses-categories'));\n        chart.draw(dataTable, options);\n      })\n      .catch(error => console.error('Error fetching CSV data:', error));\n  }\n<\/script>\n\n\n\n<script src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n  <style>\n    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 24px; }\n    #toolbar { display:flex; gap:16px; align-items:center; margin-bottom:16px; flex-wrap:wrap; }\n    #charts { display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap:14px; }\n    .card { border:1px solid #e5e7eb; border-radius:10px; padding:10px 12px; }\n    .title { font-size:13px; line-height:1.3; margin-bottom:4px; color:#111827; white-space:normal; }\n    .chart { width:100%; height:80px; }\n    .muted { color:#6b7280; font-size:12px; }\n  <\/style>\n\n  <div id=\"toolbar\">\n    <strong>Affichage :<\/strong>\n    <label><input type=\"radio\" name=\"mode\" value=\"raw\" checked> Valeurs brutes<\/label>\n    <label><input type=\"radio\" name=\"mode\" value=\"index\"> Base 100 (2020)<\/label>\n<label><input type=\"radio\" name=\"mode\" value=\"infl\"> Corrig\u00e9 de l&#8217;inflation<\/label>\n\n    <span class=\"muted\">Astuce : passez la souris pour voir la valeur exacte.<\/span>\n  <\/div>\n  <div id=\"charts\" aria-live=\"polite\"><\/div>\n\n  <script>\n    const CSV_URL = 'https:\/\/huguesg.fr\/docs\/depenses-categories.csv';\n\n    \/\/ Charge Google Charts (package \"corechart\" pour LineChart).\n    google.charts.load('current', { packages: ['corechart'] });\n    google.charts.setOnLoadCallback(init);\n\nconst CSV_URL_INFLATION = 'https:\/\/huguesg.fr\/docs\/inflation.csv';\nlet inflationCumMap = new Map(); \/\/ ann\u00e9e -> facteur cumulatif (base 1 en 2020)\n\nasync function loadInflation() {\n  const txt = await fetch(CSV_URL_INFLATION, { cache: 'no-store' }).then(r=>r.text());\n  const lines = txt.trim().split(\/\\r?\\n\/).slice(1); \/\/ saute l\u2019ent\u00eate\n\n  const rates = new Map();\n  lines.forEach(l => {\n    const [year, val] = l.split(\/[,;\\t]\/).map(x=>x.trim());\n    const y = parseInt(year,10);\n    const v = parseFloat(val.replace(',','.'));\n    if (y && !isNaN(v)) rates.set(y, v);\n  });\n\n  inflationCumMap.set(2020, 1);\n  const years = [...rates.keys()].sort((a,b)=>a-b);\n  for (let y = 2021; y <= Math.max(...years); y++) {\n    const prevFactor = inflationCumMap.get(y-1) ?? 1;\n    const rate = rates.get(y) ?? 0;\n    inflationCumMap.set(y, prevFactor * (1 + rate\/100));\n  }\n}\n\n\n    async function init() {\n      try {\n        const csvText = await fetch(CSV_URL, { cache: 'no-store' }).then(r => {\n          if (!r.ok) throw new Error('\u00c9chec de chargement du CSV (' + r.status + ')');\n          return r.text();\n        });\n        const parsed = parseCSVSmart(csvText);\n        const dataset = normalizeData(parsed);\nawait loadInflation();\n\n        \/\/ Construit l\u2019UI\n        buildCards(dataset);\n        \/\/ Premier rendu (valeurs brutes)\n        drawAll(dataset, 'raw');\n\n        \/\/ Gestion du s\u00e9lecteur\n        document.querySelectorAll('input[name=\"mode\"]').forEach(r => {\n          r.addEventListener('change', (e) => drawAll(dataset, e.target.value));\n        });\n      } catch (err) {\n        console.error(err);\n        document.getElementById('charts').innerHTML =\n          '<div class=\"card\">Impossible de charger le CSV : ' + (err.message || err) + '<\/div>';\n      }\n    }\n\n    \/\/ D\u00e9tection \"intelligente\" du s\u00e9parateur et parsing simple (CSV mono-ligne par cellule ; pas de guillemets imbriqu\u00e9s)\n    function parseCSVSmart(text) {\n      \/\/ Normalise les fins de ligne\n      const lines = text.replace(\/\\r\\n?\/g, '\\n').trim().split('\\n').filter(Boolean);\n\n      \/\/ D\u00e9tecte le s\u00e9parateur le plus probable parmi ; , \\t\n      const candidates = [';', '\\t', ','];\n      const score = (sep) => lines.slice(0, Math.min(lines.length, 5)).reduce((acc, l) => acc + (l.split(sep).length), 0);\n      candidates.sort((a,b) => score(b) - score(a));\n      const sep = candidates[0];\n\n      const rows = lines.map(l => l.split(sep).map(cell => cell.trim()));\n      return { rows, sep };\n    }\n\n    \/\/ Convertit en structure exploitable : headers + [{label, values: [{xLabel, value}], base2020}]\n    function normalizeData(parsed) {\n      const [headers, ...dataRows] = parsed.rows;\n\n      \/\/ On suppose : col0 = libell\u00e9 ; colonnes suivantes = ann\u00e9es + types (ex: \"2020 Pr\u00e9vision\", ...)\n      const valueHeaders = headers.slice(2);\n\n      \/\/ Indice de la colonne \u201c2020 R\u00e9alisation\u201d si existante ; sinon premi\u00e8re colonne contenant \"2020\"\n      let baseColIndex = valueHeaders.findIndex(h => \/2020\\s*R[\u00e9e]al\/i.test(h));\n      if (baseColIndex === -1) baseColIndex = valueHeaders.findIndex(h => \/2020\/.test(h));\n      \/\/ Fallback ultime\n      if (baseColIndex === -1) baseColIndex = 0;\n\n      const categories = [];\n\n      for (const row of dataRows) {\n        const label = (row[0] || '') + ' \u2014 ' + (row[1] || '');\n        if (!row[0] && !row[1]) continue;\n\n        \/\/ Convertit chaque cellule num\u00e9rique (format FR avec virgule) en Number\n        const nums = row.slice(2).map(v => toNumberFR(v));\n\n        \/\/ Ignore les lignes totalement vides\n        if (nums.every(v => v === null)) continue;\n\n        const series = valueHeaders.map((h, i) => ({\n          xLabel: h,\n          value: isFinite(nums[i]) ? nums[i] : null\n        }));\n\n        const base2020 = isFinite(nums[baseColIndex]) ? nums[baseColIndex] : null;\n\n        categories.push({ label, series, base2020 });\n      }\n\n      return { categories };\n    }\n\n    \/\/ Conversion nombre FR -> JS Number (retourne null si vide \/ non num\u00e9rique)\n    function toNumberFR(s) {\n      if (s == null || s === '') return null;\n      \/\/ autorise le s\u00e9parateur de milliers espace fine ou espace, mais pas pr\u00e9sent ici a priori\n      const cleaned = s.replace(\/\\s?(?=(?:\\d{3})+(?!\\d))\/g, '');\n      \/\/ virgule d\u00e9cimale -> point\n      const normalized = cleaned.replace(',', '.');\n      const n = Number(normalized);\n      return isNaN(n) ? null : n;\n    }\n\n    function buildCards(dataset) {\n      const container = document.getElementById('charts');\n      container.innerHTML = '';\n      dataset.categories.forEach((cat, idx) => {\n        const card = document.createElement('div');\n        card.className = 'card';\n        const title = document.createElement('div');\n        title.className = 'title';\n        title.textContent = cat.label;\n        const chartDiv = document.createElement('div');\n        chartDiv.className = 'chart';\n        chartDiv.id = 'chart-' + idx;\n        card.appendChild(title);\n        card.appendChild(chartDiv);\n        container.appendChild(card);\n      });\n    }\n\n    function drawAll(dataset, mode) {\n      dataset.categories.forEach((cat, idx) => drawSparkline(cat, document.getElementById('chart-' + idx), mode));\n    }\n\nfunction drawSparkline(category, el, mode) {\n  \/\/ DataTable : P\u00e9riode | Valeur | Style (pour styliser des points individuellement)\n  const data = new google.visualization.DataTable();\n  data.addColumn('string', 'P\u00e9riode');\n  data.addColumn('number', category.label);\n  data.addColumn({ type: 'string', role: 'style' }); \/\/ <-- style par point\n\n  const isIndex = (mode === 'index');\nconst isInfl  = (mode === 'infl');\nconst base = (isIndex ? (category.base2020 || null) : null);\n\nconst rows = category.series.map(pt => {\n  let val = pt.value;\n  if (val == null) return [pt.xLabel, null, null];\n\n  if (isIndex && base && base !== 0) {\n    val = (val \/ base) * 100;\n  }\n\n  if (isInfl) {\n    const m = pt.xLabel.match(\/(\\d{4})\/);\n    if (m) {\n      const year = parseInt(m[1],10);\n      const factor = inflationCumMap.get(year);\n      if (factor != null && factor !== 0) {\n        val = val \/ factor; \/\/ exprim\u00e9 en euros constants 2020\n      }\n    }\n  }\n\n  const isForecast = \/pr\u00e9vision\/i.test(pt.xLabel);\n  const style = isForecast ? 'point { fill-color: #93c5fd; size: 2; }' : null;\n\n  return [pt.xLabel, val, style];\n});\n  data.addRows(rows);\n\n  const options = {\n    legend: 'none',\n    height: 110,\n    axisTitlesPosition: 'out',\n    chartArea: { left: 42, right: 10, top: 8, bottom: 32, width: '100%', height: '100%' },\n    lineWidth: 2,\n    pointSize: 4,                 \/\/ taille par d\u00e9faut (peut \u00eatre surcharg\u00e9e par le style)\n    tooltip: { trigger: 'focus' },\n    hAxis: { title: 'P\u00e9riode', textPosition: 'out', slantedText: true, slantedTextAngle: 45 },\n    vAxis: {\n  title: isIndex ? 'Indice (base 100 en 2020)' :\n         isInfl  ? 'Valeur corrig\u00e9e (euros constants 2020)' :\n                   'Valeur',\n  textPosition: 'out',\n  viewWindowMode: 'pretty'\n}\n\n  };\n\n  const chart = new google.visualization.LineChart(el);\n  chart.draw(data, options);\n}\n\n\n  <\/script>\n\n\n\n<p><\/p>\n\n\n\n<p>Pour rappel, les flux observ\u00e9s ici correspondent aux flux qui sont r\u00e9capitul\u00e9s <a href=\"https:\/\/huguesg.fr\/site\/index.php\/diagramme-de-flux-sankey\/\" data-type=\"page\" data-id=\"174\">dans la page des flux \u00e9conomiques du syst\u00e8me des transports en France<\/a>, avec les correspondances ci-dessous.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"987\" src=\"https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/10\/image-1-1024x987.png\" alt=\"\" class=\"wp-image-597\" srcset=\"https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/10\/image-1-1024x987.png 1024w, https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/10\/image-1-300x289.png 300w, https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/10\/image-1-768x740.png 768w, https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/10\/image-1.png 1157w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.2) Zoom sur le Programme 203<\/h3>\n\n\n\n<p>Le Programme 203 est un des \u00e9l\u00e9ments majeurs de la politique nationale des transports. Cette partie d\u00e9taille son contenu et l&#8217;\u00e9volution de chacune de ses actions.<\/p>\n\n\n\n<script src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n  <style>\n    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 24px; }\n    #toolbar203 { display:flex; gap:16px; align-items:center; margin-bottom:16px; flex-wrap:wrap; }\n    #charts203 { display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap:14px; }\n    .card203 { border:1px solid #e5e7eb; border-radius:10px; padding:10px 12px; }\n    .title203 { font-size:13px; line-height:1.3; margin-bottom:4px; color:#111827; white-space:normal; }\n    .chart203 { width:100%; height:150px; }\n    .muted { color:#6b7280; font-size:12px; }\n  <\/style>\n\n  <div id=\"toolbar203\">\n    <strong>Affichage :<\/strong>\n    <label><input type=\"radio\" name=\"mode203\" value=\"raw203\" checked> Valeurs brutes<\/label>\n    <label><input type=\"radio\" name=\"mode203\" value=\"index203\"> Base 100 (2020)<\/label>\n<label><input type=\"radio\" name=\"mode203\" value=\"infl203\"> Corrig\u00e9 de l&#8217;inflation<\/label>\n\n    <span class=\"muted\">Astuce : passez la souris pour voir la valeur exacte.<\/span>\n  <\/div>\n  <div id=\"charts203\" aria-live=\"polite\"><\/div>\n\n  <script>\n    const CSV_URL_203 = 'https:\/\/huguesg.fr\/docs\/depenses-p203.csv';\n\nconst CSV_URL_INFLATION_203 = 'https:\/\/huguesg.fr\/docs\/inflation.csv';\nlet inflationCumMap203 = new Map(); \/\/ ann\u00e9e -> facteur cumulatif (base 1 en 2020)\n\nasync function loadInflation203() {\n  const txt = await fetch(CSV_URL_INFLATION_203, { cache: 'no-store' }).then(r=>r.text());\n  const lines = txt.trim().split(\/\\r?\\n\/).slice(1); \/\/ saute l\u2019ent\u00eate\n\n  \/\/ 1. Charger taux annuels\n  const rates = new Map();\n  lines.forEach(l => {\n    const [year, val] = l.split(\/[,;\\t]\/).map(x=>x.trim());\n    const y = parseInt(year,10);\n    const v = parseFloat(val.replace(',','.'));\n    if (y && !isNaN(v)) rates.set(y, v);\n  });\n\n  \/\/ 2. Construire les facteurs cumulatifs\n  \/\/ Base 2020 = 1\n  inflationCumMap203.set(2020, 1);\n  const years = [...rates.keys()].sort((a,b)=>a-b);\n  for (let y = 2021; y <= Math.max(...years); y++) {\n    const prevFactor = inflationCumMap203.get(y-1) ?? 1;\n    const rate = rates.get(y) ?? 0;\n    inflationCumMap203.set(y, prevFactor * (1 + rate\/100));\n  }\n}\n\n\n    \/\/ Charge Google Charts (package \"corechart\" pour LineChart).\n    google.charts.load('current', { packages: ['corechart'] });\n    google.charts.setOnLoadCallback(init203);\n\n    async function init203() {\n      try {\n        const csvText203 = await fetch(CSV_URL_203, { cache: 'no-store' }).then(r => {\n          if (!r.ok) throw new Error('\u00c9chec de chargement du CSV (' + r.status + ')');\n          return r.text();\n        });\n        const parsed203 = parseCSVSmart203(csvText203);\n        const dataset203 = normalizeData203(parsed203);\n\nawait loadInflation203();\n\n        \/\/ Construit l\u2019UI\n        buildCards203(dataset203);\n        \/\/ Premier rendu (valeurs brutes)\n        drawAll203(dataset203, 'raw203');\n\n        \/\/ Gestion du s\u00e9lecteur\n        document.querySelectorAll('input[name=\"mode203\"]').forEach(r => {\n          r.addEventListener('change', (e) => drawAll203(dataset203, e.target.value));\n        });\n      } catch (err) {\n        console.error(err);\n        document.getElementById('charts203').innerHTML =\n          '<div class=\"card\">Impossible de charger le CSV : ' + (err.message || err) + '<\/div>';\n      }\n    }\n\n    \/\/ D\u00e9tection \"intelligente\" du s\u00e9parateur et parsing simple (CSV mono-ligne par cellule ; pas de guillemets imbriqu\u00e9s)\n    function parseCSVSmart203(text) {\n      \/\/ Normalise les fins de ligne\n      const lines = text.replace(\/\\r\\n?\/g, '\\n').trim().split('\\n').filter(Boolean);\n\n      \/\/ D\u00e9tecte le s\u00e9parateur le plus probable parmi ; , \\t\n      const candidates = [';', '\\t', ','];\n      const score = (sep) => lines.slice(0, Math.min(lines.length, 5)).reduce((acc, l) => acc + (l.split(sep).length), 0);\n      candidates.sort((a,b) => score(b) - score(a));\n      const sep = candidates[0];\n\n      const rows = lines.map(l => l.split(sep).map(cell => cell.trim()));\n      return { rows, sep };\n    }\n\n    \/\/ Convertit en structure exploitable : headers + [{label, values: [{xLabel, value}], base2020}]\n    function normalizeData203(parsed) {\n      const [headers203, ...dataRows203] = parsed.rows;\n\n      \/\/ On suppose : col0 = libell\u00e9 ; colonnes suivantes = ann\u00e9es + types (ex: \"2020 Pr\u00e9vision\", ...)\n      const valueHeaders203 = headers203.slice(3);\n\n      \/\/ Indice de la colonne \u201c2020 R\u00e9alisation\u201d si existante ; sinon premi\u00e8re colonne contenant \"2020\"\n      let baseColIndex203 = valueHeaders203.findIndex(h => \/2020\\s*R[\u00e9e]al\/i.test(h));\n      if (baseColIndex203 === -1) baseColIndex203 = valueHeaders203.findIndex(h => \/2020\/.test(h));\n      \/\/ Fallback ultime\n      if (baseColIndex203 === -1) baseColIndex203 = 0;\n\n      const categories203 = [];\n\n      for (const row203 of dataRows203) {\n        const label203 = (row203[1] || '') + ' \u2014 ' + (row203[2] || '');\n        if (!row203[1] && !row203[2]) continue; \/\/ ignore lignes vides\n\n        \/\/ Convertit chaque cellule num\u00e9rique (format FR avec virgule) en Number\n        const nums203 = row203.slice(3).map(v => toNumberFR(v));\n\n        \/\/ Ignore les lignes totalement vides\n        if (nums203.every(v => v === null)) continue;\n\n        const series203 = valueHeaders203.map((h, i) => ({\n          xLabel203: h,\n          value203: isFinite(nums203[i]) ? nums203[i] : null\n        }));\n\n        const base2020203 = isFinite(nums203[baseColIndex203]) ? nums203[baseColIndex203] : null;\n\n        categories203.push({ label203, series203, base2020203 });\n      }\n\n      return { categories203 };\n    }\n\n    \/\/ Conversion nombre FR -> JS Number (retourne null si vide \/ non num\u00e9rique)\n    function toNumberFR(s) {\n      if (s == null || s === '') return null;\n      \/\/ autorise le s\u00e9parateur de milliers espace fine ou espace, mais pas pr\u00e9sent ici a priori\n      const cleaned = s.replace(\/\\s?(?=(?:\\d{3})+(?!\\d))\/g, '');\n      \/\/ virgule d\u00e9cimale -> point\n      const normalized = cleaned.replace(',', '.');\n      const n = Number(normalized);\n      return isNaN(n) ? null : n;\n    }\n\n    function buildCards203(dataset203) {\n      const container203 = document.getElementById('charts203');\n      container203.innerHTML = '';\n      dataset203.categories203.forEach((cat, idx) => {\n        const card203 = document.createElement('div');\n        card203.className = 'card203';\n        const title203 = document.createElement('div');\n        title203.className = 'title203';\n        title203.textContent = cat.label203;\n        const chartDiv203 = document.createElement('div');\n        chartDiv203.className = 'chart203';\n        chartDiv203.id = 'chart203-' + idx;\n        card203.appendChild(title203);\n        card203.appendChild(chartDiv203);\n        container203.appendChild(card203);\n      });\n    }\n\n    function drawAll203(dataset203, mode) {\n      dataset203.categories203.forEach((cat, idx) => drawSparkline203(cat, document.getElementById('chart203-' + idx), mode));\n    }\n\nfunction drawSparkline203(category, el, mode) {\n  const data203 = new google.visualization.DataTable();\n  data203.addColumn('string', 'P\u00e9riode');\n  data203.addColumn('number', category.label203);\n  data203.addColumn({ type: 'string', role: 'style' });\n\n  const isIndex203 = (mode === 'index203');\n  const isInfl203  = (mode === 'infl203');\n  const base203 = (isIndex203 ? (category.base2020203 || null) : null);\n\n  const rows203 = category.series203.map(pt => {\n    let val203 = pt.value203;\n    if (val203 == null) return [pt.xLabel203, null, null];\n\n    if (isIndex203 && base203 && base203 !== 0) {\n      val203 = (val203 \/ base203) * 100;\n    }\n\n    if (isInfl203) {\n  const m = pt.xLabel203.match(\/(\\d{4})\/);\n  if (m) {\n    const year = parseInt(m[1],10);\n    const factor = inflationCumMap203.get(year);\n    if (factor != null && factor !== 0) {\n      \/\/ On exprime la valeur en euros constants 2020\n      val203 = val203 \/ factor;\n    }\n  }\n}\n\n    const isForecast203 = \/pr\u00e9vision\/i.test(pt.xLabel203);\n    const style203 = isForecast203 ? 'point { fill-color: #93c5fd; size: 2; }' : null;\n    return [pt.xLabel203, val203, style203];\n  });\n\n  data203.addRows(rows203);\n\n  const options203 = {\n    legend: 'none',\n    height: 150,\n    axisTitlesPosition: 'out',\n    chartArea: { left: 42, right: 10, top: 8, bottom: 32, width: '100%', height: '100%' },\n    lineWidth: 2,\n    pointSize: 4,\n    tooltip: { trigger: 'focus' },\n    hAxis: { title: 'P\u00e9riode', textPosition: 'out', slantedText: true, slantedTextAngle: 45 },\n    vAxis: {\n  title: isIndex203 ? 'Indice (base 100 en 2020)' :\n         isInfl203 ? 'Valeur corrig\u00e9e (euros constants 2020)' : 'Valeur',\n  textPosition: 'out',\n  viewWindowMode: 'pretty'\n}\n\n  };\n\n  const chart203 = new google.visualization.LineChart(el);\n  chart203.draw(data203, options203);\n}\n\n\n  <\/script>\n\n\n\n<p>Les flux observ\u00e9s ci-dessus correspondent \u00e0 la partie ci-dessous du diagramme de flux, et recouvrent donc des valeurs d\u00e9j\u00e0 pr\u00e9sentes dans la partie pr\u00e9c\u00e9dente.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"653\" height=\"616\" src=\"https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/09\/Recap-flux-P203.png\" alt=\"\" class=\"wp-image-588\" srcset=\"https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/09\/Recap-flux-P203.png 653w, https:\/\/huguesg.fr\/site\/wp-content\/uploads\/2025\/09\/Recap-flux-P203-300x283.png 300w\" sizes=\"auto, (max-width: 653px) 100vw, 653px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.3) Zoom sur le budget de l&#8217;AFITF<\/h3>\n\n\n\n<p>L&#8217;Agence de Financement des Infrastructures de Transport Fran\u00e7aises (AFITF) vote son budget de mani\u00e8re ind\u00e9pendante de celui de l&#8217;Etat, bien que ses ressources financi\u00e8res soient d\u00e9cid\u00e9es par le vote du budget, et que ses versements rentrent pour une large part dans les financements du programme 203 \u00e9voqu\u00e9 ci-dessus, rendant la lisibilit\u00e9 du budget des transports pour le moins complexe&#8230;<\/p>\n\n\n\n<p>Cette partie d\u00e9taille donc le contenu du budget de l&#8217;AFITF, ainsi que l&#8217;\u00e9volution de chacune des actions.<\/p>\n\n\n\n<script src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n<style>\n  body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 24px; }\n  #toolbarafitf { display:flex; gap:16px; align-items:center; margin-bottom:16px; flex-wrap:wrap; }\n  #chartsafitf { display:grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap:14px; }\n  .cardafitf { border:1px solid #e5e7eb; border-radius:10px; padding:10px 12px; }\n  .titleafitf { font-size:13px; line-height:1.3; margin-bottom:4px; color:#111827; white-space:normal; }\n  .chartafitf { width:100%; height:150px; }\n  .muted { color:#6b7280; font-size:12px; }\n<\/style>\n\n<div id=\"toolbarafitf\">\n  <strong>Affichage :<\/strong>\n  <label><input type=\"radio\" name=\"modeafitf\" value=\"rawafitf\" checked> Valeurs brutes<\/label>\n  <label><input type=\"radio\" name=\"modeafitf\" value=\"indexafitf\"> Base 100 (2020)<\/label>\n  <label><input type=\"radio\" name=\"modeafitf\" value=\"inflafitf\"> Corrig\u00e9 de l&#8217;inflation<\/label>\n  <span class=\"muted\">Astuce : passez la souris pour voir la valeur exacte.<\/span>\n<\/div>\n<div id=\"chartsafitf\" aria-live=\"polite\"><\/div>\n\n<script>\n  \/\/ --- URLs des CSV\n  const CSV_URL_afitf = 'https:\/\/huguesg.fr\/docs\/depenses-afitf.csv';\n  const CSV_URL_INFLATION_afitf = 'https:\/\/huguesg.fr\/docs\/inflation.csv';\n\n  \/\/ ---------- D\u00c9CODAGE ROBUSTE (UTF-8 -> fallback Windows-1252\/Latin-1) ----------\n  async function fetchTextSmart(url) {\n    const resp = await fetch(url, { cache: 'no-store' });\n    if (!resp.ok) throw new Error('\u00c9chec de chargement (' + resp.status + ')');\n    const buf = await resp.arrayBuffer();\n    const u8  = new Uint8Array(buf);\n\n    \/\/ 1) si le serveur annonce un charset, on le tente d\u2019abord\n    const ct = resp.headers.get('content-type') || '';\n    const m  = ct.match(\/charset\\s*=\\s*([^;]+)\/i);\n    const hinted = m ? m[1].trim().toLowerCase() : null;\n\n    const tryDecode = (label) => {\n      try {\n        return new TextDecoder(label, { fatal: false }).decode(u8);\n      } catch { return null; }\n    };\n\n    \/\/ Ordre d\u2019essai : hint serveur -> utf-8 -> windows-1252 -> iso-8859-1\n    const candidates = [hinted, 'utf-8', 'windows-1252', 'iso-8859-1'].filter(Boolean);\n    let text = null;\n    for (const enc of candidates) {\n      text = tryDecode(enc);\n      if (!text) continue;\n      \/\/ Heuristique : si trop de \ufffd (U+FFFD), on consid\u00e8re l\u2019essai mauvais\n      const bad = (text.match(\/\\uFFFD\/g) || []).length;\n      if (bad <= 2) break; \/\/ ok\n      text = null;\n    }\n    if (!text) {\n      \/\/ dernier filet de s\u00e9curit\u00e9\n      text = new TextDecoder('windows-1252').decode(u8);\n    }\n\n    \/\/ Retire un \u00e9ventuel BOM\n    if (text.charCodeAt(0) === 0xFEFF) text = text.slice(1);\n    return text;\n  }\n\n  \/\/ ---------- INFLATION ----------\n  let inflationCumMapafitf = new Map(); \/\/ ann\u00e9e -> facteur cumulatif (base 1 en 2020)\n\n  async function loadInflationafitf() {\n    const txt = await fetchTextSmart(CSV_URL_INFLATION_afitf);\n    const lines = txt.replace(\/\\r\\n?\/g, '\\n').trim().split('\\n').slice(1); \/\/ saute l\u2019ent\u00eate\n\n    const rates = new Map();\n    for (const l of lines) {\n      \/\/ supporte ; , ou tab\n      const [year, val] = l.split(\/[,;\\t]\/).map(x => x.trim());\n      const y = parseInt(year, 10);\n      \/\/ remplace la virgule, retire espaces ins\u00e9cables\/\u00e9troites\n      const v = parseFloat((val || '').replace(\/[\\u00A0\\u202F\\s]\/g, '').replace(',', '.'));\n      if (y && !isNaN(v)) rates.set(y, v);\n    }\n\n    inflationCumMapafitf.set(2020, 1);\n    const years = [...rates.keys()].sort((a,b)=>a-b);\n    for (let y = 2021; y <= Math.max(...years, 2020); y++) {\n      const prev = inflationCumMapafitf.get(y-1) ?? 1;\n      const r = rates.get(y) ?? 0;\n      inflationCumMapafitf.set(y, prev * (1 + r\/100));\n    }\n  }\n\n  \/\/ ---------- GOOGLE CHARTS ----------\n  google.charts.load('current', { packages: ['corechart'] });\n  google.charts.setOnLoadCallback(initafitf);\n\n  async function initafitf() {\n    try {\n      const csvTextafitf = await fetchTextSmart(CSV_URL_afitf);\n      const parsedafitf = parseCSVSmartafitf(csvTextafitf);\n      const datasetafitf = normalizeDataafitf(parsedafitf);\n\n      await loadInflationafitf();\n\n      buildCardsafitf(datasetafitf);\n      drawAllafitf(datasetafitf, 'rawafitf');\n\n      document.querySelectorAll('input[name=\"modeafitf\"]').forEach(r => {\n        r.addEventListener('change', (e) => drawAllafitf(datasetafitf, e.target.value));\n      });\n    } catch (err) {\n      console.error(err);\n      document.getElementById('chartsafitf').innerHTML =\n        '<div class=\"cardafitf\">Impossible de charger le CSV : ' + (err.message || err) + '<\/div>';\n    }\n  }\n\n  \/\/ ---------- PARSE CSV (simple) ----------\n  function parseCSVSmartafitf(text) {\n    const lines = text.replace(\/\\r\\n?\/g, '\\n').trim().split('\\n').filter(Boolean);\n\n    \/\/ D\u00e9tecte le s\u00e9parateur le plus probable parmi ; , \\t\n    const candidates = [';', '\\t', ','];\n    const score = (sep) => lines.slice(0, Math.min(lines.length, 5))\n                                .reduce((acc, l) => acc + l.split(sep).length, 0);\n    candidates.sort((a,b) => score(b) - score(a));\n    const sep = candidates[0];\n\n    const rows = lines.map(l => l.split(sep).map(cell => {\n      \/\/ Nettoie BOM \u00e9ventuel sur la premi\u00e8re cellule\n      if (cell && cell.charCodeAt(0) === 0xFEFF) cell = cell.slice(1);\n      return cell.trim();\n    }));\n\n    return { rows, sep };\n  }\n\n  \/\/ ---------- NORMALISATION DES DONN\u00c9ES ----------\n  function normalizeDataafitf(parsed) {\n    const [headersafitf, ...dataRowsafitf] = parsed.rows;\n\n    \/\/ On suppose : col0=Mode ; col1=Cat\u00e9gorie ; col2 = 2020 R\u00e9alisation ; etc.\n    const valueHeadersafitf = headersafitf.slice(3);\n\n    \/\/ Colonne de base (2020 R\u00e9alisation ou, \u00e0 d\u00e9faut, premi\u00e8re colonne contenant 2020)\n    let baseColIndexafitf = valueHeadersafitf.findIndex(h => \/2020\\s*R[\u00e9e]al\/i.test(h));\n    if (baseColIndexafitf === -1) baseColIndexafitf = valueHeadersafitf.findIndex(h => \/2020\/.test(h));\n    if (baseColIndexafitf === -1) baseColIndexafitf = 0;\n\n    const categoriesafitf = [];\n\n    for (const rowafitf of dataRowsafitf) {\n      const labelafitf = (rowafitf[0] || '') + ' \u2014 ' + (rowafitf[1] || '');\n      if (!rowafitf[0] && !rowafitf[1]) continue;\n\n      \/\/ Conversion FR -> Number avec normalisation des espaces (y compris ins\u00e9cables)\n      const numsafitf = rowafitf.slice(2).map(v => toNumberFR(v));\n\n      if (numsafitf.every(v => v === null)) continue;\n\n      const seriesafitf = valueHeadersafitf.map((h, i) => ({\n        xLabelafitf: h,\n        valueafitf: isFinite(numsafitf[i]) ? numsafitf[i] : null\n      }));\n\n      const base2020afitf = isFinite(numsafitf[baseColIndexafitf]) ? numsafitf[baseColIndexafitf] : null;\n\n      categoriesafitf.push({ labelafitf, seriesafitf, base2020afitf });\n    }\n\n    return { categoriesafitf };\n  }\n\n  function toNumberFR(s) {\n    if (s == null) return null;\n    const str = String(s).trim();\n    if (!str) return null;\n    \/\/ Supprime espaces normaux, ins\u00e9cables (U+00A0) et fines (U+202F)\n    const noSpaces = str.replace(\/[\\u00A0\\u202F\\s]\/g, '');\n    \/\/ Virgule d\u00e9cimale -> point\n    const normalized = noSpaces.replace(',', '.');\n    const n = Number(normalized);\n    return Number.isFinite(n) ? n : null;\n  }\n\n  \/\/ ---------- UI + DESSIN ----------\n  function buildCardsafitf(datasetafitf) {\n    const containerafitf = document.getElementById('chartsafitf');\n    containerafitf.innerHTML = '';\n    datasetafitf.categoriesafitf.forEach((cat, idx) => {\n      const cardafitf = document.createElement('div');\n      cardafitf.className = 'cardafitf';\n      const titleafitf = document.createElement('div');\n      titleafitf.className = 'titleafitf';\n      titleafitf.textContent = cat.labelafitf;\n      const chartDivafitf = document.createElement('div');\n      chartDivafitf.className = 'chartafitf';\n      chartDivafitf.id = 'chartafitf-' + idx;\n      cardafitf.appendChild(titleafitf);\n      cardafitf.appendChild(chartDivafitf);\n      containerafitf.appendChild(cardafitf);\n    });\n  }\n\n  function drawAllafitf(datasetafitf, mode) {\n    datasetafitf.categoriesafitf.forEach((cat, idx) =>\n      drawSparklineafitf(cat, document.getElementById('chartafitf-' + idx), mode)\n    );\n  }\n\n  function drawSparklineafitf(category, el, mode) {\n    const dataafitf = new google.visualization.DataTable();\n    dataafitf.addColumn('string', 'P\u00e9riode');\n    dataafitf.addColumn('number', category.labelafitf);\n    dataafitf.addColumn({ type: 'string', role: 'style' });\n\n    const isIndexafitf = (mode === 'indexafitf');\n    const isInflafitf  = (mode === 'inflafitf');\n    const baseafitf    = (isIndexafitf ? (category.base2020afitf || null) : null);\n\n    const rowsafitf = category.seriesafitf.map(pt => {\n      let valafitf = pt.valueafitf;\n      if (valafitf == null) return [pt.xLabelafitf, null, null];\n\n      if (isIndexafitf && baseafitf && baseafitf !== 0) {\n        valafitf = (valafitf \/ baseafitf) * 100;\n      }\n\n      if (isInflafitf) {\n        const m = pt.xLabelafitf.match(\/(\\d{4})\/);\n        if (m) {\n          const year = parseInt(m[1], 10);\n          const factor = inflationCumMapafitf.get(year);\n          if (factor != null && factor !== 0) {\n            \/\/ euros constants 2020\n            valafitf = valafitf \/ factor;\n          }\n        }\n      }\n\n      const isForecastafitf = \/pr\u00e9vision\/i.test(pt.xLabelafitf);\n      const styleafitf = isForecastafitf ? 'point { fill-color: #93c5fd; size: 2; }' : null;\n      return [pt.xLabelafitf, valafitf, styleafitf];\n    });\n\n    dataafitf.addRows(rowsafitf);\n\n    const optionsafitf = {\n      legend: 'none',\n      height: 150,\n      axisTitlesPosition: 'out',\n      chartArea: { left: 42, right: 10, top: 8, bottom: 32, width: '100%', height: '100%' },\n      lineWidth: 2,\n      pointSize: 4,\n      tooltip: { trigger: 'focus' },\n      hAxis: { title: 'P\u00e9riode', textPosition: 'out', slantedText: true, slantedTextAngle: 45 },\n      vAxis: {\n        title: isIndexafitf ? 'Indice (base 100 en 2020)' :\n               isInflafitf ? 'Valeur corrig\u00e9e (euros constants 2020)' : 'Valeur',\n        textPosition: 'out',\n        viewWindowMode: 'pretty'\n      }\n    };\n\n    const chartafitf = new google.visualization.LineChart(el);\n    chartafitf.draw(dataafitf, optionsafitf);\n  }\n<\/script>\n\n\n\n\n<p>Les flux observ\u00e9s ci-dessus correspondent \u00e0 la partie num\u00e9rot\u00e9e 3 du diagramme de flux ci-dessus.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. R\u00e9partition du budget des transports par mode de transport<\/h2>\n\n\n\n<p>Le troisi\u00e8me graphique met en avant la r\u00e9partition du budget des transports par mode de transport. Il s&#8217;agit d&#8217;une vue comparative de l&#8217;allocation des ressources entre les diff\u00e9rents modes de transport, tels que le ferroviaire, la route, le fluvial, l&#8217;a\u00e9rien, et d&#8217;autres formes de mobilit\u00e9.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>R\u00e9partition des priorit\u00e9s<\/strong> : Les modes ferroviaire et routier captent la majorit\u00e9 des financements, refl\u00e9tant l&#8217;importance accord\u00e9e \u00e0 ces deux secteurs. On note \u00e9galement des investissements significatifs dans la relance ferroviaire et les transports collectifs, ce qui indique un effort pour soutenir une transition vers des modes de transport plus \u00e9cologiques.<\/li>\n<\/ul>\n\n\n\n<div id=\"chart_div\" style=\"height: 800px;\"><\/div>\n\n<script type=\"text\/javascript\" src=\"https:\/\/www.gstatic.com\/charts\/loader.js\"><\/script>\n<script type=\"text\/javascript\">\n  google.charts.load('current', {packages: ['corechart', 'bar']});\n  google.charts.setOnLoadCallback(drawChart);\n\n  function drawChart() {\n    fetch('https:\/\/huguesg.fr\/docs\/depenses-modes.csv')\n      .then(response => response.text())\n      .then(data => {\n        const rows = data.split('\\n').map(row => row.split(';'));\n        const headers = rows[0]; \/\/ First row for headers\n\n        const dataTable = new google.visualization.DataTable();\n        dataTable.addColumn('string', 'Ann\u00e9e');\n\n        \/\/ Add columns for each category\n        rows.slice(1).forEach(row => {\n          dataTable.addColumn('number', row[0]);\n          dataTable.addColumn({type: 'string', role: 'annotation'});\n          dataTable.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}}); \/\/ Tooltip column\n        \n        });\n\n        \/\/ Transpose the data and calculate percentages\n        for (let i = 1; i < headers.length; i++) {\n          const rowData = [headers[i]];\n          let total = 0;\n          const values = rows.slice(1).map(row => {\n              const value = parseFloat((row[i] || '').replace(\/,\/g, '.'));\n              return isNaN(value) ? 0 : value;\n           });\n           total = values.reduce((sum, value) => sum + value, 0);\n\n          values.forEach((value, index) => {\n            const percentage = (value \/ total) * 100;\n            const tooltip = `<div><strong>${headers[i]}<\/strong><br>${rows[index + 1][0]}: ${value.toFixed(2)} (${percentage.toFixed(1)}%)<\/div>`;\n            rowData.push(percentage);\n            rowData.push(percentage > 5 ? `${percentage.toFixed(1)}%` : ''); \/\/ Only add annotation if > 5%\n            rowData.push(tooltip); \/\/ Tooltip with absolute and relative values\n          });\n          dataTable.addRow(rowData);\n        }\nconsole.log(dataTable);\n        const options = {\n          title: 'Budget des Transports en %',\n          isStacked: true,\n          height: 800,\n          legend: { position: 'top', maxLines: 3 },\n          vAxis: {\n            title: 'Pourcentage',\n            minValue: 0,\n            maxValue: 100,\n            format: '#\\'%\\''\n          },\n          hAxis: {\n            title: 'Ann\u00e9e'\n          },\n          tooltip: { isHtml: true }, \/\/ Enable HTML tooltips\n          annotations: {\n            alwaysOutside: false,\n            textStyle: {\n              fontSize: 12,\n              auraColor: 'none',\n              color: '#555'\n            }\n          }\n        };\n\n        const chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));\n        chart.draw(dataTable, options);\n      })\n      .catch(error => console.error('Error fetching CSV data:', error));\n  }\n<\/script>\n\n\n\n<h2 class=\"wp-block-heading\">4. D\u00e9tail des montants par cat\u00e9gorie<\/h2>\n\n\n\n<p>Ce grahique reprend de mani\u00e8re exhaustive les montants budg\u00e9taires allou\u00e9s \u00e0 chaque cat\u00e9gorie pour les ann\u00e9es 2020 \u00e0 2024. Il permet d&#8217;avoir une vue d\u00e9taill\u00e9e sur les sommes engag\u00e9es, ann\u00e9e par ann\u00e9e, pour chaque cat\u00e9gorie du budget des transports.<\/p>\n\n\n\n<div id=\"csv-table-container-depenses-categories\"><\/div>\n\n<script>\n  document.addEventListener('DOMContentLoaded', function() {\n    fetch('https:\/\/huguesg.fr\/docs\/depenses-categories.csv')\n      .then(response => response.text())\n      .then(data => {\n        let rows = data.split('\\n');\n        let table = '<table>';\n        rows.forEach(row => {\n          let columns = row.split(';');\n          table += '<tr>';\n          columns.forEach(column => {\n            table += `<td>${column}<\/td>`;\n          });\n          table += '<\/tr>';\n        });\n        table += '<\/table>';\n        document.getElementById('csv-table-container-depenses-categories').innerHTML = table;\n      })\n      .catch(error => console.error('Error fetching CSV data:', error));\n  });\n<\/script>\n\n\n\n<h2 class=\"wp-block-heading\">5. D\u00e9tail de la nature des lignes budg\u00e9taires<\/h2>\n\n\n\n<p>Le dernier tableau pr\u00e9sente la nature de chaque ligne budg\u00e9taire du budget des transports. Il s&#8217;agit d&#8217;une explication pr\u00e9cise de ce que repr\u00e9sente chaque cat\u00e9gorie budg\u00e9taire et de comment ces fonds sont utilis\u00e9s.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Clarifications<\/strong> : Par exemple, les &#8220;Taxes Affect\u00e9es SGP&#8221; correspondent aux taxes d\u00e9cid\u00e9es par l&#8217;\u00c9tat et directement affect\u00e9es au financement de la Soci\u00e9t\u00e9 du Grand Paris. De m\u00eame, le &#8220;Fonds vert&#8221; est d\u00e9di\u00e9 \u00e0 l&#8217;am\u00e9lioration du cadre de vie, notamment via le soutien \u00e0 la transition \u00e9cologique dans les zones \u00e0 faibles \u00e9missions.<\/li>\n<\/ul>\n\n\n\n<div id=\"csv-table-container-categories\"><\/div>\n\n<script>\n  document.addEventListener('DOMContentLoaded', function() {\n    fetch('https:\/\/huguesg.fr\/docs\/categories.csv')\n      .then(response => response.text())\n      .then(data => {\n        let rows = data.split('\\n');\n        let table = '<table>';\n        rows.forEach(row => {\n          let columns = row.split(';');\n          table += '<tr>';\n          columns.forEach(column => {\n            table += `<td>${column}<\/td>`;\n          });\n          table += '<\/tr>';\n        });\n        table += '<\/table>';\n        document.getElementById('csv-table-container-categories').innerHTML = table;\n      })\n      .catch(error => console.error('Error fetching CSV data:', error));\n  });\n<\/script>\n\n\n\n<p>Ces graphiques et tableaux nous permettent de mieux comprendre la complexit\u00e9 et les \u00e9volutions du budget des transports en France. Nous observons que l&#8217;\u00c9tat continue de concentrer une part importante de ses investissements dans des secteurs strat\u00e9giques comme les infrastructures ferroviaires et routi\u00e8res, tout en prenant progressivement en compte les enjeux li\u00e9s \u00e0 la mobilit\u00e9 durable et \u00e0 la transition \u00e9cologique. Ces analyses nous offrent une vision claire des priorit\u00e9s budg\u00e9taires et de l&#8217;impact de ces investissements sur les diff\u00e9rents modes de transport.<\/p>\n\n\n\n<p>Au fil des ann\u00e9es, il sera int\u00e9ressant de suivre comment ces allocations \u00e9voluent, notamment avec l&#8217;introduction de nouvelles lignes budg\u00e9taires ax\u00e9es sur la durabilit\u00e9 et la modernisation des infrastructures.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><a href=\"https:\/\/huguesg.fr\/site\/index.php\/budget-transports\/\">Retour au sommaire de la s\u00e9rie Budget Transport<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le budget des transports est un sujet central dans les finances publiques fran\u00e7aises, englobant une vari\u00e9t\u00e9 de projets allant de la mobilit\u00e9 quotidienne \u00e0 la modernisation des infrastructures. Dans cet article, nous allons explorer en d\u00e9tail l&#8217;\u00e9volution du budget national des transports au fil des ann\u00e9es. Nous aborderons les pr\u00e9visions et les r\u00e9alisations, la composition [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","footnotes":""},"class_list":["post-111","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/pages\/111","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/comments?post=111"}],"version-history":[{"count":112,"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/pages\/111\/revisions"}],"predecessor-version":[{"id":614,"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/pages\/111\/revisions\/614"}],"wp:attachment":[{"href":"https:\/\/huguesg.fr\/site\/index.php\/wp-json\/wp\/v2\/media?parent=111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}