Données parcours-sup 2021-2025

Voir Parcoursup 2025 - vœux de poursuite d’études et de réorientation dans l’enseignement supérieur et réponses des établissements.

[1]:
import pandas
from teachpyx.tools.pandas import read_csv_cached
from skrub import TableReport

Récupération des données

[2]:
urls = {
    "2021": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2021/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
    "2022": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2022/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
    "2023": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2023/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
    "2024": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup_2024/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
    "2025": "https://data.enseignementsup-recherche.gouv.fr/api/explore/v2.1/catalog/datasets/fr-esr-parcoursup/exports/csv?lang=fr&timezone=Europe%2FBerlin&use_labels=true&delimiter=%3B",
}
[3]:
df2025 = read_csv_cached(urls["2025"], sep=";")
TableReport(df2025, max_plot_columns=120, max_association_columns=120)
Processing column 118 / 118
[3]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[4]:
df2024 = read_csv_cached(urls["2024"], sep=";")
TableReport(df2024, max_plot_columns=120, max_association_columns=120)
Processing column 118 / 118
[4]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[5]:
dfs = {}
for k, url in urls.items():
    print(f"loading {k!r}")
    dfs[k] = read_csv_cached(url, sep=";")
loading '2021'
loading '2022'
loading '2023'
loading '2024'
loading '2025'

Fusion des années

[6]:
df = pandas.concat(dfs.values(), axis=0)
df.shape
[6]:
(69240, 123)

Toutes les variables

[7]:
admis = [c for c in df.columns if "Effectif" in c]
admis[:20]
[7]:
['Effectif total des candidats pour une formation',
 'Effectif total des candidats en phase principale',
 'Effectif des candidats néo bacheliers généraux en phase principale',
 'Effectif des candidats néo bacheliers technologiques en phase principale',
 'Effectif des candidats néo bacheliers professionnels en phase principale',
 'Effectif des autres candidats en phase principale',
 'Effectif total des candidats en phase complémentaire',
 'Effectif des candidats néo bacheliers généraux en phase complémentaire',
 'Effectif des candidats néo bacheliers technologique en phase complémentaire',
 'Effectif des candidats néo bacheliers professionnels en phase complémentaire',
 'Effectifs des autres candidats en phase complémentaire',
 'Effectif total des candidats classés par l’établissement en phase principale',
 'Effectif des candidats classés par l’établissement en phase complémentaire',
 'Effectif des candidats classés par l’établissement en internat (CPGE)',
 'Effectif des candidats classés par l’établissement hors internat (CPGE)',
 'Effectif des candidats néo bacheliers généraux classés par l’établissement',
 'Effectif des candidats néo bacheliers technologiques classés par l’établissement',
 'Effectif des candidats néo bacheliers professionnels classés par l’établissement',
 'Effectif des autres candidats classés par l’établissement',
 'Effectif total des candidats ayant reçu une proposition d’admission de la part de l’établissement']
[8]:
admis[20:]
[8]:
['Effectif total des candidats ayant accepté la proposition de l’établissement (admis)',
 'Effectif des admis en phase principale',
 'Effectif des admis en phase complémentaire',
 'Effectif des admis néo bacheliers',
 'Effectif des admis néo bacheliers généraux',
 'Effectif des admis néo bacheliers technologiques',
 'Effectif des admis néo bacheliers professionnels',
 'Effectif des autres candidats admis',
 'Effectif des admis néo bacheliers généraux ayant eu une mention au bac',
 'Effectif des admis néo bacheliers technologiques ayant eu une mention au bac',
 'Effectif des admis néo bacheliers professionnels ayant eu une mention au bac',
 'Effectif des candidats en terminale générale ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des candidats en terminale technologique ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des candidats en terminale professionnelle ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des autres candidats ayant reçu une proposition d’admission de la part de l’établissement']
