{"id":1962,"date":"2026-10-14T18:00:46","date_gmt":"2026-10-14T18:00:46","guid":{"rendered":"http:\/\/french.arabpsychology.com\/statistics\/comment-calculer-la-mediane-dans-pandas-avec-exemples\/"},"modified":"2026-10-14T18:00:46","modified_gmt":"2026-10-14T18:00:46","slug":"comment-calculer-la-mediane-dans-pandas-avec-exemples","status":"publish","type":"psych_stat","link":"https:\/\/french.arabpsychology.com\/?psych_stat=comment-calculer-la-mediane-dans-pandas-avec-exemples","title":{"rendered":"Comment calculer la m\u00e9diane dans Pandas (avec exemples)"},"content":{"rendered":"<p>Dans le paysage contemporain de la science des donn\u00e9es et de l&rsquo;analyse computationnelle, l&rsquo;exploration rigoureuse des structures tabulaires constitue une \u00e9tape fondamentale pr\u00e9alable \u00e0 toute mod\u00e9lisation statistique ou pr\u00e9dictive. L&rsquo;\u00e9cosyst\u00e8me Python, soutenu par la biblioth\u00e8que open source <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/\">Pandas<\/a>, s&rsquo;est impos\u00e9 comme l&rsquo;environnement d&rsquo;ing\u00e9nierie de r\u00e9f\u00e9rence pour les chercheurs, statisticiens et analystes de donn\u00e9es \u00e0 travers le monde. Au c\u0153ur de cette biblioth\u00e8que matricielle, le traitement des m\u00e9triques descriptives exige une compr\u00e9hension pointue des propri\u00e9t\u00e9s math\u00e9matiques fondamentales et des comportements algorithmiques sous-jacents, particuli\u00e8rement lorsqu&rsquo;il s&rsquo;agit d&rsquo;\u00e9valuer la distribution et la tendance centrale d&rsquo;\u00e9chantillons complexes.<\/p>\n<p>Si la moyenne arithm\u00e9tique demeure historiquement la statistique la plus fr\u00e9quemment mobilis\u00e9e lors des phases exploratoires, son incapacit\u00e9 structurelle \u00e0 r\u00e9sister aux perturbations induites par les valeurs aberrantes et les asym\u00e9tries de distribution limite drastiquement sa pertinence empirique. Dans les protocoles de recherche rigoureux, la m\u00e9diane s&rsquo;affirme comme une mesure de substitution ou de compl\u00e9ment indispensable, offrant une robustesse exceptionnelle face aux art\u00e9facts observationnels. La m\u00e9thode d\u00e9di\u00e9e int\u00e9gr\u00e9e \u00e0 Pandas, encapsul\u00e9e sous la fonction membre <em>median()<\/em>, offre une flexibilit\u00e9 technique et une efficacit\u00e9 computationnelle consid\u00e9rables, \u00e0 la condition expresse d&rsquo;en ma\u00eetriser l&rsquo;architecture, les param\u00e8tres et les nuances d&rsquo;ex\u00e9cution.<\/p>\n<p>Le pr\u00e9sent trait\u00e9 propose une d\u00e9composition exhaustive et m\u00e9thodologique du calcul de la m\u00e9diane au sein des structures de donn\u00e9es Pandas, notamment les s\u00e9ries unidimensionnelles et les DataFrames multidimensionnels. Depuis les justifications th\u00e9oriques issues de la statistique non param\u00e9trique jusqu&rsquo;aux architectures de pipelines d&rsquo;imputation et d&rsquo;agr\u00e9gation conditionnelle de haut niveau, cette \u00e9tude d\u00e9taille l&rsquo;ensemble des m\u00e9canismes op\u00e9ratoires n\u00e9cessaires pour manipuler, optimiser et interpr\u00e9ter les valeurs m\u00e9dianes dans le strict respect des standards de reproductibilit\u00e9 et de rigueur scientifique.<\/p>\n<h2>1. Fondements th\u00e9oriques et importance statistique de la m\u00e9diane<\/h2>\n<h3>1.1 D\u00e9finition math\u00e9matique et comparaison avec la moyenne<\/h3>\n<p>D&rsquo;un point de vue strictement math\u00e9matique et formel, la m\u00e9diane d&rsquo;une variable al\u00e9atoire r\u00e9elle ou d&rsquo;une s\u00e9rie statistique ordonn\u00e9e correspond \u00e0 la valeur s\u00e9paratrice qui partitionne l&rsquo;\u00e9chantillon en deux sous-ensembles de cardinalit\u00e9s rigoureusement \u00e9quivalentes. Si l&rsquo;on consid\u00e8re un ensemble fini de <span class=\"arabpsy-math-inline\" data-latex=\"n\">$n$<\/span> observations quantitatives r\u00e9ordonn\u00e9es selon une relation d&rsquo;ordre croissant, not\u00e9es sous la forme de statistiques d&rsquo;ordre <span class=\"arabpsy-math-inline\" data-latex=\"X_{(1)} le X_{(2)} le dots le X_{(n)}\">$X_{(1)} le X_{(2)} le dots le X_{(n)}$<\/span>, la m\u00e9diane correspond au point d&rsquo;\u00e9valuation o\u00f9 la fonction de r\u00e9partition empirique atteint ou d\u00e9passe le seuil de 0,5. En d&rsquo;autres termes, au moins cinquante pour cent des observations observ\u00e9es sont inf\u00e9rieures ou \u00e9gales \u00e0 cette valeur, et au moins cinquante pour cent lui sont sup\u00e9rieures ou \u00e9gales.<\/p>\n<p>Cette approche positionnelle se distingue radicalement de la d\u00e9finition de la moyenne arithm\u00e9tique, laquelle correspond au centre de gravit\u00e9 barycentrique des donn\u00e9es, calcul\u00e9 en divisant la somme arithm\u00e9tique de toutes les valeurs par la taille globale de l&rsquo;\u00e9chantillon. Sur le plan de la th\u00e9orie de l&rsquo;optimisation, la moyenne arithm\u00e9tique constitue l&rsquo;estimateur qui minimise la somme des carr\u00e9s des d\u00e9viations, correspondant formellement \u00e0 la minimisation de la norme <span class=\"arabpsy-math-inline\" data-latex=\"L_2\">$L_2$<\/span>. \u00c0 l&rsquo;inverse, la m\u00e9diane g\u00e9om\u00e9trique ou univari\u00e9e correspond \u00e0 la valeur qui minimise la somme des \u00e9carts absolus, r\u00e9pondant ainsi au principe de minimisation de la norme <span class=\"arabpsy-math-inline\" data-latex=\"L_1\">$L_1$<\/span>. Cette divergence fondamentale explique pourquoi la moyenne r\u00e9agit de mani\u00e8re disproportionn\u00e9e aux valeurs atypiques, chaque \u00e9cart \u00e9tant \u00e9lev\u00e9 au carr\u00e9 dans la fonction de perte associ\u00e9e.<\/p>\n<p>L&rsquo;avantage d\u00e9cisif de la m\u00e9diane dans la recherche scientifique r\u00e9side dans son <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Statistique_robuste\">point de rupture<\/a> (ou <em>breakdown point<\/em>), qui est une mesure classique de la robustesse statistique. Le point de rupture de la m\u00e9diane univari\u00e9e atteint 50 %, ce qui signifie qu&rsquo;il faut corrompre ou d\u00e9placer vers l&rsquo;infini au moins la moiti\u00e9 des observations d&rsquo;un \u00e9chantillon pour provoquer une d\u00e9rive infinie de la valeur m\u00e9diane. En comparaison directe, le point de rupture de la moyenne arithm\u00e9tique est de <span class=\"arabpsy-math-inline\" data-latex=\"1\/n\">$1\/n$<\/span>, tendant vers 0 % \u00e0 mesure que la taille de l&rsquo;\u00e9chantillon augmente. Une seule observation pathologique ou une erreur typographique d&rsquo;acquisition peut ainsi fausser arbitrairement une moyenne arithm\u00e9tique, tandis que la m\u00e9diane demeure parfaitement stable et repr\u00e9sentative du corps central des donn\u00e9es analys\u00e9es.<\/p>\n<h3>1.2 Pertinence de la m\u00e9diane dans l&rsquo;analyse de donn\u00e9es exp\u00e9rimentales<\/h3>\n<p>Dans le domaine des sciences exp\u00e9rimentales, \u00e0 l&rsquo;instar des neurosciences cognitives, de la psychom\u00e9trie, de la chronom\u00e9trie mentale ou de la biologie quantitative, les donn\u00e9es r\u00e9colt\u00e9es ne suivent que tr\u00e8s rarement une loi normale pure ou une distribution parfaitement gaussienne. Par exemple, la mesure des temps de r\u00e9action lors d&rsquo;\u00e9preuves de discrimination perceptive g\u00e9n\u00e8re de mani\u00e8re quasi syst\u00e9matique des distributions asym\u00e9triques positives, fr\u00e9quemment mod\u00e9lis\u00e9es par des distributions ex-gaussiennes, log-normales ou des lois de Wald. L&rsquo;observation de ces latences r\u00e9v\u00e8le une longue tra\u00eene vers les valeurs temporelles \u00e9lev\u00e9es, due \u00e0 des laps d&rsquo;attention transitoires, des d\u00e9faillances de capteurs ou des micro-r\u00e9veils cognitifs.<\/p>\n<p>Le recours \u00e0 la moyenne arithm\u00e9tique dans ces contextes exp\u00e9rimentaux induit un biais d&rsquo;estimation s\u00e9v\u00e8re, d\u00e9pla\u00e7ant artificiellement le centre de la distribution vers la droite et masquant la performance motrice ou cognitive r\u00e9elle du sujet test\u00e9. L&rsquo;exploitation de la m\u00e9diane permet de s&rsquo;affranchir de cette distorsion structurelle en isolant le point de bascule de la densit\u00e9 de probabilit\u00e9 sans accorder un poids d\u00e9mesur\u00e9 aux latences extr\u00eames. Ainsi, la validit\u00e9 interne du protocole exp\u00e9rimental est rigoureusement pr\u00e9serv\u00e9e, \u00e9liminant la n\u00e9cessit\u00e9 souvent arbitraire d&rsquo;\u00e9laguer manuellement les observations p\u00e9riph\u00e9riques selon des seuils de troncature discutables.<\/p>\n<p>Par ailleurs, au sein de populations h\u00e9t\u00e9rog\u00e8nes compos\u00e9es de plusieurs sous-groupes non identifi\u00e9s ou pr\u00e9sentant une variance non constante, l&rsquo;inf\u00e9rence statistique repose de mani\u00e8re croissante sur des protocoles non param\u00e9triques. La m\u00e9diane s&rsquo;impose alors comme l&rsquo;estimateur de tendance centrale privil\u00e9gi\u00e9, autorisant des comparaisons inter-groupes l\u00e9gitimes sans requ\u00e9rir d&rsquo;hypoth\u00e8ses inv\u00e9rifiables relatives \u00e0 l&rsquo;homosc\u00e9dasticit\u00e9 ou \u00e0 la sym\u00e9trie de la dispersion des r\u00e9sidus. Dans les essais cliniques, les dur\u00e9es de survie ou de r\u00e9mission constituent \u00e9galement un arch\u00e9type o\u00f9 la pr\u00e9sence de censure \u00e0 droite rend la moyenne incalculable ou biais\u00e9e, tandis que la m\u00e9diane de survie demeure calculable avec une remarquable exactitude.<\/p>\n<h3>1.3 Algorithmes de calcul du rang m\u00e9dian pour effectifs pairs et impairs<\/h3>\n<p>Le calcul effectif de la m\u00e9diane d\u00e9pend formellement de la parit\u00e9 de l&rsquo;effectif total <span class=\"arabpsy-math-inline\" data-latex=\"n\">$n$<\/span> de la s\u00e9rie statistique consid\u00e9r\u00e9e. Lorsque l&rsquo;\u00e9chantillon comprend un effectif impair, c&rsquo;est-\u00e0-dire lorsque <span class=\"arabpsy-math-inline\" data-latex=\"n = 2k + 1\">$n = 2k + 1$<\/span> pour un entier <span class=\"arabpsy-math-inline\" data-latex=\"k ge 0\">$k ge 0$<\/span>, la d\u00e9termination du rang m\u00e9dian est directe et non ambigu\u00eb. Apr\u00e8s avoir proc\u00e9d\u00e9 au tri ordonn\u00e9 des donn\u00e9es selon la s\u00e9quence <span class=\"arabpsy-math-inline\" data-latex=\"X_{(1)}, X_{(2)}, dots, X_{(2k+1)}\">$X_{(1)}, X_{(2)}, dots, X_{(2k+1)}$<\/span>, la m\u00e9diane correspond exactement \u00e0 l&rsquo;\u00e9l\u00e9ment central index\u00e9 par la position d&rsquo;ordre <span class=\"arabpsy-math-inline\" data-latex=\"(n + 1) \/ 2\">$(n + 1) \/ 2$<\/span>, soit formellement :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\text{M\u00e9diane} = X_{(k+1)}\">$$\\text{M\u00e9diane} = X_{(k+1)}$$<\/span><\/p>\n<p>Cette observation unique divise m\u00e9caniquement la distribution en deux segments rigoureusement sym\u00e9triques contenant chacun <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span> observations de part et d&rsquo;autre de la valeur pivot.<\/p>\n<p>En revanche, lorsque la s\u00e9rie statistique comporte un effectif pair, tel que <span class=\"arabpsy-math-inline\" data-latex=\"n = 2k\">$n = 2k$<\/span> pour <span class=\"arabpsy-math-inline\" data-latex=\"k ge 1\">$k ge 1$<\/span>, il n&rsquo;existe pas d&rsquo;\u00e9l\u00e9ment d&rsquo;observation unique occupant le centre arithm\u00e9tique de la distribution ordonn\u00e9e. Dans ce cas de figure, toute valeur comprise dans l&rsquo;intervalle ferm\u00e9 d\u00e9limit\u00e9 par les deux valeurs centrales, \u00e0 savoir <span class=\"arabpsy-math-inline\" data-latex=\"[X_{(k)}, X_{(k+1)}]\">$[X_{(k)}, X_{(k+1)}]$<\/span>, r\u00e9pond formellement aux crit\u00e8res th\u00e9oriques de la d\u00e9finition d&rsquo;une valeur s\u00e9paratrice m\u00e9diane. Afin d&rsquo;\u00e9liminer cette ind\u00e9termination dans les calculs d\u00e9terministes, la convention statistique internationale standard consiste \u00e0 op\u00e9rer une interpolation arithm\u00e9tique lin\u00e9aire en calculant la demi-somme des deux observations centrales :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\text{M\u00e9diane} = \\frac{X_{(k)} + X_{(k+1)}}{2}\">$$\\text{M\u00e9diane} = \\frac{X_{(k)} + X_{(k+1)}}{2}$$<\/span><\/p>\n<p>Sur le plan algorithmique sous-jacent, le traitement automatis\u00e9 de ce calcul au sein des biblioth\u00e8ques informatiques comme <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/\">NumPy<\/a> et Pandas n&rsquo;ex\u00e9cute g\u00e9n\u00e9ralement pas un tri exhaustif complet de complexit\u00e9 <span class=\"arabpsy-math-inline\" data-latex=\"O(n log n)\">$O(n log n)$<\/span> via Quicksort ou Timsort. Pour des raisons d&rsquo;optimisation computationnelle, les moteurs d&rsquo;ex\u00e9cution recourent plut\u00f4t \u00e0 des algorithmes de s\u00e9lection partielle fond\u00e9s sur le principe de <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Quickselect\">Quickselect<\/a> ou d&rsquo;Introselect, dont la complexit\u00e9 moyenne asymptotique est lin\u00e9aire, soit <span class=\"arabpsy-math-inline\" data-latex=\"O(n)\">$O(n)$<\/span>. L&rsquo;algorithme partitionne la structure de donn\u00e9es autour de pivots successifs jusqu&rsquo;\u00e0 ce que les rangs index\u00e9s <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"k+1\">$k+1$<\/span> soient localis\u00e9s, minimisant ainsi les op\u00e9rations de comparaison en m\u00e9moire vive.<\/p>\n<h2>2. Architecture et signature de la m\u00e9thode median() dans Pandas<\/h2>\n<h3>2.1 Structure syntaxique et param\u00e8tres fondamentaux<\/h3>\n<p>Dans l&rsquo;\u00e9cosyst\u00e8me architectural de Pandas, le calcul de la m\u00e9diane est impl\u00e9ment\u00e9 nativement au sein des classes fondamentales <em>Series<\/em> et <em>DataFrame<\/em>. Cette m\u00e9thode partage une signature normalis\u00e9e destin\u00e9e \u00e0 assurer l&rsquo;uniformit\u00e9 des interfaces de programmation applicative de la biblioth\u00e8que. Pour une structure tabulaire \u00e0 deux dimensions, la signature canonique de la fonction s&rsquo;articule comme suit :<\/p>\n<p><code>DataFrame.median(axis=0, skipna=True, numeric_only=False, **kwargs)<\/code><\/p>\n<p>Pour une structure unidimensionnelle du type <em>Series<\/em>, la signature est all\u00e9g\u00e9e des param\u00e8tres structurels non pertinents, se r\u00e9sumant principalement aux arguments <em>axis<\/em> et <em>skipna<\/em> :<\/p>\n<p><code>Series.median(axis=0, skipna=True, numeric_only=False, **kwargs)<\/code><\/p>\n<p>L&rsquo;argument <em>axis<\/em> d\u00e9finit la direction vectorielle de la r\u00e9duction statistique, tandis que <em>skipna<\/em> contr\u00f4le rigoureusement le comportement algorithmique adopt\u00e9 face aux valeurs manquantes ou non d\u00e9finies. Le param\u00e8tre <em>numeric_only<\/em> d\u00e9termine si les colonnes ou entr\u00e9es non quantitatives doivent \u00eatre \u00e9cart\u00e9es de l&rsquo;\u00e9valuation ou soumises \u00e0 une tentative d&rsquo;agr\u00e9gation. L&rsquo;ex\u00e9cution de cette m\u00e9thode sur une <em>Series<\/em> produit par d\u00e9faut un scalaire de type num\u00e9rique, usuellement instanci\u00e9 comme un flottant standard de pr\u00e9cision double <em>numpy.float64<\/em>, m\u00eame si les donn\u00e9es sous-jacentes sont originellement encod\u00e9es sous forme d&rsquo;entiers. Lorsqu&rsquo;elle est appliqu\u00e9e \u00e0 un <em>DataFrame<\/em> complet, la fonction r\u00e9alise une op\u00e9ration de r\u00e9duction dimensionnelle renvoyant une nouvelle <em>Series<\/em> dont l&rsquo;index correspond aux \u00e9tiquettes des axes agr\u00e9g\u00e9s.<\/p>\n<p>L&rsquo;\u00e9volution interne de Pandas, notamment lors du passage pivot de la branche 1.x vers la version majeure Pandas 2.0, a entra\u00een\u00e9 des modifications majeures dans la typologie des objets renvoy\u00e9s et la gestion des types de donn\u00e9es sous-jacents. L&rsquo;introduction formelle du support natif du moteur <a rel=\"noopener noreferrer\" href=\"https:\/\/arrow.apache.org\/\">Apache Arrow<\/a> et des types nullables int\u00e9gr\u00e9s (comme les entiers <em>Int64<\/em> ou les bool\u00e9ens <em>boolean<\/em>) permet d\u00e9sormais \u00e0 la m\u00e9thode d&rsquo;op\u00e9rer sans conversion implicite syst\u00e9matique vers les structures de stockage C-array de NumPy, garantissant une int\u00e9grit\u00e9 accrue des m\u00e9tadonn\u00e9es typ\u00e9es lors des r\u00e9ductions statistiques.<\/p>\n<h3>2.2 Comportement du param\u00e8tre numeric_only<\/h3>\n<p>Le param\u00e8tre bool\u00e9en <em>numeric_only<\/em> constitue un m\u00e9canisme de contr\u00f4le essentiel pour garantir la stabilit\u00e9 des cha\u00eenes de traitement automatis\u00e9es. Historiquement, dans les versions ant\u00e9rieures de Pandas, ce param\u00e8tre \u00e9tait positionn\u00e9 implicitement \u00e0 <em>None<\/em> ou <em>True<\/em>, ce qui incitait le moteur d&rsquo;ex\u00e9cution \u00e0 ignorer silencieusement toutes les colonnes contenant des cha\u00eenes de caract\u00e8res, des objets arbitraires ou des dates non convertibles lors d&rsquo;une tentative de calcul d&rsquo;agr\u00e9gation globale sur une table h\u00e9t\u00e9rog\u00e8ne.<\/p>\n<p>Cependant, cette conversion implicite a \u00e9t\u00e9 identifi\u00e9e comme une source majeure d&rsquo;effets de bord, masquant souvent des anomalies graves dans la structure des sch\u00e9mas de donn\u00e9es, comme des valeurs num\u00e9riques accidentellement stock\u00e9es sous forme de cha\u00eenes de texte. En cons\u00e9quence, les versions modernes de Pandas imposent une politique beaucoup plus stricte. L&rsquo;omission d\u00e9lib\u00e9r\u00e9e de <em>numeric_only=True<\/em> lors de l&rsquo;appel de <em>df.median()<\/em> sur un <em>DataFrame<\/em> comportant des types non num\u00e9riques engendre d\u00e9sormais une lev\u00e9e d&rsquo;avertissement de type <em>FutureWarning<\/em>, et dans les configurations strictes r\u00e9centes, une exception explicite de type <em>TypeError<\/em> signalant l&rsquo;impossibilit\u00e9 d&rsquo;\u00e9valuer la m\u00e9diane sur des donn\u00e9es nominales ou textuelles.<\/p>\n<p>Afin de concevoir des scripts p\u00e9rennes, reproductibles et conformes aux meilleures pratiques de d\u00e9veloppement logiciel, il est fortement prescrit de d\u00e9clarer explicitement la valeur de ce param\u00e8tre. La fixation syst\u00e9matique de <em>numeric_only=True<\/em> indique formellement \u00e0 l&rsquo;interpr\u00e9teur de filtrer en amont la matrice d&rsquo;entr\u00e9e en ne conservant que les repr\u00e9sentations binaires d&rsquo;entiers, de flottants et de bool\u00e9ens, \u00e9vitant ainsi toute interruption intempestive du flux de travail statistique lors de l&rsquo;int\u00e9gration de nouvelles variables qualitatives.<\/p>\n<h3>2.3 Gestion de la dimensionnalit\u00e9 avec le param\u00e8tre axis<\/h3>\n<p>L&rsquo;argument <em>axis<\/em> r\u00e9git l&rsquo;orientation spatiale de l&rsquo;op\u00e9ration de r\u00e9duction dimensionnelle appliqu\u00e9e \u00e0 la matrice de donn\u00e9es. Par construction conventionnelle dans l&rsquo;alg\u00e8bre de Pandas, l&rsquo;axe index\u00e9 0, d\u00e9sign\u00e9 de mani\u00e8re \u00e9quivalente par <em>axis=0<\/em> ou la cha\u00eene s\u00e9mantique <em>axis=&rsquo;index&rsquo;<\/em>, sp\u00e9cifie un calcul vertical. Dans cette configuration, l&rsquo;algorithme parcourt les lignes pour chaque colonne de fa\u00e7on ind\u00e9pendante. Le r\u00e9sultat d&rsquo;une telle op\u00e9ration collapse la dimension des lignes pour produire une synth\u00e8se univari\u00e9e par colonne, ce qui constitue le cas d&rsquo;usage pr\u00e9dominant dans l&rsquo;exploration de tableaux o\u00f9 les colonnes repr\u00e9sentent des variables exp\u00e9rimentales distinctes et les lignes repr\u00e9sentent des observations ou des sujets individuels.<\/p>\n<p>\u00c0 l&rsquo;oppos\u00e9, l&rsquo;assignation de <em>axis=1<\/em> ou <em>axis=&rsquo;columns&rsquo;<\/em> d\u00e9clenche un calcul horizontal. Le moteur it\u00e8re alors \u00e0 travers les colonnes pour chaque ligne de la structure tabulaire. Cette modalit\u00e9 trouve son utilit\u00e9 dans les analyses de profils intra-individuels, par exemple lorsque plusieurs colonnes capturent des mesures r\u00e9p\u00e9t\u00e9es ou des r\u00e9plicats techniques d&rsquo;un m\u00eame ph\u00e9nom\u00e8ne pour une entit\u00e9 donn\u00e9e. La sortie g\u00e9n\u00e9r\u00e9e correspond alors \u00e0 un vecteur unidimensionnel dont la longueur \u00e9quivaut pr\u00e9cis\u00e9ment au nombre de lignes du <em>DataFrame<\/em> originel.<\/p>\n<p>La compr\u00e9hension rigoureuse de ce param\u00e8tre est primordiale pour pr\u00e9venir les erreurs d&rsquo;alignement d&rsquo;index lors des \u00e9tapes de r\u00e9assignation. L&rsquo;insertion du r\u00e9sultat d&rsquo;un calcul horizontal (axis=1) dans une nouvelle colonne du <em>DataFrame<\/em> s&rsquo;effectue sans heurts en raison de la concordance parfaite des index de lignes. En revanche, tenter de r\u00e9injecter un r\u00e9sultat vertical (axis=0) sans transposition pr\u00e9alable engendre des incoh\u00e9rences dimensionnelles ou la g\u00e9n\u00e9ration de valeurs manquantes dues aux m\u00e9canismes d&rsquo;alignement automatique propres \u00e0 Pandas.<\/p>\n<h2>3. Configuration de l&rsquo;environnement et cr\u00e9ation du jeu de donn\u00e9es exp\u00e9rimental<\/h2>\n<h3>3.1 Initialisation du DataFrame d&rsquo;\u00e9tude<\/h3>\n<p>Pour illustrer de mani\u00e8re concr\u00e8te l&rsquo;ensemble des m\u00e9canismes algorithmiques d\u00e9crits pr\u00e9c\u00e9demment, il convient de d\u00e9finir un environnement de travail contr\u00f4l\u00e9 et reproductible. Nous construisons \u00e0 cet effet un <em>DataFrame<\/em> repr\u00e9sentant les r\u00e9sultats d&rsquo;une cohorte exp\u00e9rimentale soumise \u00e0 des \u00e9preuves d&rsquo;\u00e9valuation cognitive et comportementale. Ce jeu de donn\u00e9es fictif mais repr\u00e9sentatif int\u00e8gre d\u00e9lib\u00e9r\u00e9ment des m\u00e9triques h\u00e9t\u00e9rog\u00e8nes, des \u00e9carts d&rsquo;\u00e9chelle significatifs ainsi qu&rsquo;une perturbation structurelle sous la forme d&rsquo;une valeur manquante.<\/p>\n<p>Consid\u00e9rons l&rsquo;initialisation du tableau de donn\u00e9es structur\u00e9 \u00e0 travers l&rsquo;extrait op\u00e9rationnel suivant :<\/p>\n<p><code>import numpy as np<br \/>\nimport pandas as pd<\/p>\n<p>donnees_experimentales = {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'identifiant': ['SUBJ_01', 'SUBJ_02', 'SUBJ_03', 'SUBJ_04', 'SUBJ_05', 'SUBJ_06'],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'groupe': ['Controle', 'Controle', 'Controle', 'Traitement', 'Traitement', 'Traitement'],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'temps_reaction_ms': [245.0, 312.0, 215.0, 230.0, 278.0, 480.0],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'score_attention': [88, 76, 94, 91, np.nan, 62],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'erreurs_comptabilisees': [2, 5, 1, 0, 3, 12]<br \/>\n}<\/p>\n<p>df = pd.DataFrame(donnees_experimentales)<\/code><\/p>\n<p>Dans ce mod\u00e8le matriciel, nous disposons de six observations exp\u00e9rimentales r\u00e9parties entre un groupe contr\u00f4le et un groupe recevant une intervention. Deux variables continues fondamentales sont enregistr\u00e9es : la latence de r\u00e9ponse motrice exprim\u00e9e en millisecondes (&lsquo;temps_reaction_ms&rsquo;) et un score synth\u00e9tique d&rsquo;attention soutenue (&lsquo;score_attention&rsquo;). Une variable discr\u00e8te de comptage d\u00e9nombre les d\u00e9faillances commises lors de la t\u00e2che (&lsquo;erreurs_comptabilisees&rsquo;). L&rsquo;introduction intentionnelle de l&rsquo;\u00e9l\u00e9ment <em>np.nan<\/em> au sein de la cinqui\u00e8me observation de la m\u00e9trique attentionnelle mod\u00e9lise fid\u00e8lement les r\u00e9alit\u00e9s de terrain, o\u00f9 les pannes d&rsquo;appareillage ou les abandons de sujets cr\u00e9ent des discontinuit\u00e9s dans les matrices d&rsquo;observation.<\/p>\n<h3>3.2 V\u00e9rification des distributions et coh\u00e9rence des variables<\/h3>\n<p>Pr\u00e9alablement \u00e0 toute extraction de m\u00e9triques descriptives, l&rsquo;inspection minutieuse de la coh\u00e9rence interne du sch\u00e9ma de donn\u00e9es repr\u00e9sente une exigence m\u00e9thodologique absolue. L&rsquo;ex\u00e9cution de la m\u00e9thode diagnostique <em>df.info()<\/em> permet d&rsquo;\u00e9valuer la compl\u00e9tude des colonnes ainsi que le typage m\u00e9moire affect\u00e9 par l&rsquo;interpr\u00e9teur de Pandas lors de l&rsquo;instanciation de la structure.<\/p>\n<p>L&rsquo;inspection r\u00e9v\u00e8le imm\u00e9diatement que la variable &lsquo;identifiant&rsquo; et la variable factorielle &lsquo;groupe&rsquo; sont stock\u00e9es sous le type g\u00e9n\u00e9rique <em>object<\/em> (ou sous le type <em>string<\/em> si les extensions modernes sont activ\u00e9es). Les colonnes &lsquo;temps_reaction_ms&rsquo; et &lsquo;score_attention&rsquo; sont classifi\u00e9es comme <em>float64<\/em> en raison de la pr\u00e9sence de nombres d\u00e9cimaux et de la valeur non d\u00e9finie <em>NaN<\/em>, cette derni\u00e8re \u00e9tant intrins\u00e8quement d\u00e9finie selon la norme <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/IEEE_754\">IEEE 754<\/a> comme une entit\u00e9 flottante. Enfin, la variable &lsquo;erreurs_comptabilisees&rsquo; est encod\u00e9e comme <em>int64<\/em>.<\/p>\n<p>Une observation qualitative de ces grandeurs met en exergue des divergences d&rsquo;\u00e9chelle et d&rsquo;asym\u00e9trie notables. La sixi\u00e8me observation (&lsquo;SUBJ_06&rsquo;) pr\u00e9sente un temps de r\u00e9action particuli\u00e8rement long de 480,0 millisecondes et un total d&rsquo;erreurs \u00e9lev\u00e9 \u00e0 12, contrastant fortement avec les scores enregistr\u00e9s sur le reste de la cohorte. Cette observation p\u00e9riph\u00e9rique d\u00e9montre parfaitement la vuln\u00e9rabilit\u00e9 d&rsquo;une moyenne arithm\u00e9tique globale et justifie l&rsquo;application imm\u00e9diate de la m\u00e9diane pour capturer le barycentre m\u00e9dian de la population exp\u00e9rimentale sans alt\u00e9ration de perspective.<\/p>\n<h2>4. Calcul de la m\u00e9diane pour une colonne unique<\/h2>\n<h3>4.1 Extraction sur une structure Series isol\u00e9e<\/h3>\n<p>L&rsquo;op\u00e9ration la plus \u00e9l\u00e9mentaire en analyse univari\u00e9e consiste \u00e0 extraire une unique colonne du tableau pour en quantifier la tendance centrale. Dans l&rsquo;architecture Pandas, la s\u00e9lection d&rsquo;une colonne singuli\u00e8re via l&rsquo;op\u00e9rateur d&rsquo;indexation par crochets retourne une structure <em>Series<\/em>. L&rsquo;application de la m\u00e9thode <em>median()<\/em> s&rsquo;effectue alors directement en aval de cette extraction vectorielle :<\/p>\n<p><code>mediane_tr = df['temps_reaction_ms'].median()<br \/>\nprint(mediane_tr)<\/code><\/p>\n<p>L&rsquo;ex\u00e9cution de cette commande renvoie la valeur scalaire <em>237.5<\/em>. L&rsquo;analyse du type de donn\u00e9es via la fonction native <em>type(mediane_tr)<\/em> confirme que l&rsquo;entit\u00e9 produite appartient \u00e0 la classe <em>numpy.float64<\/em>. Ce comportement atteste de l&rsquo;interop\u00e9rabilit\u00e9 directe entre Pandas et le socle scientifique NumPy, permettant l&rsquo;injection imm\u00e9diate de ce r\u00e9sultat dans d&rsquo;autres modules analytiques tels que SciPy, Scikit-Learn ou Matplotlib.<\/p>\n<p>Pour comprendre rigoureusement l&rsquo;origine arithm\u00e9tique de cette valeur de 237,5, il convient de retracer manuellement l&rsquo;algorithme sous-jacent. La colonne &lsquo;temps_reaction_ms&rsquo; contient six observations valides, d\u00e9finissant un effectif pair (<span class=\"arabpsy-math-inline\" data-latex=\"n = 6\">$n = 6$<\/span>). La s\u00e9quence originelle des valeurs est : [245.0, 312.0, 215.0, 230.0, 278.0, 480.0]. L&rsquo;algorithme op\u00e8re dans un premier temps le tri ordonn\u00e9 croissant de la s\u00e9rie, produisant le vecteur statistique suivant :<\/p>\n<p>[215.0, 230.0, 245.0, 278.0, 312.0, 480.0]<\/p>\n<p>L&rsquo;effectif total \u00e9tant pair, la m\u00e9diane ne correspond pas \u00e0 un \u00e9l\u00e9ment physique pr\u00e9existant, mais \u00e0 l&rsquo;interpolation lin\u00e9aire arithm\u00e9tique des deux valeurs occupant les rangs centraux <span class=\"arabpsy-math-inline\" data-latex=\"k = 6\/2 = 3\">$k = 6\/2 = 3$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"k+1 = 4\">$k+1 = 4$<\/span>. Ces observations centrales sont <span class=\"arabpsy-math-inline\" data-latex=\"X_{(3)} = 245.0\">$X_{(3)} = 245.0$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"X_{(4)} = 278.0\">$X_{(4)} = 278.0$<\/span>. Le calcul ex\u00e9cut\u00e9 par Pandas \u00e9quivaut donc rigoureusement \u00e0 :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\text{M\u00e9diane} = \\frac{245.0 + 278.0}{2} = \\frac{523.0}{2} = 237.5\">$$\\text{M\u00e9diane} = \\frac{245.0 + 278.0}{2} = \\frac{523.0}{2} = 237.5$$<\/span><\/p>\n<p>Cet exemple met en \u00e9vidence la pr\u00e9cision de l&rsquo;interpolation num\u00e9rique, qui produit un r\u00e9sultat rationnel repr\u00e9sentatif du centre de masse sans \u00eatre d\u00e9form\u00e9 par l&rsquo;extr\u00eame sup\u00e9rieur de 480,0.<\/p>\n<h3>4.2 Indexation par attribut versus indexation par crochets<\/h3>\n<p>Sur le plan de l&rsquo;\u00e9criture du code Python, il existe deux approches syntaxiques concurrentes pour extraire une colonne sp\u00e9cifique avant d&rsquo;en calculer la m\u00e9diane : l&rsquo;acc\u00e8s par attribut de classe et l&rsquo;acc\u00e8s par indexation textuelle \u00e0 l&rsquo;aide de crochets.<\/p>\n<p>La syntaxe par attribut se pr\u00e9sente sous la forme concise <em>df.temps_reaction_ms.median()<\/em>. Bien que s\u00e9duisante par sa concision et sa ressemblance avec la notation orient\u00e9e objet traditionnelle, cette notation comporte de graves faiblesses techniques. Premi\u00e8rement, elle \u00e9choue syst\u00e9matiquement d\u00e8s lors que le nom de la variable contient des espaces, des caract\u00e8res r\u00e9serv\u00e9s ou des ponctuations non autoris\u00e9es dans les identifiants Python. Deuxi\u00e8mement, et plus insidieusement, elle cr\u00e9e des collisions d&rsquo;espace de noms critiques si le nom d&rsquo;une variable co\u00efncide avec une m\u00e9thode native pr\u00e9d\u00e9finie de la classe <em>DataFrame<\/em> (telle que <em>count<\/em>, <em>min<\/em>, <em>shape<\/em> ou <em>index<\/em>). Dans ce cas, l&rsquo;interpr\u00e9teur r\u00e9sout la r\u00e9f\u00e9rence vers la m\u00e9thode interne et non vers la colonne du tableau, g\u00e9n\u00e9rant des erreurs de type difficiles \u00e0 diagnostiquer.<\/p>\n<p>\u00c0 l&rsquo;inverse, l&rsquo;indexation par crochets s&rsquo;articule comme suit :<\/p>\n<p><code>mediane_tr = df['temps_reaction_ms'].median()<\/code><\/p>\n<p>Cette forme constitue le standard d&rsquo;ing\u00e9nierie universellement prescrit par les normes stylistiques <a rel=\"noopener noreferrer\" href=\"https:\/\/peps.python.org\/pep-0008\/\">PEP 8<\/a> et l&rsquo;\u00e9quipe de d\u00e9veloppement de Pandas. Elle garantit une immunit\u00e9 totale contre les collisions de noms de m\u00e9thodes, autorise l&rsquo;usage de n&rsquo;importe quelle cha\u00eene de caract\u00e8res arbitraire comme nom de colonne, et facilite la manipulation dynamique des colonnes par injection de variables scalaires ou it\u00e9rables dans des boucles de traitement automatis\u00e9es.<\/p>\n<h3>4.3 Interpr\u00e9tation du r\u00e9sultat statistique obtenu<\/h3>\n<p>L&rsquo;obtention d&rsquo;une m\u00e9diane empirique fix\u00e9e \u00e0 237,5 millisecondes pour la variable &lsquo;temps_reaction_ms&rsquo; fournit un \u00e9clairage statistique particuli\u00e8rement instructif sur la cohorte \u00e9valu\u00e9e. Si l&rsquo;on calcule parall\u00e8lement la moyenne arithm\u00e9tique de cette m\u00eame s\u00e9rie temporelle, on observe une valeur de 293,33 millisecondes. L&rsquo;\u00e9cart absolu entre la moyenne et la m\u00e9diane d\u00e9passe ainsi 55 millisecondes, traduisant une forte asym\u00e9trie droite (skewness positive) induite quasi exclusivement par l&rsquo;observation &lsquo;SUBJ_06&rsquo; dont la latence atteint 480 millisecondes.<\/p>\n<p>La m\u00e9diane de 237,5 indique avec exactitude que 50 % des sujets de l&rsquo;\u00e9chantillon manifestent une vitesse de traitement \u00e9gale ou sup\u00e9rieure \u00e0 cette valeur, tandis que l&rsquo;autre moiti\u00e9 pr\u00e9sente une vitesse inf\u00e9rieure. Contrairement \u00e0 la moyenne, la m\u00e9diane n&rsquo;est pas attir\u00e9e par l&rsquo;observation atypique, offrant ainsi une estimation beaucoup plus fid\u00e8le du niveau de performance standard de la cohorte d&rsquo;\u00e9tude.<\/p>\n<p>Dans la litt\u00e9rature m\u00e9thodologique, la m\u00e9diane univari\u00e9e est fr\u00e9quemment exploit\u00e9e pour proc\u00e9der \u00e0 une dichotomisation op\u00e9rationnelle des effectifs, selon la proc\u00e9dure standard dite du <em>median-split<\/em>. Cette m\u00e9thode permet de scinder la cohorte en deux cat\u00e9gories fonctionnelles : les sujets \u00e0 traitement rapide (inf\u00e9rieurs ou \u00e9gaux \u00e0 237,5 ms) et les sujets \u00e0 traitement lent (sup\u00e9rieurs \u00e0 237,5 ms). Bien que la dichotomisation de variables continues doive \u00eatre mani\u00e9e avec pr\u00e9caution en raison de la perte potentielle d&rsquo;information de variance qu&rsquo;elle implique, elle s&rsquo;av\u00e8re particuli\u00e8rement utile pour \u00e9quilibrer les classes dans des protocoles de classification binaire supervis\u00e9e ou pour stratifier des groupes de diagnostic clinique.<\/p>\n<h2>5. Calcul de la m\u00e9diane sur un sous-ensemble de colonnes sp\u00e9cifiques<\/h2>\n<h3>5.1 S\u00e9lection par liste de variables explicatives<\/h3>\n<p>Dans le cadre d&rsquo;\u00e9tudes multidimensionnelles complexes, il est rarement utile de calculer la m\u00e9diane sur l&rsquo;ensemble exhaustif des m\u00e9triques disponibles, certaines colonnes constituant des identifiants cat\u00e9goriels ou des variables secondaires sans pertinence quantitative. Pour restreindre la r\u00e9duction statistique \u00e0 un sous-ensemble contr\u00f4l\u00e9 de variables, Pandas propose l&rsquo;usage d&rsquo;une liste d&rsquo;\u00e9tiquettes encapsul\u00e9e dans une double paire de crochets :<\/p>\n<p><code>colonnes_cibles = ['temps_reaction_ms', 'erreurs_comptabilisees']<br \/>\nmedianes_selection = df[colonnes_cibles].median()<\/code><\/p>\n<p>L&rsquo;expression <em>df[colonnes_cibles]<\/em> r\u00e9alise une projection structurelle produisant un sous-<em>DataFrame<\/em> temporaire ne conservant que les deux axes sp\u00e9cifi\u00e9s. L&rsquo;appel ult\u00e9rieur de <em>.median()<\/em> op\u00e8re ensuite le calcul de r\u00e9duction de mani\u00e8re ind\u00e9pendante sur chacune de ces deux dimensions verticales. La structure r\u00e9sultante n&rsquo;est plus un scalaire flottant unique, mais une <em>Series<\/em> Pandas indic\u00e9e par le nom des variables cibles :<\/p>\n<p><code>print(medianes_selection)<br \/>\n# temps_reaction_ms         237.5<br \/>\n# erreurs_comptabilisees      2.5<br \/>\n# dtype: float64<\/code><\/p>\n<p>Dans cet objet r\u00e9capitulatif, chaque composante vectorielle conserve son \u00e9tiquette d&rsquo;origine, permettant un adressage direct ou des requ\u00eates ult\u00e9rieures par indexation s\u00e9mantique standard, par exemple via l&rsquo;instruction <em>medianes_selection[&lsquo;erreurs_comptabilisees&rsquo;]<\/em>.<\/p>\n<h3>5.2 Analyse comparative des variables retenues<\/h3>\n<p>Le vecteur de synth\u00e8se issu de cette s\u00e9lection offre une visibilit\u00e9 directe sur la tendance centrale de variables quantitatives aux propri\u00e9t\u00e9s distinctes. L&rsquo;analyse conjointe du temps de r\u00e9action m\u00e9dian (237,5 ms) et du volume m\u00e9dian d&rsquo;erreurs (2,5) permet d&rsquo;\u00e9tablir imm\u00e9diatement le profil m\u00e9dian de la cohorte exp\u00e9rimentale sans qu&rsquo;il soit n\u00e9cessaire d&rsquo;appliquer une standardisation z-score pr\u00e9alable, la m\u00e9diane demeurant invariante sous toutes les transformations monotones croissantes.<\/p>\n<p>Pour la variable &lsquo;erreurs_comptabilisees&rsquo;, qui est une m\u00e9trique discr\u00e8te d&rsquo;entiers naturels repr\u00e9sentant des d\u00e9comptes d&rsquo;\u00e9v\u00e9nements, la s\u00e9rie ordonn\u00e9e est [0, 1, 2, 3, 5, 12]. L&rsquo;application de la r\u00e8gle de parit\u00e9 impose la demi-somme des valeurs centrales <span class=\"arabpsy-math-inline\" data-latex=\"X_{(3)} = 2\">$X_{(3)} = 2$<\/span> et <span class=\"arabpsy-math-inline\" data-latex=\"X_{(4)} = 3\">$X_{(4)} = 3$<\/span>, produisant ainsi une m\u00e9diane non enti\u00e8re de 2,5. Ce comportement illustre le fait qu&rsquo;une statistique de tendance centrale appliqu\u00e9e \u00e0 des variables discr\u00e8tes peut parfaitement g\u00e9n\u00e9rer un nombre rationnel d\u00e9cimal, refl\u00e9tant le point d&rsquo;\u00e9quilibre probabiliste de la loi sous-jacente.<\/p>\n<p>Ce format vectoriel sous forme de <em>Series<\/em> se pr\u00eate particuli\u00e8rement bien \u00e0 l&rsquo;int\u00e9gration dans des pipelines d&rsquo;exportation vers des formats tabulaires secondaires. L&rsquo;analyste peut ainsi convertir instantan\u00e9ment cette synth\u00e8se descriptive en un tableau de bord consolid\u00e9 ou la fusionner avec d&rsquo;autres s\u00e9ries r\u00e9capitulatives d&rsquo;\u00e9carts interquartiles pour publication institutionnelle.<\/p>\n<h3>5.3 Gestion des sous-ensembles mixtes contenant des types non num\u00e9riques<\/h3>\n<p>Une probl\u00e9matique majeure survient lorsque la liste des variables s\u00e9lectionn\u00e9es contient par inadvertance des colonnes non num\u00e9riques, telles que des cha\u00eenes de caract\u00e8res descriptives ou des identifiants alphanum\u00e9riques. Consid\u00e9rons la s\u00e9lection fautive suivante :<\/p>\n<p><code>sous_ensemble_invalide = df[['identifiant', 'temps_reaction_ms']]<\/code><\/p>\n<p>Si l&rsquo;on appelle <em>sous_ensemble_invalide.median()<\/em> sans argument compl\u00e9mentaire dans une version contemporaine de Pandas, le syst\u00e8me tente d&rsquo;ex\u00e9cuter l&rsquo;algorithme sur l&rsquo;ensemble des colonnes. Face \u00e0 l&rsquo;impossibilit\u00e9 math\u00e9matique et computationnelle d&rsquo;ordonner et d&rsquo;interpoler des cha\u00eenes arbitraires comme &lsquo;SUBJ_01&rsquo; et &lsquo;SUBJ_02&rsquo;, l&rsquo;interpr\u00e9teur d\u00e9clenche une exception bloquante de type <em>TypeError: could not convert string to float<\/em>.<\/p>\n<p>Pour immuniser le flux de traitement contre ces d\u00e9faillances impr\u00e9vues lors du traitement automatis\u00e9 de tables \u00e0 sch\u00e9mas dynamiques, il convient de filtrer explicitement la s\u00e9lection en amont \u00e0 l&rsquo;aide de la m\u00e9thode hautement sp\u00e9cialis\u00e9e <em>select_dtypes()<\/em>. Cette approche programmable permet d&rsquo;isoler uniquement les colonnes purement quantitatives avant de transmettre la projection matricielle \u00e0 la m\u00e9thode de calcul :<\/p>\n<p><code>colonnes_quantitatives = df[['identifiant', 'temps_reaction_ms', 'erreurs_comptabilisees']].select_dtypes(include=[np.number])<br \/>\nmedianes_securisees = colonnes_quantitatives.median()<\/code><\/p>\n<p>En formulant le pipeline de cette mani\u00e8re, la variable textuelle &lsquo;identifiant&rsquo; est filtr\u00e9e de fa\u00e7on pr\u00e9ventive et transparente, \u00e9liminant tout risque de crash logiciel sans d\u00e9pendre des m\u00e9canismes d&rsquo;exclusion implicites de bas niveau.<\/p>\n<h2>6. Calcul global de la m\u00e9diane sur l&rsquo;ensemble du DataFrame<\/h2>\n<h3>6.1 Ex\u00e9cution de df.median() et agr\u00e9gation globale<\/h3>\n<p>Dans de nombreux cas d&rsquo;usage industriels, tels que la normalisation robuste globale, l&rsquo;audit de qualit\u00e9 pr\u00e9liminaire ou la d\u00e9tection automatis\u00e9e d&rsquo;anomalies sur des tables massives comptant des centaines de colonnes, il devient impraticable de lister manuellement chaque variable. Il est alors d&rsquo;usage d&rsquo;appliquer l&rsquo;op\u00e9rateur de r\u00e9duction statistique directement sur la totalit\u00e9 de la structure tabulaire via l&rsquo;invocation globale :<\/p>\n<p><code>medianes_globales = df.median(numeric_only=True)<\/code><\/p>\n<p>Cette commande traite la totalit\u00e9 de la matrice bidimensionnelle en une seule op\u00e9ration vectoris\u00e9e. L&rsquo;algorithme parcourt syst\u00e9matiquement chaque colonne r\u00e9pondant aux contraintes num\u00e9riques, applique la logique de tri partiel optimis\u00e9e, r\u00e9sout les \u00e9ventuelles interpolations li\u00e9es \u00e0 la parit\u00e9 de chaque dimension, et assemble la totalit\u00e9 des r\u00e9sultats au sein d&rsquo;une unique <em>Series<\/em> r\u00e9sultante index\u00e9e par le sch\u00e9ma des colonnes quantitatives valides.<\/p>\n<p>Le vecteur produit rassemble l&rsquo;ensemble des coordonn\u00e9es centrales du nuage de points multidimensionnel projet\u00e9 sur chacun des axes univari\u00e9s. Il constitue la base calculatoire standard \u00e0 partir de laquelle sont d\u00e9finies les distances g\u00e9om\u00e9triques robustes, comme la distance de Manhattan bas\u00e9e sur la m\u00e9diane, souvent pr\u00e9f\u00e9r\u00e9e \u00e0 la distance euclidienne lors de la fouille de donn\u00e9es en haute dimension sujettes aux perturbations p\u00e9riph\u00e9riques.<\/p>\n<h3>6.2 R\u00f4le d\u00e9terminant du param\u00e8tre numeric_only dans l&rsquo;agr\u00e9gation globale<\/h3>\n<p>Il importe de souligner avec insistance les implications techniques directes de l&rsquo;utilisation explicite du param\u00e8tre <em>numeric_only=True<\/em> dans le cadre d&rsquo;un appel global sur un <em>DataFrame<\/em>. Depuis les mises \u00e0 jour structurelles majeures introduites dans Pandas 2.0, l&rsquo;adoption de normes de typage strictes inspir\u00e9es des sp\u00e9cifications de bases de donn\u00e9es formelles interdit l&rsquo;application d&rsquo;op\u00e9rateurs math\u00e9matiques ind\u00e9finis sur des conteneurs d&rsquo;objets g\u00e9n\u00e9riques.<\/p>\n<p>Si l&rsquo;instruction <em>df.median()<\/em> \u00e9tait tol\u00e9r\u00e9e dans les versions obsol\u00e8tes en omettant silencieusement les variables cat\u00e9gorielles &lsquo;identifiant&rsquo; et &lsquo;groupe&rsquo;, l&rsquo;absence de sp\u00e9cification du param\u00e8tre dans les versions actuelles provoque l&rsquo;\u00e9mission d&rsquo;alertes <em>FutureWarning<\/em> critiques, voire un arr\u00eat imm\u00e9diat du code avec \u00e9mission d&rsquo;une erreur <em>TypeError<\/em>. La directive <em>numeric_only=True<\/em> agit comme une consigne explicite donn\u00e9e au moteur d&rsquo;ex\u00e9cution en langage C\/Cython pour inspecter les m\u00e9tadonn\u00e9es de colonnes (<em>dtypes<\/em>) et court-circuiter pr\u00e9ventivement toute variable dont l&rsquo;espace d&rsquo;encodage m\u00e9moire ne correspond pas \u00e0 des entiers (<em>int8<\/em>, <em>int16<\/em>, <em>int32<\/em>, <em>int64<\/em>), des r\u00e9els (<em>float16<\/em>, <em>float32<\/em>, <em>float64<\/em>) ou des types bool\u00e9ens natifs.<\/p>\n<p>Pour tout ing\u00e9nieur logiciel ou scientifique de donn\u00e9es concevant des modules appel\u00e9s \u00e0 \u00eatre d\u00e9ploy\u00e9s en production au sein de conteneurs Docker ou de pipelines d&rsquo;int\u00e9gration continue, l&rsquo;omission de cet argument expose l&rsquo;infrastructure logicielle \u00e0 des ruptures de service lors de la mise \u00e0 jour des environnements d&rsquo;ex\u00e9cution virtuels. L&rsquo;adoption d&rsquo;un paradigme de d\u00e9claration syst\u00e9matique et explicite repr\u00e9sente ainsi le socle de la maintenabilit\u00e9 applicative.<\/p>\n<h3>6.3 Conversion du vecteur de synth\u00e8se en structures tierces<\/h3>\n<p>Une fois le vecteur de m\u00e9dianes globales g\u00e9n\u00e9r\u00e9, il est fr\u00e9quemment requis de le convertir vers des formats de donn\u00e9es alternatifs pour alimenter des architectures distribu\u00e9es, des micro-services Web de restitution ou des bases de donn\u00e9es relationnelles. La <em>Series<\/em> r\u00e9sultante peut \u00eatre convertie selon plusieurs voies canoniques.<\/p>\n<p>Pour s\u00e9rialiser les r\u00e9sultats dans une architecture orient\u00e9e documents ou un \u00e9change d&rsquo;API REST au format JSON, la transformation en dictionnaire Python standard s&rsquo;ex\u00e9cute de mani\u00e8re optimale \u00e0 l&rsquo;aide de la m\u00e9thode native :<\/p>\n<p><code>dictionnaire_medianes = df.median(numeric_only=True).to_dict()<\/code><\/p>\n<p>Cette instruction convertit les paires cl\u00e9-valeur (o\u00f9 la cl\u00e9 correspond au nom de la colonne et la valeur au flottant r\u00e9sultant) en structures natives Python compatibles avec les moteurs de s\u00e9rialisation standard. Si l&rsquo;objectif consiste plut\u00f4t \u00e0 concevoir un rapport synth\u00e9tique r\u00e9utilisable dans un tableur ou un tableau comparatif imbriqu\u00e9, la transformation de la <em>Series<\/em> en un nouveau <em>DataFrame<\/em> s&rsquo;effectue au moyen de :<\/p>\n<p><code>df_synthese = df.median(numeric_only=True).reset_index()<br \/>\ndf_synthese.columns = ['Variable', 'Valeur_Mediane']<\/code><\/p>\n<p>Cette op\u00e9ration convertit l&rsquo;index des colonnes en une variable textuelle explicite et associe chaque estimation m\u00e9diane au sein d&rsquo;une structure rectangulaire standardis\u00e9e, pr\u00eate pour l&rsquo;exportation vers des formats p\u00e9rennes via <em>df_synthese.to_csv(&lsquo;synthese_medianes.csv&rsquo;, index=False)<\/em>.<\/p>\n<h2>7. Gestion rigoureuse des valeurs manquantes avec skipna<\/h2>\n<h3>7.1 Comportement par d\u00e9faut : omission des valeurs nulles<\/h3>\n<p>L&rsquo;un des atouts op\u00e9rationnels majeurs de la biblioth\u00e8que Pandas r\u00e9side dans son traitement robuste des valeurs nulles, encod\u00e9es selon les conventions historiques via la sentinelle \u00e0 virgule flottante <em>numpy.nan<\/em> ou, plus r\u00e9cemment, via la sentinelle scalaire g\u00e9n\u00e9rique unifi\u00e9e <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/docs\/user_guide\/missing_data.html\">pd.NA<\/a>. Par d\u00e9faut, le param\u00e8tre <em>skipna<\/em> de la fonction <em>median()<\/em> est implicitement initialis\u00e9 \u00e0 la valeur bool\u00e9enne <em>True<\/em>.<\/p>\n<p>Ce param\u00e9trage induit un comportement algorithmique pr\u00e9cis : lors du parcours de la structure de donn\u00e9es, le moteur d&rsquo;ex\u00e9cution commence par op\u00e9rer un filtrage en m\u00e9moire pour \u00e9liminer l&rsquo;int\u00e9gralit\u00e9 des \u00e9l\u00e9ments reconnus comme non valides ou absents. Le calcul du rang m\u00e9dian s&rsquo;ex\u00e9cute ensuite exclusivement sur l&rsquo;\u00e9chantillon effectif constitu\u00e9 des donn\u00e9es valides r\u00e9siduelles, dont la taille effective devient <span class=\"arabpsy-math-inline\" data-latex=\"N_{\\text{valide}} = N_{\\text{total}} - N_{\\text{manquants}}\">$N_{\\text{valide}} = N_{\\text{total}} &#8211; N_{\\text{manquants}}$<\/span>.<\/p>\n<p>Pour illustrer ce m\u00e9canisme avec clart\u00e9, examinons le traitement appliqu\u00e9 \u00e0 la colonne &lsquo;score_attention&rsquo; de notre jeu de donn\u00e9es exp\u00e9rimental. Cette variable regroupe originellement six observations : [88, 76, 94, 91, np.nan, 62]. L&rsquo;activation implicite de <em>skipna=True<\/em> \u00e9limine la cinqui\u00e8me observation corrompue. L&rsquo;\u00e9chantillon effectif est ainsi r\u00e9duit \u00e0 cinq observations quantitatives valides (<span class=\"arabpsy-math-inline\" data-latex=\"N_{\\text{valide}} = 5\">$N_{\\text{valide}} = 5$<\/span>) : [88, 76, 94, 91, 62]. L&rsquo;effectif effectif devenant impair, la s\u00e9rie tri\u00e9e prend la forme suivante :<\/p>\n<p>[62, 76, 88, 91, 94]<\/p>\n<p>L&rsquo;algorithme identifie ensuite l&rsquo;\u00e9l\u00e9ment central \u00e0 la position ordonn\u00e9e <span class=\"arabpsy-math-inline\" data-latex=\"(5 + 1) \/ 2 = 3\">$(5 + 1) \/ 2 = 3$<\/span>. La valeur m\u00e9diane renvoy\u00e9e par l&rsquo;instruction <em>df[&lsquo;score_attention&rsquo;].median()<\/em> est donc rigoureusement \u00e9gale \u00e0 88,0. L&rsquo;omission dynamique permet ainsi d&rsquo;extraire une tendance centrale informative sans que la pr\u00e9sence d&rsquo;une valeur manquante n&rsquo;interrompe pr\u00e9matur\u00e9ment le calcul.<\/p>\n<h3>7.2 Application stricte de la sensibilit\u00e9 aux manques avec skipna=False<\/h3>\n<p>Si la tol\u00e9rance aux valeurs manquantes constitue un comportement souhaitable lors des phases exploratoires rapides, elle pr\u00e9sente des risques m\u00e9thodologiques certains dans les contextes industriels critiques ou les protocoles de validation clinique \u00e0 haute int\u00e9grit\u00e9. Dans ces contextes stricts, la survenue impr\u00e9vue d&rsquo;une valeur manquante peut signaler une d\u00e9faillance mat\u00e9rielle d&rsquo;acquisition, une rupture de la cha\u00eene d&rsquo;anonymisation ou un biais d&rsquo;\u00e9chantillonnage syst\u00e9matique qui invalide la repr\u00e9sentativit\u00e9 de l&rsquo;observation.<\/p>\n<p>Pour obliger l&rsquo;interpr\u00e9teur \u00e0 adopter une approche stricte de propagation de l&rsquo;incertitude num\u00e9rique, il est possible de fixer explicitement l&rsquo;argument \u00e0 <em>skipna=False<\/em> :<\/p>\n<p><code>mediane_attention_stricte = df['score_attention'].median(skipna=False)<br \/>\nprint(mediane_attention_stricte)<br \/>\n# NaN<\/code><\/p>\n<p>En configurant la fonction de cette mani\u00e8re, la pr\u00e9sence d&rsquo;au moins un \u00e9l\u00e9ment manquant au sein du vecteur d&rsquo;analyse contamine imm\u00e9diatement le r\u00e9sultat global, provoquant le renvoi syst\u00e9matique de la sentinelle <em>NaN<\/em>. Cette caract\u00e9ristique transforme la m\u00e9thode <em>median()<\/em> en un outil de diagnostic particuli\u00e8rement performant : un r\u00e9sultat non nul ou non d\u00e9fini signale instantan\u00e9ment \u00e0 l&rsquo;ing\u00e9nieur de donn\u00e9es l&rsquo;existence d&rsquo;une incompl\u00e9tude dans la collecte sans n\u00e9cessiter l&rsquo;ex\u00e9cution conjointe et co\u00fbteuse d&rsquo;un appel distinct \u00e0 la m\u00e9thode <em>isna().any()<\/em>.<\/p>\n<h3>7.3 Strat\u00e9gies d&rsquo;imputation m\u00e9diane pour la compl\u00e9tion des donn\u00e9es<\/h3>\n<p>Dans la construction de cha\u00eenes d&rsquo;apprentissage automatique supervis\u00e9, la majorit\u00e9 des mod\u00e8les pr\u00e9dictifs standards (tels que les r\u00e9gressions logistiques r\u00e9gularis\u00e9es, les r\u00e9seaux de neurones denses ou les machines \u00e0 vecteurs de support) sont structurellement incapables d&rsquo;ing\u00e9rer des matrices contenant des valeurs manquantes. Une strat\u00e9gie d&rsquo;ing\u00e9nierie des variables tr\u00e8s r\u00e9pandue consiste \u00e0 proc\u00e9der \u00e0 une <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Imputation_(statistiques)\">imputation univari\u00e9e<\/a> par la m\u00e9diane pour pr\u00e9server la compl\u00e9tude du tableau d&rsquo;apprentissage sans supprimer d&rsquo;observations pr\u00e9cieuses.<\/p>\n<p>La mise en \u0153uvre conjointe des m\u00e9thodes <em>fillna()<\/em> et <em>median()<\/em> permet de r\u00e9aliser cette op\u00e9ration de restauration avec une grande \u00e9l\u00e9gance syntaxique :<\/p>\n<p><code>valeur_mediane = df['score_attention'].median()<br \/>\ndf['score_attention_impute'] = df['score_attention'].fillna(valeur_mediane)<\/code><\/p>\n<p>Apr\u00e8s l&rsquo;ex\u00e9cution de ce code, la cinqui\u00e8me observation du tableau exp\u00e9rimental re\u00e7oit formellement l&rsquo;assignation de la valeur 88,0, r\u00e9tablissant la compl\u00e9tude dimensionnelle sans modifier la tendance centrale univari\u00e9e originelle de la distribution.<\/p>\n<p>N\u00e9anmoins, sur le plan m\u00e9thodologique rigoureux, l&rsquo;imputation par la m\u00e9diane pr\u00e9sente des limites th\u00e9oriques bien document\u00e9es qu&rsquo;il importe de garder \u00e0 l&rsquo;esprit. Si elle pr\u00e9serve parfaitement le barycentre m\u00e9dian de la s\u00e9rie, elle induit m\u00e9caniquement un \u00e9crasement artificiel de la variance globale de l&rsquo;\u00e9chantillon, concentre artificiellement de la densit\u00e9 de probabilit\u00e9 au point d&rsquo;imputation et att\u00e9nue les coefficients de corr\u00e9lation de Pearson ou de Spearman calcul\u00e9s avec les autres variables pr\u00e9dictives. Dans les contextes statistiques avanc\u00e9s, elle doit donc \u00eatre r\u00e9serv\u00e9e \u00e0 des situations o\u00f9 le taux d&rsquo;attrition demeure marginal (typiquement inf\u00e9rieur \u00e0 5 % des observations totales), sous peine de devoir recourir \u00e0 des m\u00e9thodes d&rsquo;imputation multiple par \u00e9quations cha\u00een\u00e9es (MICE) ou par k-plus proches voisins (k-NN).<\/p>\n<h2>8. Calcul horizontal de la m\u00e9diane par ligne (axis=1)<\/h2>\n<h3>8.1 Principes du calcul transversal intra-individuel<\/h3>\n<p>L&rsquo;analyse des structures tabulaires ne se limite pas \u00e0 la description verticale des colonnes. Dans une vaste diversit\u00e9 d&rsquo;architectures de donn\u00e9es, la structure matricielle encode des dimensions r\u00e9p\u00e9t\u00e9es \u00e0 travers l&rsquo;axe horizontal. C&rsquo;est typiquement le cas des protocoles de mesures r\u00e9p\u00e9t\u00e9es, o\u00f9 chaque ligne mod\u00e9lise un individu unique et o\u00f9 plusieurs colonnes contigu\u00ebs consignent les performances mesur\u00e9es lors d&rsquo;essais successifs, de capteurs biom\u00e9caniques multiples ou de r\u00e9plicats biologiques pr\u00e9lev\u00e9s au m\u00eame instant t.<\/p>\n<p>Dans cette configuration g\u00e9om\u00e9trique, le calcul de la m\u00e9diane selon la dimension horizontale requiert la sp\u00e9cification formelle de <em>axis=1<\/em> (ou <em>axis=&rsquo;columns&rsquo;<\/em>). L&rsquo;algorithme r\u00e9alise alors une it\u00e9ration ligne par ligne, calculant pour chaque entit\u00e9 observ\u00e9e la m\u00e9diane transversale des variables quantitatives sp\u00e9cifi\u00e9es. Cette approche fournit une estimation robuste du niveau de performance de chaque individu, r\u00e9sistant parfaitement aux erreurs d&rsquo;inattention transitoires, aux art\u00e9facts d&rsquo;enregistrement ou aux faux d\u00e9parts observ\u00e9s sur un essai isol\u00e9.<\/p>\n<h3>8.2 Exemple pratique sur une s\u00e9lection de variables r\u00e9p\u00e9t\u00e9es<\/h3>\n<p>Pour contextualiser concr\u00e8tement ce mode op\u00e9ratoire transversal, enrichissons notre tableau exp\u00e9rimental en simulant trois mesures cons\u00e9cutives de temps de r\u00e9action obtenues lors de trois blocs exp\u00e9rimentaux s\u00e9quentiels administr\u00e9s \u00e0 chacun des six participants de la cohorte :<\/p>\n<p><code>df_essais = pd.DataFrame({<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'sujet': ['SUBJ_01', 'SUBJ_02', 'SUBJ_03', 'SUBJ_04', 'SUBJ_05', 'SUBJ_06'],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'essai_1': [245.0, 312.0, 215.0, 230.0, 278.0, 480.0],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'essai_2': [250.0, 305.0, 220.0, 240.0, 285.0, 290.0],<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;'essai_3': [242.0, 410.0, 210.0, 235.0, np.nan, 305.0]<br \/>\n})<\/p>\n<p>colonnes_essais = ['essai_1', 'essai_2', 'essai_3']<br \/>\ndf_essais['mediane_sujet'] = df_essais[colonnes_essais].median(axis=1)<\/code><\/p>\n<p>L&rsquo;affichage du tableau r\u00e9sultant met en lumi\u00e8re l&rsquo;int\u00e9r\u00eat de cette approche :<\/p>\n<p>Pour le sujet &lsquo;SUBJ_02&rsquo;, les scores aux trois essais sont respectivement de 312,0, 305,0 et 410,0 millisecondes. La troisi\u00e8me valeur manifeste une d\u00e9rive temporelle s\u00e9v\u00e8re de 410 ms. Le calcul de la m\u00e9diane horizontale extrait la valeur centrale ordonn\u00e9e [305.0, 312.0, 410.0], fixant la m\u00e9diane individuelle \u00e0 312,0 millisecondes. Une moyenne arithm\u00e9tique aurait \u00e9tabli le score \u00e0 342,33 ms, p\u00e9nalisant ind\u00fbment le sujet pour une d\u00e9faillance transitoire. De m\u00eame, pour le sujet &lsquo;SUBJ_06&rsquo;, dont le premier essai \u00e0 480,0 ms repr\u00e9sentait une anomalie manifeste par rapport aux essais 2 et 3 (290,0 et 305,0 ms), la m\u00e9diane horizontale r\u00e9tablit un score repr\u00e9sentatif de 305,0 millisecondes.<\/p>\n<h3>8.3 Impact des donn\u00e9es manquantes en dimension horizontale<\/h3>\n<p>L&rsquo;application d&rsquo;un calcul transversal via <em>axis=1<\/em> interagit directement avec le m\u00e9canisme de gestion des donn\u00e9es manquantes r\u00e9gi par <em>skipna<\/em>. Dans l&rsquo;exemple pr\u00e9c\u00e9dent, le sujet &lsquo;SUBJ_05&rsquo; ne pr\u00e9sente que deux mesures valides en raison d&rsquo;un \u00e9chec technique lors du troisi\u00e8me bloc d&rsquo;\u00e9valuation consign\u00e9 par <em>np.nan<\/em> : [278.0, 285.0, np.nan].<\/p>\n<p>Par l&rsquo;effet de <em>skipna=True<\/em>, l&rsquo;algorithme horizontal omet la case vide pour ce sujet et r\u00e9duit son calcul effectif aux deux mesures disponibles (<span class=\"arabpsy-math-inline\" data-latex=\"N_{\\text{valide}} = 2\">$N_{\\text{valide}} = 2$<\/span>). Appliquant la r\u00e8gle de parit\u00e9 sur la s\u00e9rie [278.0, 285.0], la m\u00e9diane assign\u00e9e correspond \u00e0 la moyenne des deux valeurs : (278.0 + 285.0) \/ 2 = 281.5 millisecondes. Bien que cette souplesse permette de conserver le sujet dans l&rsquo;analyse, elle soul\u00e8ve une interrogation m\u00e9thodologique fondamentale : \u00e0 partir de quel niveau d&rsquo;attrition horizontale une m\u00e9diane individuelle cesse-t-elle d&rsquo;\u00eatre fiable ?<\/p>\n<p>Si un protocole comporte dix essais r\u00e9p\u00e9t\u00e9s et qu&rsquo;un participant n&rsquo;en valide qu&rsquo;un seul, l&rsquo;application aveugle de <em>axis=1<\/em> avec <em>skipna=True<\/em> assignera cette unique valeur comme m\u00e9diane individuelle, masquant le fait qu&rsquo;il s&rsquo;agit d&rsquo;une estimation \u00e0 variance d&rsquo;\u00e9chantillonnage extr\u00eame. Il est d\u00e8s lors vivement recommand\u00e9 d&rsquo;associer le calcul transversal \u00e0 un seuillage pr\u00e9alable du taux de compl\u00e9tude par ligne, en utilisant par exemple la m\u00e9thode <em>dropna(axis=0, thresh=seuil_minimal)<\/em> pour filtrer en amont les observations pr\u00e9sentant un d\u00e9ficit excessif de mesures valides.<\/p>\n<h2>9. Agr\u00e9gation conditionnelle et m\u00e9diane par groupe avec groupby()<\/h2>\n<h3>9.1 Segmentation cat\u00e9gorielle et syntaxe groupby<\/h3>\n<p>L&rsquo;exploration des donn\u00e9es exp\u00e9rimentales implique presque syst\u00e9matiquement la segmentation de la cohorte selon des facteurs qualitatifs, comme les groupes de traitement pharmacologique, les cohortes d&rsquo;\u00e2ge, le genre ou les conditions de stimulation environnementale. Dans Pandas, cette approche s&rsquo;articule autour du paradigme canonique du <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/docs\/user_guide\/groupby.html\">Split-Apply-Combine<\/a> (Scinder-Appliquer-Combiner), magistralement orchestr\u00e9 par la m\u00e9thode <em>groupby()<\/em>.<\/p>\n<p>Ce m\u00e9canisme proc\u00e8de en trois \u00e9tapes s\u00e9quentielles : la table d&rsquo;origine est d&rsquo;abord fragment\u00e9e en sous-groupes homog\u00e8nes selon les modalit\u00e9s de la variable cat\u00e9gorielle d\u00e9sign\u00e9e ; la fonction d&rsquo;agr\u00e9gation sp\u00e9cifi\u00e9e (en l&rsquo;esp\u00e8ce <em>median()<\/em>) est ensuite appliqu\u00e9e de mani\u00e8re isol\u00e9e et vectoris\u00e9e sur chaque partition ; enfin, les r\u00e9sultats partiels sont recombin\u00e9s au sein d&rsquo;une structure de synth\u00e8se unifi\u00e9e :<\/p>\n<p><code>mediane_par_groupe = df.groupby('groupe')['temps_reaction_ms'].median()<br \/>\nprint(mediane_par_groupe)<\/code><\/p>\n<p>L&rsquo;ex\u00e9cution de cette syntaxe sur notre jeu de donn\u00e9es exp\u00e9rimental originel segmente les six participants entre les conditions &lsquo;Controle&rsquo; et &lsquo;Traitement&rsquo; :<\/p>\n<p><code># groupe<br \/>\n# Controle      245.0<br \/>\n# Traitement    278.0<br \/>\n# Name: temps_reaction_ms, dtype: float64<\/code><\/p>\n<p>Dans le sous-groupe &lsquo;Controle&rsquo;, les trois observations ordonn\u00e9es sont [215.0, 245.0, 312.0], l&rsquo;effectif \u00e9tant impair (<span class=\"arabpsy-math-inline\" data-latex=\"n = 3\">$n = 3$<\/span>), la m\u00e9diane est imm\u00e9diatement identifi\u00e9e comme l&rsquo;\u00e9l\u00e9ment central \u00e0 245,0 ms. Dans le sous-groupe &lsquo;Traitement&rsquo;, les valeurs sont [230.0, 278.0, 480.0], produisant une m\u00e9diane de 278,0 ms. Cette d\u00e9composition permet de constater que, malgr\u00e9 la pr\u00e9sence de la valeur aberrante \u00e0 480 ms dans le groupe trait\u00e9, l&rsquo;\u00e9cart entre les m\u00e9dianes de groupe n&rsquo;est que de 33 ms, offrant une base d&rsquo;\u00e9valuation comparative bien plus \u00e9quilibr\u00e9e que si l&rsquo;on avait compar\u00e9 des moyennes arithm\u00e9tiques.<\/p>\n<h3>9.2 Agr\u00e9gations multidimensionnelles complexes<\/h3>\n<p>L&rsquo;architecture de <em>groupby()<\/em> se pr\u00eate avec la m\u00eame fluidit\u00e9 au traitement simultan\u00e9 de multiples variables d\u00e9pendantes, ainsi qu&rsquo;au croisement de plusieurs facteurs ind\u00e9pendants au sein de sch\u00e9mas factoriels crois\u00e9s complexes. Pour calculer simultan\u00e9ment la m\u00e9diane sur l&rsquo;ensemble des dimensions quantitatives du tableau pour chaque sous-groupe exp\u00e9rimental, il suffit d&rsquo;omettre la s\u00e9lection de colonne unique et d&rsquo;adjoindre le param\u00e8tre num\u00e9rique obligatoire :<\/p>\n<p><code>synthese_groupee = df.groupby('groupe').median(numeric_only=True)<\/code><\/p>\n<p>La structure r\u00e9sultante est un nouveau <em>DataFrame<\/em> o\u00f9 l&rsquo;index hi\u00e9rarchique est form\u00e9 par les \u00e9tiquettes de groupes et o\u00f9 chaque colonne contient la m\u00e9diane correspondante pour la variable mesur\u00e9e. Si la mod\u00e9lisation implique un plan exp\u00e9rimental factoriel complet, par exemple en croisant la variable &lsquo;groupe&rsquo; avec une variable factorielle &lsquo;sexe&rsquo;, la m\u00e9thode accepte une liste de cl\u00e9s d&rsquo;agr\u00e9gation : <em>df.groupby([&lsquo;groupe&rsquo;, &lsquo;sexe&rsquo;]).median(numeric_only=True)<\/em>.<\/p>\n<p>Dans ce dernier cas, Pandas g\u00e9n\u00e8re une structure dot\u00e9e d&rsquo;un index \u00e0 plusieurs niveaux, un <em>MultiIndex<\/em>. Pour faciliter l&rsquo;exploitation ult\u00e9rieure de cette structure matricielle, notamment pour des trac\u00e9s graphiques ou des exports vers des bases de donn\u00e9es tabulaires \u00e0 plat, il est courant de d\u00e9samorcer l&#8217;empilement hi\u00e9rarchique en appliquant la m\u00e9thode <em>reset_index()<\/em> ou d&rsquo;effectuer une rotation structurelle des colonnes via <em>unstack()<\/em> :<\/p>\n<p><code>synthese_aplatie = synthese_groupee.reset_index()<\/code><\/p>\n<p>Cette commande r\u00e9injecte les identifiants cat\u00e9goriels dans le corps matriciel sous forme de colonnes r\u00e9guli\u00e8res, facilitant leur manipulation au sein d&rsquo;autres librairies statistiques.<\/p>\n<h3>9.3 Comparaison inter-groupes et exploration de contrastes<\/h3>\n<p>L&rsquo;int\u00e9r\u00eat statistique majeur de l&rsquo;extraction des m\u00e9dianes group\u00e9es r\u00e9side dans l&rsquo;exploration pr\u00e9liminaire des effets d&rsquo;intervention dans les protocoles de recherche o\u00f9 les hypoth\u00e8ses param\u00e9triques usuelles (telles que la normalit\u00e9 des r\u00e9sidus mesur\u00e9e par le test de Shapiro-Wilk ou l&rsquo;\u00e9galit\u00e9 des variances valid\u00e9e par le test de Levene) sont viol\u00e9es.<\/p>\n<p>La mise en \u00e9vidence de contrastes m\u00e9dians substantiels entre deux groupes oriente l&rsquo;analyste vers le choix de tests d&rsquo;hypoth\u00e8ses non param\u00e9triques adapt\u00e9s, \u00e0 l&rsquo;instar du test des rangs sign\u00e9s de <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Test_de_Wilcoxon-Mann-Whitney\">Wilcoxon-Mann-Whitney<\/a> pour deux \u00e9chantillons ind\u00e9pendants, ou du test de Kruskal-Wallis pour des comparaisons impliquant <span class=\"arabpsy-math-inline\" data-latex=\"k\">$k$<\/span> groupes mutuellement exclusifs. Dans ces proc\u00e9dures inf\u00e9rentielles, les hypoth\u00e8ses nulles test\u00e9es s&rsquo;alignent \u00e9troitement sur l&rsquo;\u00e9galit\u00e9 des rangs m\u00e9dians plut\u00f4t que sur l&rsquo;\u00e9galit\u00e9 stricte des moyennes de populations.<\/p>\n<p>En outre, l&rsquo;\u00e9valuation des \u00e9carts entre m\u00e9dianes fournit une estimation robuste de la taille d&rsquo;effet brute sans normalisation, que l&rsquo;on peut rapporter utilement en association avec la d\u00e9viation absolue m\u00e9diane (MAD) ou les \u00e9tendues interquartiles afin de pr\u00e9senter un \u00e9tat exhaustif de la distribution des performances exp\u00e9rimentales.<\/p>\n<h2>10. Combinaison de median() avec les m\u00e9thodes agg(), transform() et apply()<\/h2>\n<h3>10.1 Synth\u00e8se multi-statistique avec la m\u00e9thode agg()<\/h3>\n<p>Dans un rapport d&rsquo;analyse de donn\u00e9es conforme aux exigences de l&rsquo;American Psychological Association (APA) ou des standards de reporting biom\u00e9dicaux, la m\u00e9diane ne doit jamais \u00eatre pr\u00e9sent\u00e9e de fa\u00e7on totalement isol\u00e9e. Elle doit obligatoirement \u00eatre confront\u00e9e \u00e0 d&rsquo;autres estimateurs de dispersion et de forme afin de caract\u00e9riser pleinement la distribution observ\u00e9e. La m\u00e9thode hautement flexible <em>agg()<\/em> (ou son alias <em>aggregate()<\/em>) permet d&rsquo;ex\u00e9cuter conjointement plusieurs calculs statistiques en une seule passe op\u00e9rationnelle optimis\u00e9e :<\/p>\n<p><code>synthese_complete = df.groupby('groupe')['temps_reaction_ms'].agg([<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;('Effectif', 'count'),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;('Moyenne', 'mean'),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;('Mediane', 'median'),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;('Ecart_Type', 'std'),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;('IQR', lambda x: x.quantile(0.75) - x.quantile(0.25))<br \/>\n])<\/code><\/p>\n<p>Dans cette formulation, l&rsquo;utilisation de tuples d\u00e9finissant une \u00e9tiquette personnalis\u00e9e associ\u00e9e \u00e0 une cha\u00eene de fonction native ou \u00e0 une expression anonyme lambda produit imm\u00e9diatement une table descriptive professionnelle. L&rsquo;introduction conjointe de la m\u00e9diane et de l&rsquo;intervalle interquartile (IQR) offre un couple de param\u00e8tres non param\u00e9triques (position et dispersion) parfaitement coh\u00e9rent et ind\u00e9pendant de toute hypoth\u00e8se distributionnelle pr\u00e9alable.<\/p>\n<p>L&rsquo;optimisation interne de Pandas veille \u00e0 ce que les fonctions d\u00e9sign\u00e9es par des cha\u00eenes textuelles standardis\u00e9es (telles que &lsquo;median&rsquo;, &lsquo;mean&rsquo; ou &lsquo;std&rsquo;) soient ex\u00e9cut\u00e9es via des routines vectoris\u00e9es \u00e9crites en Cython ou C, garantissant des temps de r\u00e9ponse computationnels minimaux m\u00eame sur des jeux de donn\u00e9es atteignant plusieurs millions d&rsquo;enregistrements.<\/p>\n<h3>10.2 Normalisation et centrage sur la m\u00e9diane avec transform()<\/h3>\n<p>Alors que la m\u00e9thode <em>agg()<\/em> op\u00e8re une r\u00e9duction dimensionnelle en collapseant les lignes de chaque partition pour produire un tableau r\u00e9sum\u00e9 synth\u00e9tique, la m\u00e9thode <em>transform()<\/em> remplit un r\u00f4le radicalement diff\u00e9rent mais tout aussi fondamental : elle conserve la taille d&rsquo;\u00e9chantillon d&rsquo;origine et la structure d&rsquo;indexation exacte du <em>DataFrame<\/em> initial.<\/p>\n<p>L&rsquo;usage de <em>transform()<\/em> en conjonction avec la m\u00e9diane est particuli\u00e8rement puissant pour op\u00e9rer un centrage robuste des observations par rapport \u00e0 leur groupe d&rsquo;appartenance :<\/p>\n<p><code>mediane_groupe_alignee = df.groupby('groupe')['temps_reaction_ms'].transform('median')<br \/>\ndf['deviation_mediane'] = df['temps_reaction_ms'] - mediane_groupe_alignee<\/code><\/p>\n<p>L&rsquo;instruction <em>transform(&lsquo;median&rsquo;)<\/em> calcule la m\u00e9diane propre \u00e0 chaque modalit\u00e9 factorielle, puis r\u00e9tro-projette cette valeur scalaire sur chaque ligne individuelle appartenant au groupe correspondant. L&rsquo;op\u00e9ration de soustraction vectorielle subs\u00e9quente g\u00e9n\u00e8re la variable &lsquo;deviation_mediane&rsquo;, qui quantifie l&rsquo;\u00e9cart exact d&rsquo;un individu par rapport au barycentre m\u00e9dian de sa cohorte de r\u00e9f\u00e9rence.<\/p>\n<p>Cette technique de standardisation robuste, bas\u00e9e sur la m\u00e9diane plut\u00f4t que sur la moyenne arithm\u00e9tique, s&rsquo;av\u00e8re particuli\u00e8rement utile pour \u00e9liminer les effets fixes de grappe ou de laboratoire sans contaminer les r\u00e9sidus par les valeurs extr\u00eames locales. Elle constitue l&rsquo;\u00e9tape pr\u00e9paratoire par excellence pour l&rsquo;entra\u00eenement d&rsquo;algorithmes de d\u00e9tection d&rsquo;anomalies non supervis\u00e9s fond\u00e9s sur les r\u00e9sidus m\u00e9dians.<\/p>\n<h3>10.3 Calculs personnalis\u00e9s et fonctions lambdas avec apply()<\/h3>\n<p>La m\u00e9thode g\u00e9n\u00e9rique <em>apply()<\/em> offre une libert\u00e9 totale de programmation pour les cas de figure o\u00f9 les fonctions de r\u00e9duction standard s&rsquo;av\u00e8rent insuffisantes pour r\u00e9pondre aux contraintes d&rsquo;une mod\u00e9lisation sophistiqu\u00e9e. Bien que moins optimis\u00e9e que les routines Cython natives en raison de la boucle Python sous-jacente, elle permet d&rsquo;injecter des fonctions math\u00e9matiques arbitraires ou des calculs de m\u00e9diane pond\u00e9r\u00e9e.<\/p>\n<p>\u00c0 titre d&rsquo;exemple, supposons que nous souhaitions calculer une m\u00e9diane filtr\u00e9e qui exclut conditionnellement les valeurs inf\u00e9rieures \u00e0 un certain seuil biologique ou d&rsquo;enregistrement :<\/p>\n<p><code>def mediane_filtree(serie):<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;valeurs_valides = serie[serie &gt; 220.0]<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;return valeurs_valides.median()<\/p>\n<p>mediane_personnalisee = df.groupby('groupe')['temps_reaction_ms'].apply(mediane_filtree)<\/code><\/p>\n<p>Cette approche permet d&rsquo;adapter finement le comportement math\u00e9matique appliqu\u00e9 \u00e0 chaque segment sans devoir d\u00e9couper manuellement la structure tabulaire en plusieurs objets transitoires. L&rsquo;analyste doit toutefois veiller \u00e0 n&rsquo;utiliser <em>apply()<\/em> que lorsque des contraintes fonctionnelles sp\u00e9cifiques emp\u00eachent l&rsquo;usage des m\u00e9thodes vectoris\u00e9es directes, afin de pr\u00e9server l&rsquo;efficacit\u00e9 globale du pipeline de traitement.<\/p>\n<h2>11. Optimisation des performances et pi\u00e8ges m\u00e9thodologiques courants<\/h2>\n<h3>11.1 Consid\u00e9rations algorithmiques et passage \u00e0 l&rsquo;\u00e9chelle<\/h3>\n<p>Lorsque le volume de donn\u00e9es trait\u00e9es atteint des millions d&rsquo;enregistrements (r\u00e9gime couramment qualifi\u00e9 de <em>Big Data<\/em> unitaire), l&#8217;empreinte m\u00e9moire et la complexit\u00e9 computationnelle du calcul de la m\u00e9diane deviennent des facteurs d\u00e9terminants pour la scalabilit\u00e9 des cha\u00eenes de traitement. Comme mentionn\u00e9 pr\u00e9c\u00e9demment, la m\u00e9diane repose intrins\u00e8quement sur la statistique d&rsquo;ordre, impliquant des op\u00e9rations de partitionnement ou de tri partiel de complexit\u00e9 <span class=\"arabpsy-math-inline\" data-latex=\"O(n)\">$O(n)$<\/span> via l&rsquo;algorithme <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/reference\/generated\/numpy.partition.html\">numpy.partition<\/a>.<\/p>\n<p>Pour optimiser drastiquement le temps d&rsquo;ex\u00e9cution, il est imp\u00e9ratif d&rsquo;adopter une strat\u00e9gie rigoureuse de r\u00e9duction de la pr\u00e9cision de typage (ou <em>downcasting<\/em>). Par d\u00e9faut, Pandas charge souvent les entiers et flottants en pr\u00e9cision 64 bits (<em>int64<\/em>, <em>float64<\/em>). Si la plage dynamique des observations le permet, convertir des colonnes vers une pr\u00e9cision de 32 bits (<em>float32<\/em>) divise par deux le volume de m\u00e9moire vive consomm\u00e9 par la structure matricielle et optimise l&rsquo;utilisation des caches L1\/L2 du processeur lors des phases de partitionnement vectoriel.<\/p>\n<p>Par ailleurs, sur de tr\u00e8s volumineux tableaux o\u00f9 l&rsquo;on n&rsquo;a pas besoin de l&rsquo;infrastructure de m\u00e9tadonn\u00e9es et d&rsquo;alignement d&rsquo;index fournie par Pandas, il s&rsquo;av\u00e8re souvent hautement avantageux d&rsquo;extraire le tableau sous-jacent NumPy pour effectuer le calcul directement \u00e0 la racine du moteur num\u00e9rique, en faisant appel \u00e0 <em>np.median(df[&lsquo;colonne&rsquo;].to_numpy())<\/em>. Les benchmarks industriels d\u00e9montrent r\u00e9guli\u00e8rement que cette strat\u00e9gie permet de supprimer la surcharge d&rsquo;encapsulation de Pandas, acc\u00e9l\u00e9rant les calculs d&rsquo;un facteur pouvant varier de 2 \u00e0 10 selon les dimensions consid\u00e9r\u00e9es.<\/p>\n<h3>11.2 Pi\u00e8ges fr\u00e9quents li\u00e9s aux types de donn\u00e9es et \u00e0 l&rsquo;arrondi<\/h3>\n<p>Parmi les anomalies les plus courantes et les plus insidieuses rencontr\u00e9es lors de l&rsquo;analyse exploratoire figure la pr\u00e9sence de colonnes contenant des nombres stock\u00e9s sous forme de cha\u00eenes de caract\u00e8res (type g\u00e9n\u00e9rique <em>object<\/em>). Cet \u00e9cueil survient couramment lors de l&rsquo;ingestion de fichiers CSV mal form\u00e9s o\u00f9 un s\u00e9parateur d\u00e9cimal incorrect (une virgule au lieu d&rsquo;un point) emp\u00eache l&rsquo;interpr\u00e9teur de typage automatique de d\u00e9tecter la nature num\u00e9rique de la colonne.<\/p>\n<p>Si l&rsquo;on appelle <em>median()<\/em> sur une variable cat\u00e9goris\u00e9e comme <em>object<\/em>, Pandas 2.x l\u00e8ve une exception <em>TypeError<\/em> imm\u00e9diate. Pour r\u00e9soudre ce dysfonctionnement, une conversion explicite pr\u00e9alable doit \u00eatre syst\u00e9matiquement engag\u00e9e \u00e0 l&rsquo;aide de la fonction s\u00e9curis\u00e9e <em>pd.to_numeric()<\/em>, coupl\u00e9e \u00e0 l&rsquo;argument <em>errors=&rsquo;coerce&rsquo;<\/em> pour transformer d&rsquo;\u00e9ventuelles scories textuelles en valeurs nulles g\u00e9rables :<\/p>\n<p><code>df['colonne_corrompue'] = pd.to_numeric(df['colonne_corrompue'], errors='coerce')<br \/>\nmediane_resolue = df['colonne_corrompue'].median()<\/code><\/p>\n<p>Un second pi\u00e8ge concerne la modification silencieuse du type scalaire lors du traitement de colonnes d&rsquo;entiers purs (<em>int64<\/em>). Si l&rsquo;effectif valide est pair, l&rsquo;interpolation arithm\u00e9tique de la m\u00e9diane g\u00e9n\u00e8re presque in\u00e9vitablement un nombre \u00e0 virgule flottante (comme la m\u00e9diane de 2,5 obtenue sur nos d\u00e9comptes d&rsquo;erreurs). L&rsquo;ing\u00e9nieur doit \u00eatre conscient que le type renvoy\u00e9 est alors obligatoirement <em>float64<\/em>, ce qui peut engendrer des incompatibilit\u00e9s d&rsquo;interface si une fonction r\u00e9ceptrice en aval attend rigoureusement des entiers stricts.<\/p>\n<p>Enfin, un cas particulier notable concerne les s\u00e9ries temporelles et dates encapsul\u00e9es sous le type <em>datetime64[ns]<\/em>. Pandas prend en charge nativement le calcul de la m\u00e9diane sur les horodatages. Dans ce contexte, la m\u00e9diane repr\u00e9sente le moment chronologique pr\u00e9cis divisant la s\u00e9quence d&rsquo;\u00e9v\u00e9nements en deux parties \u00e9gales. L&rsquo;interpolation sur effectif pair calcule la moyenne arithm\u00e9tique des deux estampilles temporelles centrales \u00e0 la nanoseconde pr\u00e8s, fournissant un outil pr\u00e9cieux pour analyser les dynamiques d&rsquo;historiques d&rsquo;acc\u00e8s ou les temps de parcours industriels.<\/p>\n<h3>11.3 Biais d&rsquo;interpr\u00e9tation statistique : le sophisme de la m\u00e9diane<\/h3>\n<p>Sur le plan de l&rsquo;interpr\u00e9tation scientifique, s&rsquo;appuyer de mani\u00e8re exclusive sur la m\u00e9diane peut paradoxalement induire des biais de jugement analytique majeurs si cette statistique n&rsquo;est pas accompagn\u00e9e d&rsquo;une inspection globale de la forme de la distribution. Ce ph\u00e9nom\u00e8ne, parfois qualifi\u00e9 de <em>sophisme de la tendance centrale<\/em>, se manifeste de fa\u00e7on particuli\u00e8rement aigu\u00eb en pr\u00e9sence de distributions bimodales ou multimodales.<\/p>\n<p>Consid\u00e9rons une distribution compos\u00e9e de deux sous-populations d&rsquo;effectifs identiques, l&rsquo;une centr\u00e9e autour de la valeur 10 et l&rsquo;autre centr\u00e9e autour de la valeur 90. Le calcul de la m\u00e9diane univari\u00e9e renverra une valeur d&rsquo;environ 50. Or, dans une telle distribution bimodale, cette valeur m\u00e9diane de 50 tombe pr\u00e9cis\u00e9ment dans le creux de densit\u00e9 probabiliste o\u00f9 ne se situe quasiment aucune observation r\u00e9elle. Conclure que la performance typique de l&rsquo;\u00e9chantillon est de 50 constituerait une faute d&rsquo;interpr\u00e9tation scientifique majeure.<\/p>\n<p>Par cons\u00e9quent, une bonne pratique m\u00e9thodologique impose de toujours corr\u00e9ler le calcul d&rsquo;une m\u00e9diane avec :<\/p>\n<ul>\n<li>Une inspection syst\u00e9matique de la dispersion via les quartiles <span class=\"arabpsy-math-inline\" data-latex=\"Q_1\">$Q_1$<\/span> (25 %) et <span class=\"arabpsy-math-inline\" data-latex=\"Q_3\">$Q_3$<\/span> (75 %), compl\u00e9t\u00e9e par l&rsquo;\u00e9cart interquartile (<span class=\"arabpsy-math-inline\" data-latex=\"\\text{IQR} = Q_3 - Q_1\">$\\text{IQR} = Q_3 &#8211; Q_1$<\/span>).<\/li>\n<li>Le calcul de la d\u00e9viation absolue m\u00e9diane (<a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/D%C3%A9viation_absolue_m%C3%A9diane\">MAD<\/a>), d\u00e9finie comme <span class=\"arabpsy-math-inline\" data-latex=\"\\text{MAD} = \\text{M\u00e9diane}(|X_i - \\text{M\u00e9diane}(X)|)\">$\\text{MAD} = \\text{M\u00e9diane}(|X_i &#8211; \\text{M\u00e9diane}(X)|)$<\/span>, qui constitue l&rsquo;analogue non param\u00e9trique de l&rsquo;\u00e9cart-type le plus performant.<\/li>\n<li>Une \u00e9valuation visuelle syst\u00e9matique de la densit\u00e9 empirique via des repr\u00e9sentations graphiques d\u00e9di\u00e9es pour s&rsquo;assurer de l&rsquo;unimodalit\u00e9 effective de la distribution analys\u00e9e.<\/li>\n<\/ul>\n<h2>12. Synth\u00e8se pratique, visualisation et flux de travail complet<\/h2>\n<h3>12.1 Repr\u00e9sentation graphique de la m\u00e9diane avec Seaborn et Matplotlib<\/h3>\n<p>Dans tout rapport d&rsquo;analyse de donn\u00e9es, l&rsquo;interpr\u00e9tation num\u00e9rique des valeurs m\u00e9dianes gagne consid\u00e9rablement \u00e0 \u00eatre \u00e9tay\u00e9e par des repr\u00e9sentations graphiques claires. Les \u00e9cosyst\u00e8mes graphiques de r\u00e9f\u00e9rence sous Python, principalement <a rel=\"noopener noreferrer\" href=\"https:\/\/matplotlib.org\/\">Matplotlib<\/a> et <a rel=\"noopener noreferrer\" href=\"https:\/\/seaborn.pydata.org\/\">Seaborn<\/a>, disposent d&rsquo;int\u00e9grations natives directes pour mettre en lumi\u00e8re la m\u00e9diane et son positionnement relatif au sein des distributions.<\/p>\n<p>Le diagramme en bo\u00eete \u00e0 moustaches (ou <em>boxplot<\/em>, formalis\u00e9 initialement par John Tukey) constitue la repr\u00e9sentation canonique par excellence d\u00e9di\u00e9e \u00e0 la m\u00e9diane. Au sein de ce trac\u00e9, le segment rectiligne barrant l&rsquo;int\u00e9rieur de la bo\u00eete centrale mat\u00e9rialise avec pr\u00e9cision l&#8217;emplacement de la m\u00e9diane (<span class=\"arabpsy-math-inline\" data-latex=\"Q_2\">$Q_2$<\/span>), tandis que les limites inf\u00e9rieure et sup\u00e9rieure du rectangle d\u00e9limitent respectivement le premier (<span class=\"arabpsy-math-inline\" data-latex=\"Q_1\">$Q_1$<\/span>) et le troisi\u00e8me quartile (<span class=\"arabpsy-math-inline\" data-latex=\"Q_3\">$Q_3$<\/span>). Les observations situ\u00e9es au-del\u00e0 des moustaches (d\u00e9finies usuellement \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"1{,}5 \\times \\text{IQR}\">$1{,}5 \\times \\text{IQR}$<\/span>) sont individualis\u00e9es sous la forme de points dispers\u00e9s, permettant d&rsquo;appr\u00e9hender instantan\u00e9ment pourquoi la m\u00e9diane r\u00e9siste \u00e0 ces valeurs atypiques tandis que la moyenne en est alt\u00e9r\u00e9e.<\/p>\n<p>Une alternative graphique moderne et tr\u00e8s expressive r\u00e9side dans l&rsquo;usage du trac\u00e9 en violon (<em>violin plot<\/em>) combin\u00e9 \u00e0 un trac\u00e9 d&rsquo;estimation de la densit\u00e9 par noyau (KDE). L&rsquo;adjonction d&rsquo;une ligne verticale pointill\u00e9e mat\u00e9rialisant la m\u00e9diane au sein d&rsquo;un histogramme de densit\u00e9 permet de superposer visuellement la m\u00e9diane et la moyenne arithm\u00e9tique. Lorsque la distribution est asym\u00e9trique, ce graphique illustre imm\u00e9diatement le d\u00e9calage directionnel entre ces deux m\u00e9triques, apportant une preuve visuelle de l&rsquo;asym\u00e9trie de distribution au lectorat scientifique.<\/p>\n<h3>12.2 \u00c9laboration d&rsquo;un pipeline complet d&rsquo;analyse de donn\u00e9es<\/h3>\n<p>Pour r\u00e9sumer l&rsquo;ensemble des concepts th\u00e9oriques et op\u00e9rationnels d\u00e9velopp\u00e9s tout au long de cette \u00e9tude, il est pertinent de formaliser une fonction de traitement analytique unifi\u00e9e. Ce module logiciel synth\u00e9tique encapsule le chargement, l&rsquo;audit de sch\u00e9ma, le filtrage des types, l&rsquo;extraction des m\u00e9dianes conditionnelles et l&rsquo;exportation des m\u00e9triques sous une forme modulaire, reproductible et robuste aux erreurs de production :<\/p>\n<p><code>import numpy as np<br \/>\nimport pandas as pd<\/p>\n<p>def pipeline_analyse_mediane(dataframe, colonne_facteur, colonnes_mesures):<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"\"\"<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Ex\u00e9cute un pipeline robuste d'agr\u00e9gation m\u00e9diane et de calcul de dispersion.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\"\"\"<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;# Validation de l'existence des axes<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;colonnes_presentes = [col for col in colonnes_mesures if col in dataframe.columns]<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;if not colonnes_presentes:<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError(\"Aucune colonne de mesure valide identifi\u00e9e dans le DataFrame.\")<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;# Isolation des variables strictement num\u00e9riques<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;df_numerique = dataframe[colonnes_presentes].select_dtypes(include=[np.number])<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;# R\u00e9injection de la colonne factorielle pour le d\u00e9coupage<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;df_travail = df_numerique.copy()<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;df_travail[colonne_facteur] = dataframe[colonne_facteur]<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;# Calcul de la synth\u00e8se non param\u00e9trique compl\u00e8te<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;synthese = df_travail.groupby(colonne_facteur).agg([<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('Mediane', 'median'),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('IQR', lambda x: x.quantile(0.75) - x.quantile(0.25)),<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('MAD', lambda x: (x - x.median()).abs().median())<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;])<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return synthese<\/p>\n<p># Ex\u00e9cution du pipeline de validation<br \/>\nresultats_synthetiques = pipeline_analyse_mediane(<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;dataframe=df,<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;colonne_facteur='groupe',<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;colonnes_mesures=['temps_reaction_ms', 'score_attention', 'erreurs_comptabilisees']<br \/>\n)<br \/>\nprint(resultats_synthetiques)<\/code><\/p>\n<p>Ce pipeline illustre l&rsquo;int\u00e9gration harmonieuse des meilleures pratiques d&rsquo;ing\u00e9nierie des donn\u00e9es : v\u00e9rification pr\u00e9alable des colonnes cibles, exclusion syst\u00e9matique des colonnes non num\u00e9riques, tol\u00e9rance aux valeurs manquantes gr\u00e2ce aux comportements vectoris\u00e9s natifs, et enrichissement de la m\u00e9diane par des estimateurs de dispersion robustes (IQR et MAD). Les r\u00e9sultats obtenus sont pr\u00eats \u00e0 \u00eatre ins\u00e9r\u00e9s dans des rapports scientifiques institutionnels ou int\u00e9gr\u00e9s \u00e0 des flux de mod\u00e9lisation pr\u00e9dictive en aval.<\/p>\n<h3>12.3 Aide-m\u00e9moire synth\u00e9tique des commandes m\u00e9dianes essentielles<\/h3>\n<p>Afin d&rsquo;offrir une r\u00e9f\u00e9rence op\u00e9rationnelle imm\u00e9diate pour le travail d&rsquo;analyse quotidien, les principales commandes li\u00e9es au calcul de la m\u00e9diane dans la biblioth\u00e8que Pandas sont synth\u00e9tis\u00e9es ci-dessous :<\/p>\n<ul>\n<li><strong>Calcul univari\u00e9 sur une Series :<\/strong> <em>df[&lsquo;colonne&rsquo;].median()<\/em> \u2014 Retourne un scalaire flottant (<em>numpy.float64<\/em>) repr\u00e9sentant la m\u00e9diane de la variable, en ignorant les valeurs manquantes.<\/li>\n<li><strong>Calcul multi-colonnes vertical :<\/strong> <em>df[[&lsquo;col1&rsquo;, &lsquo;col2&rsquo;]].median()<\/em> \u2014 Retourne une <em>Series<\/em> contenant la m\u00e9diane verticale de chaque colonne sp\u00e9cifi\u00e9e.<\/li>\n<li><strong>Calcul global sur la table enti\u00e8re :<\/strong> <em>df.median(numeric_only=True)<\/em> \u2014 Traite l&rsquo;ensemble de la matrice en restreignant l&rsquo;op\u00e9ration aux types num\u00e9riques valides pour pr\u00e9venir les exceptions d&rsquo;incompatibilit\u00e9 de type.<\/li>\n<li><strong>Contr\u00f4le strict des donn\u00e9es manquantes :<\/strong> <em>df.median(numeric_only=True, skipna=False)<\/em> \u2014 Propage la valeur <em>NaN<\/em> si au moins une entr\u00e9e non valide est d\u00e9tect\u00e9e au sein du vecteur analys\u00e9.<\/li>\n<li><strong>Calcul transversal par observation (horizontal) :<\/strong> <em>df.median(axis=1, numeric_only=True)<\/em> \u2014 R\u00e9duit les colonnes pour chaque ligne, produisant une estimation m\u00e9diane propre \u00e0 chaque observation ou sujet.<\/li>\n<li><strong>Agr\u00e9gation conditionnelle par groupe :<\/strong> <em>df.groupby(&lsquo;facteur&rsquo;)[&lsquo;colonne&rsquo;].median()<\/em> \u2014 Segmente la cohorte selon une variable cat\u00e9gorielle et retourne la m\u00e9diane sp\u00e9cifique de chaque modalit\u00e9.<\/li>\n<li><strong>Projection et centrage robuste :<\/strong> <em>df.groupby(&lsquo;facteur&rsquo;)[&lsquo;colonne&rsquo;].transform(&lsquo;median&rsquo;)<\/em> \u2014 Aligne la m\u00e9diane de groupe sur chaque observation individuelle sans alt\u00e9rer les dimensions du <em>DataFrame<\/em>.<\/li>\n<li><strong>Multi-agr\u00e9gation descriptive compl\u00e8te :<\/strong> <em>df.groupby(&lsquo;facteur&rsquo;)[&lsquo;colonne&rsquo;].agg([&lsquo;median&rsquo;, &lsquo;mean&rsquo;, &lsquo;std&rsquo;])<\/em> \u2014 G\u00e9n\u00e8re une table synth\u00e9tique multidimensionnelle comparant la m\u00e9diane aux m\u00e9triques de tendance centrale et de dispersion classiques.<\/li>\n<\/ul>\n<p>La ma\u00eetrise rigoureuse de ces commandes et de leurs fondements th\u00e9oriques garantit \u00e0 l&rsquo;analyste de donn\u00e9es une manipulation pr\u00e9cise, performante et scientifiquement reproductible des m\u00e9triques de tendance centrale sur l&rsquo;ensemble de ses projets analytiques sous Python.<\/p>\n<h2>R\u00e9f\u00e9rences<\/h2>\n<ul>\n<li>Harris, C. R., Millman, K. J., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., &#8230; &amp; Oliphant, T. E. (2020). Array programming with NumPy. <em>Nature<\/em>, 585(7825), 357-362. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1038\/s41586-020-2649-2\">https:\/\/doi.org\/10.1038\/s41586-020-2649-2<\/a><\/li>\n<li>Huber, P. J. (2004). <em>Robust statistics<\/em>. John Wiley &amp; Sons. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1002\/0471725250\">https:\/\/doi.org\/10.1002\/0471725250<\/a><\/li>\n<li>McKinney, W. (2010). Data structures for statistical computing in Python. In <em>Proceedings of the 9th Python in Science Conference<\/em> (Vol. 445, pp. 51-56). <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.25080\/Majora-92bf1924-003\">https:\/\/doi.org\/10.25080\/Majora-92bf1924-003<\/a><\/li>\n<li>McKinney, W. (2022). <em>Python for data analysis: Data wrangling with pandas, NumPy, and Jupyter<\/em> (3rd ed.). O&rsquo;Reilly Media. <a rel=\"noopener noreferrer\" href=\"https:\/\/wesmckinney.com\/book\/\">https:\/\/wesmckinney.com\/book\/<\/a><\/li>\n<li>Pandas Development Team. (2024). <em>pandas documentation: pandas.DataFrame.median<\/em>. PyData. <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/docs\/reference\/api\/pandas.DataFrame.median.html\">https:\/\/pandas.pydata.org\/docs\/reference\/api\/pandas.DataFrame.median.html<\/a><\/li>\n<li>Rousseeuw, P. J., &amp; Leroy, A. M. (2005). <em>Robust regression and outlier detection<\/em>. John Wiley &amp; Sons. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1002\/0471725382\">https:\/\/doi.org\/10.1002\/0471725382<\/a><\/li>\n<li>Tukey, J. W. (1977). <em>Exploratory data analysis<\/em>. Addison-Wesley. <a rel=\"noopener noreferrer\" href=\"https:\/\/www.pearson.com\/en-us\/subject-catalog\/p\/exploratory-data-analysis\/P200000006346\">https:\/\/www.pearson.com\/en-us\/subject-catalog\/p\/exploratory-data-analysis\/P200000006346<\/a><\/li>\n<li>Virtanen, P., Gommers, R., Oliphant, T. E., Haberland, M., Reddy, T., Cournapeau, D., &#8230; &amp; SciPy 1.0 Contributors. (2020). SciPy 1.0: fundamental algorithms for scientific computing in Python. <em>Nature Methods<\/em>, 17(3), 261-272. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1038\/s41592-019-0686-2\">https:\/\/doi.org\/10.1038\/s41592-019-0686-2<\/a><\/li>\n<li>Wickham, H. (2011). The split-apply-combine strategy for data analysis. <em>Journal of Statistical Software<\/em>, 40(1), 1-29. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.18637\/jss.v040.i01\">https:\/\/doi.org\/10.18637\/jss.v040.i01<\/a><\/li>\n<li>Wilcox, R. R. (2012). <em>Introduction to robust estimation and hypothesis testing<\/em> (3rd ed.). Academic Press. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1016\/C2010-0-67044-1\">https:\/\/doi.org\/10.1016\/C2010-0-67044-1<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Guide acad\u00e9mique et pratique pour calculer la m\u00e9diane dans Pandas : analyse de colonnes uniques ou multiples, gestion des valeurs manquantes et groupby.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","categories":[2465,2464],"tags":[1884,1966,2466,2468,2344],"class_list":["post-1962","psych_stat","type-psych_stat","status-publish","hentry","category-programmation-python","category-science-des-donnees","tag-analyse-de-donnees","tag-mediane","tag-pandas","tag-python","tag-statistiques"],"_links":{"self":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/1962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat"}],"about":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/types\/psych_stat"}],"author":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1962"}],"version-history":[{"count":1,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/1962\/revisions"}],"predecessor-version":[{"id":16293,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/1962\/revisions\/16293"}],"wp:attachment":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}