[9]:
list_columns = sorted(df.columns)
list_columns[:30]
[9]:
['% d’admis ayant reçu leur proposition d’admission avant la fin de la procédure principale',
 '% d’admis ayant reçu leur proposition d’admission avant le baccalauréat',
 "% d’admis ayant reçu leur proposition d’admission à l'ouverture de la procédure principale",
 '% d’admis dont filles',
 '% d’admis néo bacheliers',
 '% d’admis néo bacheliers avec mention Assez Bien au bac',
 '% d’admis néo bacheliers avec mention Bien au bac',
 '% d’admis néo bacheliers avec mention Très Bien au bac',
 '% d’admis néo bacheliers avec mention Très Bien avec félicitations au bac',
 '% d’admis néo bacheliers boursiers',
 '% d’admis néo bacheliers généraux',
 '% d’admis néo bacheliers issus de la même académie',
 '% d’admis néo bacheliers issus de la même académie (Paris/Créteil/Versailles réunies)',
 '% d’admis néo bacheliers issus du même établissement (BTS/CPGE)',
 '% d’admis néo bacheliers professionnels',
 '% d’admis néo bacheliers sans information sur la mention au bac',
 '% d’admis néo bacheliers sans mention au bac',
 '% d’admis néo bacheliers technologiques',
 'Académie de l’établissement',
 'COD_AFF_FORM',
 'Capacité de l’établissement par formation',
 "Code UAI de l'établissement",
 'Code départemental de l’établissement',
 'Commune de l’établissement',
 "Concours communs et banque d'épreuves",
 'Coordonnées GPS de la formation',
 'Dont % d’admis avec mention (BG)',
 'Dont % d’admis avec mention (BP)',
 'Dont % d’admis avec mention (BT)',
 'Dont effectif des admis ayant reçu leur proposition d’admission avant la fin de la procédure principale']
[10]:
list_columns[30:60]
[10]:
['Dont effectif des admis ayant reçu leur proposition d’admission avant le baccalauréat',
 "Dont effectif des admis ayant reçu leur proposition d’admission à l'ouverture de la procédure principale",
 'Dont effectif des admis boursiers néo bacheliers',
 'Dont effectif des admis en internat',
 'Dont effectif des admis issus de la même académie',
 'Dont effectif des admis issus de la même académie (Paris/Créteil/Versailles réunies)',
 'Dont effectif des admis issus du même établissement (BTS/CPGE)',
 'Dont effectif des admis néo bacheliers avec mention Assez Bien au bac',
 'Dont effectif des admis néo bacheliers avec mention Bien au bac',
 'Dont effectif des admis néo bacheliers avec mention Très Bien au bac',
 'Dont effectif des admis néo bacheliers avec mention Très Bien avec félicitations au bac',
 'Dont effectif des admis néo bacheliers sans information sur la mention au bac',
 'Dont effectif des admis néo bacheliers sans mention au bac',
 'Dont effectif des admises issues du même établissement (BTS/CPGE)',
 'Dont effectif des candidates admises',
 'Dont effectif des candidates pour une formation',
 'Dont effectif des candidats ayant postulé en internat',
 'Dont effectif des candidats boursiers en terminale générale ayant reçu une proposition d’admission de la part de l’établissement',
 'Dont effectif des candidats boursiers en terminale générale professionnelle ayant reçu une proposition d’admission de la part de l’établissement',
 'Dont effectif des candidats boursiers en terminale technologique ayant reçu une proposition d’admission de la part de l’établissement',
 'Dont effectif des candidats boursiers néo bacheliers généraux classés par l’établissement',
 'Dont effectif des candidats boursiers néo bacheliers généraux en phase principale',
 'Dont effectif des candidats boursiers néo bacheliers professionnels classés par l’établissement',
 'Dont effectif des candidats boursiers néo bacheliers professionnels en phase principale',
 'Dont effectif des candidats boursiers néo bacheliers technologiques classés par l’établissement',
 'Dont effectif des candidats boursiers néo bacheliers technologiques en phase principale',
 'Dont taux d’accès des candidats ayant un bac général ayant postulé à la formation',
 'Dont taux d’accès des candidats ayant un bac professionnel ayant postulé à la formation',
 'Dont taux d’accès des candidats ayant un bac technologique ayant postulé à la formation',
 'Département de l’établissement']
[11]:
list_columns[60:90]
[11]:
['Effectif des admis en phase complémentaire',
 'Effectif des admis en phase principale',
 'Effectif des admis néo bacheliers',
 'Effectif des admis néo bacheliers généraux',
 'Effectif des admis néo bacheliers généraux ayant eu une mention au bac',
 'Effectif des admis néo bacheliers professionnels',
 'Effectif des admis néo bacheliers professionnels ayant eu une mention au bac',
 'Effectif des admis néo bacheliers technologiques',
 'Effectif des admis néo bacheliers technologiques ayant eu une mention au bac',
 'Effectif des autres candidats admis',
 'Effectif des autres candidats ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des autres candidats classés par l’établissement',
 'Effectif des autres candidats en phase principale',
 'Effectif des candidats classés par l’établissement en internat (CPGE)',
 'Effectif des candidats classés par l’établissement en phase complémentaire',
 'Effectif des candidats classés par l’établissement hors internat (CPGE)',
 'Effectif des candidats en terminale générale ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des candidats en terminale professionnelle ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des candidats en terminale technologique ayant reçu une proposition d’admission de la part de l’établissement',
 'Effectif des candidats néo bacheliers généraux classés par l’établissement',
 'Effectif des candidats néo bacheliers généraux en phase complémentaire',
 'Effectif des candidats néo bacheliers généraux en phase principale',
 'Effectif des candidats néo bacheliers professionnels classés par l’établissement',
 'Effectif des candidats néo bacheliers professionnels en phase complémentaire',
 'Effectif des candidats néo bacheliers professionnels en phase principale',
 'Effectif des candidats néo bacheliers technologique en phase complémentaire',
 'Effectif des candidats néo bacheliers technologiques classés par l’établissement',
 'Effectif des candidats néo bacheliers technologiques en phase principale',
 'Effectif total des candidats ayant accepté la proposition de l’établissement (admis)',
 'Effectif total des candidats ayant reçu une proposition d’admission de la part de l’établissement']
[12]:
list_columns[90:120]
[12]:
['Effectif total des candidats classés par l’établissement en phase principale',
 'Effectif total des candidats en phase complémentaire',
 'Effectif total des candidats en phase principale',
 'Effectif total des candidats pour une formation',
 'Effectifs des autres candidats en phase complémentaire',
 'Filière de formation',
 'Filière de formation détaillée',
 'Filière de formation détaillée bis',
 'Filière de formation très agrégée',
 'Filière de formation très détaillée',
 'Filière de formation.1',
 'Lien de la formation sur la plateforme Parcoursup',
 'Part des terminales générales qui étaient en position de recevoir une proposition en phase principale',
 'Part des terminales professionnelles qui étaient en position de recevoir une proposition en phase principale',
 'Part des terminales technologiques qui étaient en position de recevoir une proposition en phase principale',
 'Rang du dernier appelé du groupe 1',
 'Rang du dernier appelé du groupe 2',
 'Rang du dernier appelé du groupe 3',
 'Regroupement 1 effectué par les formations pour les classements',
 'Regroupement 2 effectué par les formations pour les classements',
 'Regroupement 3 effectué par les formations pour les classements',
 'Région de l’établissement',
 'Session',
 'Statut de l’établissement de la filière de formation (public, privé…)',
 'Sélectivité',
 'Taux d’accès',
 'Taux d’accès des candidats ayant postulé à la formation (ratio entre le dernier appelé et le nombre vœux PP)',
 'cod_aff_form',
 'composante_id_paysage',
 'etablissement_id_paysage']
[13]:
list_columns[120:]
[13]:
['list_com', 'tri', 'Établissement']

Quelques explorations

Quelques variables.

[14]:
eff = df[
    [
        "Session",
        "Code UAI de l'établissement",
        "Établissement",
        "Sélectivité",
        "Filière de formation très agrégée",
        "Capacité de l’établissement par formation",
        "Effectif total des candidats pour une formation",
        "Effectif total des candidats en phase principale",
        "Effectif des autres candidats en phase principale",
        "Effectif total des candidats en phase complémentaire",
        "Effectifs des autres candidats en phase complémentaire",
        "Effectif total des candidats classés par l’établissement en phase principale",
        "Effectif des candidats classés par l’établissement en phase complémentaire",
        "% d’admis ayant reçu leur proposition d’admission avant la fin de la procédure principale",
        "% d’admis dont filles",
        "Rang du dernier appelé du groupe 1",
        "Rang du dernier appelé du groupe 2",
        "Rang du dernier appelé du groupe 3",
        "Concours communs et banque d'épreuves",
        "Taux d’accès",
    ]
]
[15]:
TableReport(eff)
Processing column  20 / 20
[15]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[16]:
capa = df[
    [
        "Session",
        "Code UAI de l'établissement",
        "Établissement",
        "Filière de formation très agrégée",
        "Capacité de l’établissement par formation",
        "Effectif total des candidats en phase principale",
    ]
]
TableReport(capa.sort_values("Établissement"))
Processing column   6 / 6
[16]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[17]:
piv = capa.pivot_table(
    index=[
        "Code UAI de l'établissement",
        "Établissement",
        "Filière de formation très agrégée",
    ],
    columns=["Session"],
    values=["Capacité de l’établissement par formation"],
)
TableReport(piv)
Processing column   5 / 5
[17]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[18]:
candidats = df[
    [
        "Session",
        "Code UAI de l'établissement",
        "Établissement",
        "Filière de formation très agrégée",
        "Effectif total des candidats pour une formation",
        "Capacité de l’établissement par formation",
    ]
]
TableReport(candidats.sort_values("Établissement"))
Processing column   6 / 6
[18]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[19]:
piv = candidats.pivot_table(
    index=[
        "Code UAI de l'établissement",
        "Établissement",
        "Filière de formation très agrégée",
    ],
    columns=["Session"],
    values=["Effectif total des candidats pour une formation"],
)
TableReport(piv)
Processing column   5 / 5
[19]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

Problème : prédire Effectif total des candidats pour une formation

On utilise une base réduite pour essayer de prédire la variable Effectif total des candidats pour une formation.

[83]:
variables = [
    "Région de l’établissement",
    "Session",
    "Statut de l’établissement de la filière de formation (public, privé…)",
    "Sélectivité",
    "Code UAI de l'établissement",
    "Établissement",
    "Filière de formation détaillée bis",
    "Filière de formation très agrégée",
    "Filière de formation.1",
    "Capacité de l’établissement par formation",
    "Effectif total des candidats pour une formation",
    "Académie de l’établissement",
    "Code départemental de l’établissement",
    "Commune de l’établissement",
    "Concours communs et banque d'épreuves",
]
table = df[variables]
TableReport(table)
Processing column  15 / 15
[83]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[84]:
keys = [
    "Région de l’établissement",
    "Session",
    "Statut de l’établissement de la filière de formation (public, privé…)",
    "Sélectivité",
    "Code UAI de l'établissement",
    "Établissement",
    "Filière de formation détaillée bis",
    "Filière de formation très agrégée",
    "Filière de formation.1",
    "Académie de l’établissement",
    "Code départemental de l’établissement",
    "Commune de l’établissement",
    "Concours communs et banque d'épreuves",
]
cible = "Effectif total des candidats pour une formation"
groups = df[[*keys, cible]].groupby(keys).count()
filtered = groups[groups[cible] > 1]
TableReport(filtered)
Processing column   1 / 1
[84]:

Please enable javascript

The skrub table reports need javascript to display correctly. If you are displaying a report in a Jupyter notebook and you see this message, you may need to re-execute the cell or to trust the notebook (button on the top right or "File > Trust notebook").

[71]:
mask = df.duplicated(subset=keys, keep=False)
table = df[~mask][[*keys, cible]]
table.dtypes
[71]:
Région de l’établissement                                                   str
Session                                                                   int64
Statut de l’établissement de la filière de formation (public, privé…)       str
Sélectivité                                                                 str
Code UAI de l'établissement                                                 str
Établissement                                                               str
Filière de formation détaillée bis                                          str
Filière de formation très agrégée                                           str
Filière de formation.1                                                      str
Académie de l’établissement                                                 str
Code départemental de l’établissement                                    object
Commune de l’établissement                                                  str
Concours communs et banque d'épreuves                                       str
Effectif total des candidats pour une formation                           int64
dtype: object
[72]:
table.shape
[72]:
(56990, 14)

Le point de départ : l’année précédente pour point de départ

[85]:
unique_keys = [
    "Code UAI de l'établissement",
    "Établissement",
    "Région de l’établissement",
    "Session",
    "Statut de l’établissement de la filière de formation (public, privé…)",
    "Sélectivité",
    "Filière de formation détaillée bis",
    "Filière de formation très agrégée",
    "Filière de formation.1",
    "Capacité de l’établissement par formation",
]

f2025 = table["Session"] == 2025
f2024 = table["Session"] == 2024
ftwo = table[f2025 | f2024]
piv = (
    pandas.pivot_table(
        ftwo,
        index=[c for c in unique_keys if c != "Session"],
        columns="Session",
        values=cible,
    )
    .dropna(axis=0)
    .sort_index()
)
piv
[85]:
Session 2024 2025
Code UAI de l'établissement Établissement Région de l’établissement Statut de l’établissement de la filière de formation (public, privé…) Sélectivité Filière de formation détaillée bis Filière de formation très agrégée Filière de formation.1 Capacité de l’établissement par formation
0010013J Lycée Lalande Auvergne-Rhône-Alpes Public formation sélective PCSI CPGE Classe préparatoire scientifique 48 937.0 957.0
0010014K Lycée Edgar Quinet Auvergne-Rhône-Alpes Public formation sélective Collaborateur juriste notarial BTS BTS - Services 24 515.0 408.0
ECG - Mathématiques appliquées + ESH CPGE Classe préparatoire économique et commerciale 25 425.0 457.0
ECG - Mathématiques appliquées + HGG CPGE Classe préparatoire économique et commerciale 15 321.0 334.0
Gestion de la PME BTS BTS - Services 30 411.0 512.0
... ... ... ... ... ... ... ... ... ... ...
9760363R Lycée Cité scolaire de Bandrélé Mayotte Public formation sélective Economie sociale familiale BTS BTS - Services 36 1197.0 1497.0
9760370Y Lycée des Lumières Mayotte Public formation sélective Assistance, conseil, vente à distance Autre formation Certificat de Spécialisation 29 426.0 636.0
Commerce International BTS BTS - Services 24 1237.0 1172.0
Gestion de la PME BTS BTS - Services 35 1585.0 1962.0
Support à l'action managériale BTS BTS - Services 35 1123.0 1080.0

9001 rows × 2 columns

[86]:
from sklearn.metrics import mean_absolute_error

mean_absolute_error(piv[2025], piv[2024])
[86]:
155.24428226509383

Un model simple

[90]:
X, y = table.drop(cible, axis=1), table[cible]

train_test = X["Session"] < 2025

drop = ["Session", "Code UAI de l'établissement", "Établissement"]

train_X = X[train_test].drop(drop, axis=1)
train_y = y[train_test]
test_X = X[train_test].drop(drop, axis=1)
test_y = y[train_test]
[91]:
train_X.shape
[91]:
(54988, 11)
[92]:
train_X.describe()
[92]:
Capacité de l’établissement par formation
count 54988.000000
mean 55.915709
std 103.765073
min 0.000000
25% 20.000000
50% 31.000000
75% 50.000000
max 3400.000000
[ ]:
num_cols = ["Capacité de l’établissement par formation"]
cat_cols = [c for c in unique_keys if c not in num_cols]

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.ensemble import HistGradientBoostingRegressor

model = Pipeline(
    [
        (
            "preprocessing",
            ColumnTransformer(
                [
                    ("num", StandardScaler(), num_cols),
                    ("cats", OneHotEncoder(handle_unknown="ignore"), cat_cols),
                ]
            ),
        ),
        ("regressor", HistGradientBoostingRegressor()),
    ]
)
model.fit(train_X, train_y)
/tmp/ipykernel_1056/1981098955.py:18: Pandas4Warning: For backward compatibility, 'str' dtypes are included by select_dtypes when 'object' dtype is specified. This behavior is deprecated and will be removed in a future version. Explicitly pass 'str' to `include` to select them, or to `exclude` to remove them and silence this warning.
See https://pandas.pydata.org/docs/user_guide/migration-3-strings.html#string-migration-select-dtypes for details on how to write code that works with pandas 2 and 3.
  train_X.select_dtypes(include=["object", "category"]).columns
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[95], line 24
      7 from sklearn.ensemble import HistGradientBoostingRegressor
      9 model = Pipeline([
     10     ("preprocessing",
     11      ColumnTransformer([
   (...)     22     ("regressor", HistGradientBoostingRegressor())
     23 ])
---> 24 model.fit(train_X, train_y)

File ~/vv/this312/lib/python3.12/site-packages/sklearn/base.py:1336, in _fit_context.<locals>.decorator.<locals>.wrapper(estimator, *args, **kwargs)
   1329     estimator._validate_params()
   1331 with config_context(
   1332     skip_parameter_validation=(
   1333         prefer_skip_nested_validation or global_skip_validation
   1334     )
   1335 ):
-> 1336     return fit_method(estimator, *args, **kwargs)

File ~/vv/this312/lib/python3.12/site-packages/sklearn/pipeline.py:613, in Pipeline.fit(self, X, y, **params)
    606     raise ValueError(
    607         "The `transform_input` parameter can only be set if metadata "
    608         "routing is enabled. You can enable metadata routing using "
    609         "`sklearn.set_config(enable_metadata_routing=True)`."
    610     )
    612 routed_params = self._check_method_params(method="fit", props=params)
--> 613 Xt = self._fit(X, y, routed_params, raw_params=params)
    614 with _print_elapsed_time("Pipeline", self._log_message(len(self.steps) - 1)):
    615     if self._final_estimator != "passthrough":

File ~/vv/this312/lib/python3.12/site-packages/sklearn/pipeline.py:547, in Pipeline._fit(self, X, y, routed_params, raw_params)
    540 # Fit or load from cache the current transformer
    541 step_params = self._get_metadata_for_step(
    542     step_idx=step_idx,
    543     step_params=routed_params[name],
    544     all_params=raw_params,
    545 )
--> 547 X, fitted_transformer = fit_transform_one_cached(
    548     cloned_transformer,
    549     X,
    550     y,
    551     weight=None,
    552     message_clsname="Pipeline",
    553     message=self._log_message(step_idx),
    554     params=step_params,
    555 )
    556 # Replace the transformer of the step with the fitted
    557 # transformer. This is necessary when loading the transformer
    558 # from the cache.
    559 self.steps[step_idx] = (name, fitted_transformer)

File ~/vv/this312/lib/python3.12/site-packages/joblib/memory.py:326, in NotMemorizedFunc.__call__(self, *args, **kwargs)
    325 def __call__(self, *args, **kwargs):
--> 326     return self.func(*args, **kwargs)

File ~/vv/this312/lib/python3.12/site-packages/sklearn/pipeline.py:1484, in _fit_transform_one(transformer, X, y, weight, message_clsname, message, params)
   1482 with _print_elapsed_time(message_clsname, message):
   1483     if hasattr(transformer, "fit_transform"):
-> 1484         res = transformer.fit_transform(X, y, **params.get("fit_transform", {}))
   1485     else:
   1486         res = transformer.fit(X, y, **params.get("fit", {})).transform(
   1487             X, **params.get("transform", {})
   1488         )

File ~/vv/this312/lib/python3.12/site-packages/sklearn/utils/_set_output.py:316, in _wrap_method_output.<locals>.wrapped(self, X, *args, **kwargs)
    314 @wraps(f)
    315 def wrapped(self, X, *args, **kwargs):
--> 316     data_to_wrap = f(self, X, *args, **kwargs)
    317     if isinstance(data_to_wrap, tuple):
    318         # only wrap the first output for cross decomposition
    319         return_tuple = (
    320             _wrap_data_with_container(method, data_to_wrap[0], X, self),
    321             *data_to_wrap[1:],
    322         )

File ~/vv/this312/lib/python3.12/site-packages/sklearn/base.py:1336, in _fit_context.<locals>.decorator.<locals>.wrapper(estimator, *args, **kwargs)
   1329     estimator._validate_params()
   1331 with config_context(
   1332     skip_parameter_validation=(
   1333         prefer_skip_nested_validation or global_skip_validation
   1334     )
   1335 ):
-> 1336     return fit_method(estimator, *args, **kwargs)

File ~/vv/this312/lib/python3.12/site-packages/sklearn/compose/_column_transformer.py:988, in ColumnTransformer.fit_transform(self, X, y, **params)
    986 X = _check_X(X)
    987 # set n_features_in_ attribute
--> 988 self._validate_transformers()
    989 n_samples = _num_samples(X)
    991 self._validate_column_callables(X)

File ~/vv/this312/lib/python3.12/site-packages/sklearn/compose/_column_transformer.py:513, in ColumnTransformer._validate_transformers(self)
    510 names, transformers, _ = zip(*self.transformers)
    512 # validate names
--> 513 self._validate_names(names)
    515 # validate estimators
    516 for t in transformers:

File ~/vv/this312/lib/python3.12/site-packages/sklearn/utils/metaestimators.py:88, in _BaseComposition._validate_names(self, names)
     87 def _validate_names(self, names):
---> 88     if len(set(names)) != len(names):
     89         raise ValueError("Names provided are not unique: {0!r}".format(list(names)))
     90     invalid_names = set(names).intersection(self.get_params(deep=False))

TypeError: unhashable type: 'list'
[ ]:


Notebook on github