{"id":6050,"date":"2026-10-14T18:02:04","date_gmt":"2026-10-14T18:02:04","guid":{"rendered":"http:\/\/french.arabpsychology.com\/statistics\/comment-calculer-mode-tableau-numpy-exemples\/"},"modified":"2026-10-14T18:02:04","modified_gmt":"2026-10-14T18:02:04","slug":"comment-calculer-mode-tableau-numpy-exemples","status":"publish","type":"psych_stat","link":"https:\/\/french.arabpsychology.com\/?psych_stat=comment-calculer-mode-tableau-numpy-exemples","title":{"rendered":"Comment calculer le mode d&rsquo;un tableau NumPy (avec exemples)"},"content":{"rendered":"<p>Dans le paysage du calcul scientifique et de l&rsquo;analyse exploratoire de donn\u00e9es contemporaine, la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/\">NumPy<\/a> s&rsquo;impose comme le socle fondamental sur lequel repose l&rsquo;ensemble de l&rsquo;\u00e9cosyst\u00e8me num\u00e9rique Python. Gr\u00e2ce \u00e0 son objet central, le tableau multidimensionnel homog\u00e8ne d\u00e9sign\u00e9 sous le terme de <code>ndarray<\/code>, NumPy offre des primitives de calcul matriciel d&rsquo;une efficacit\u00e9 critique, ex\u00e9cut\u00e9es au plus pr\u00e8s du mat\u00e9riel sous-jacent gr\u00e2ce \u00e0 des liaisons internes optimis\u00e9es en C et en Fortran. Les scientifiques, chercheurs et ing\u00e9nieurs des donn\u00e9es mobilisent continuellement cette infrastructure pour quantifier des ph\u00e9nom\u00e8nes complexes, r\u00e9sumer des populations statistiques et mod\u00e9liser des syst\u00e8mes stochastiques \u00e0 grande \u00e9chelle.<\/p>\n<p>Toutefois, lorsqu&rsquo;il s&rsquo;agit de caract\u00e9riser les propri\u00e9t\u00e9s fondamentales d&rsquo;une distribution \u00e0 travers les trois piliers canoniques de la statistique descriptive que sont la moyenne arithm\u00e9tique, la m\u00e9diane et le mode, les praticiens se heurtent \u00e0 une asym\u00e9trie d&rsquo;impl\u00e9mentation notable. Si les deux premi\u00e8res m\u00e9triques b\u00e9n\u00e9ficient de fonctions intrins\u00e8ques vectoris\u00e9es, rapides et hautement param\u00e9trables, respectivement <code>numpy.mean<\/code> et <code>numpy.median<\/code>, la recherche de la valeur la plus fr\u00e9quente est \u00e9trangement orpheline d&rsquo;une fonction native directe. Cette absence apparente suscite fr\u00e9quemment des interrogations, voire une perplexit\u00e9 l\u00e9gitime, chez les analystes confront\u00e9s \u00e0 la n\u00e9cessit\u00e9 d&rsquo;extraire la tendance dominante de leurs tenseurs de donn\u00e9es.<\/p>\n<p>Cette omission n&rsquo;est nullement le fruit d&rsquo;une n\u00e9gligence des concepteurs, mais proc\u00e8de d&rsquo;une r\u00e9flexion architecturale d\u00e9lib\u00e9r\u00e9e, ancr\u00e9e dans la distinction entre les types de donn\u00e9es fondamentaux, la s\u00e9mantique formelle de la multimodalit\u00e9 et la modularit\u00e9 inh\u00e9rente \u00e0 la suite scientifique SciPy. Comprendre comment calculer le mode d&rsquo;un tableau NumPy requiert d\u00e8s lors une exploration approfondie des m\u00e9canismes vectoriels, des particularit\u00e9s algorithmiques du tri, de l&rsquo;indexation bool\u00e9enne et des subtilit\u00e9s arithm\u00e9tiques de la norme IEEE 754. Le pr\u00e9sent trait\u00e9 fournit une analyse exhaustive, rigoureuse et formalis\u00e9e des techniques permettant de d\u00e9terminer le mode au sein de tableaux NumPy, allant des paradigmes de base aux architectures de haute performance pour le traitement massif de donn\u00e9es.<\/p>\n<h2>1. Introduction \u00e0 la statistique descriptive et au concept de mode dans les tableaux NumPy<\/h2>\n<p>La statistique descriptive constitue le premier niveau d&rsquo;appr\u00e9hension math\u00e9matique d&rsquo;un ensemble de donn\u00e9es brutes. Elle vise \u00e0 synth\u00e9tiser une grande quantit\u00e9 d&rsquo;informations \u00e0 travers un ensemble restreint d&rsquo;indicateurs quantitatifs capables de r\u00e9sumer la distribution des valeurs observ\u00e9es, d&rsquo;\u00e9valuer leur dispersion et de quantifier d&rsquo;\u00e9ventuelles asym\u00e9tries structurelles.<\/p>\n<h3>1.1 D\u00e9finition math\u00e9matique et propri\u00e9t\u00e9s fondamentales du mode<\/h3>\n<p>Sur le plan de la th\u00e9orie des probabilit\u00e9s et de la statistique descriptive univari\u00e9e, le mode d&rsquo;une variable al\u00e9atoire discr\u00e8te correspond formellement \u00e0 la valeur d&rsquo;une distribution dont la probabilit\u00e9 d&rsquo;occurrence, ou la fr\u00e9quence absolue au sein d&rsquo;un \u00e9chantillon fini, est maximale. Soit un \u00e9chantillon fini repr\u00e9sent\u00e9 par un ensemble de <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> observations <span class=\"arabpsy-math-inline\" data-latex=\"{x_1, x_2, dots, x_N}\">${x_1, x_2, dots, x_N}$<\/span>. Le mode, couramment d\u00e9sign\u00e9 par la notation <span class=\"arabpsy-math-inline\" data-latex=\"M_o\">$M_o$<\/span>, est formellement d\u00e9fini comme la valeur <span class=\"arabpsy-math-inline\" data-latex=\"x\">$x$<\/span> appartenant \u00e0 l&rsquo;espace d&rsquo;\u00e9tat de l&rsquo;\u00e9chantillon satisfaisant la condition d&rsquo;optimalit\u00e9 suivante :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"M_o = arg\\max_{x in \\mathcal{X}} \\sum_{i=1}^N \\mathbf{1}_{{x_i = x}}\">$$M_o = arg\\max_{x in \\mathcal{X}} \\sum_{i=1}^N \\mathbf{1}_{{x_i = x}}$$<\/span><\/p>\n<p>o\u00f9 <span class=\"arabpsy-math-inline\" data-latex=\"\\mathbf{1}\">$\\mathbf{1}$<\/span> d\u00e9signe la fonction indicatrice et <span class=\"arabpsy-math-inline\" data-latex=\"\\mathcal{X}\">$\\mathcal{X}$<\/span> repr\u00e9sente l&rsquo;ensemble des valeurs uniques distinctes pr\u00e9sentes dans le vecteur d&rsquo;observations. Contrairement \u00e0 la moyenne arithm\u00e9tique, qui est un op\u00e9rateur barycentrique sensible aux valeurs extr\u00eames et exigeant une \u00e9chelle d&rsquo;intervalle ou de rapport, et \u00e0 la m\u00e9diane, qui repose sur une relation d&rsquo;ordre lin\u00e9aire stricte n\u00e9cessitant au minimum une \u00e9chelle ordinale, le mode est la seule m\u00e9trique de tendance centrale universellement d\u00e9finie pour tous les types de donn\u00e9es selon la typologie de Stevens. Il poss\u00e8de ainsi une pertinence heuristique majeure pour les variables qualitatives nominales, o\u00f9 les notions d&rsquo;addition et de classement s\u00e9quentiel sont d\u00e9nu\u00e9es de sens physique.<\/p>\n<p>Dans le contexte des distributions asym\u00e9triques, l&rsquo;\u00e9cart spatial et quantitatif s\u00e9parant la moyenne, la m\u00e9diane et le mode permet de diagnostiquer imm\u00e9diatement la nature du biais distributionnel. Dans une distribution pr\u00e9sentant une asym\u00e9trie positive prononc\u00e9e, la moyenne est syst\u00e9matiquement entra\u00een\u00e9e vers la longue queue de distribution par les valeurs atypiques \u00e9lev\u00e9es, suivie par la m\u00e9diane, tandis que le mode demeure ancr\u00e9 sur le pic de densit\u00e9 locale. Cette r\u00e9silience intrins\u00e8que du mode face aux valeurs aberrantes (outliers) en fait un outil diagnostique robuste lorsque l&rsquo;analyste cherche \u00e0 d\u00e9terminer le comportement typique d&rsquo;une population plut\u00f4t que son centre de gravit\u00e9 math\u00e9matique.<\/p>\n<h3>1.2 N\u00e9cessit\u00e9 de l&rsquo;analyse du mode en programmation scientifique<\/h3>\n<p>Au sein des pipelines de mod\u00e9lisation pr\u00e9dictive, d&rsquo;apprentissage automatique et d&rsquo;ing\u00e9nierie des donn\u00e9es, la recherche du mode remplit plusieurs fonctions critiques. En premier lieu, dans l&rsquo;analyse de cohortes exp\u00e9rimentales et d&rsquo;enqu\u00eates sociologiques ou m\u00e9dicales, l&rsquo;identification de la r\u00e9ponse modale permet d&rsquo;isoler sans ambigu\u00eft\u00e9 le profil typique d&rsquo;un patient ou d&rsquo;un utilisateur. Lorsqu&rsquo;un syst\u00e8me physique ou biologique \u00e9volue entre diff\u00e9rents \u00e9tats d&rsquo;\u00e9quilibre m\u00e9tastables, le calcul du mode dans les s\u00e9ries temporelles correspondantes r\u00e9v\u00e8le les attracteurs dominants du syst\u00e8me dynamique \u00e9tudi\u00e9, c&rsquo;est-\u00e0-dire les configurations d&rsquo;\u00e9nergie minimale au sein desquelles le syst\u00e8me passe la majeure partie de sa trajectoire de phase.<\/p>\n<p>En second lieu, l&rsquo;extraction de la valeur dominante constitue le fondement des protocoles d&rsquo;imputation univari\u00e9e des donn\u00e9es manquantes. Lorsqu&rsquo;un jeu de donn\u00e9es tabulaire pr\u00e9sente des valeurs nulles ou non renseign\u00e9es au sein d&rsquo;une variable cat\u00e9gorielle discr\u00e8te, telle qu&rsquo;un diagnostic m\u00e9dical codifi\u00e9, l&rsquo;imputation par la moyenne arithm\u00e9tique est math\u00e9matiquement impossible ou g\u00e9n\u00e8re des valeurs d\u00e9cimales absurdes d\u00e9pourvues de signification ontologique. L&rsquo;application du mode permet de restaurer la compl\u00e9tude structurelle de la matrice sans alt\u00e9rer le domaine de d\u00e9finition de la variable ni injecter de variance artificielle dans les mod\u00e8les d&rsquo;inf\u00e9rence en aval.<\/p>\n<p>Enfin, dans le domaine du traitement d&rsquo;images num\u00e9riques et du traitement du signal, les filtres bas\u00e9s sur le mode local permettent d&rsquo;\u00e9liminer le bruit impulsionnel tout en pr\u00e9servant la nettet\u00e9 des discontinuit\u00e9s g\u00e9om\u00e9triques, surpassant fr\u00e9quemment les performances des filtres de convolution gaussiens traditionnels qui tendent \u00e0 estomper les contours critiques en moyennant indistinctement les pixels adjacents.<\/p>\n<h3>1.3 L&rsquo;\u00e9cosyst\u00e8me NumPy et la gestion vectorielle des fr\u00e9quences<\/h3>\n<p>Pour comprendre les modalit\u00e9s de calcul du mode en Python scientifique, il est imp\u00e9ratif d&rsquo;examiner l&rsquo;architecture interne des structures de donn\u00e9es manipul\u00e9es par la biblioth\u00e8que NumPy. L&rsquo;objet fondamental <code>numpy.ndarray<\/code> se distingue structurellement des listes natives de Python en ce qu&rsquo;il encapsule un bloc contigu de m\u00e9moire allou\u00e9 dynamiquement, associ\u00e9 \u00e0 des m\u00e9tadonn\u00e9es strictes d\u00e9crivant le type d&rsquo;\u00e9l\u00e9ment homog\u00e8ne (<code>dtype<\/code>), la forme dimensionnelle (<code>shape<\/code>) et les pas de progression m\u00e9moire le long de chaque axe (<code>strides<\/code>). Cette contigu\u00eft\u00e9 physique permet d&rsquo;exploiter pleinement les registres vectoriels SIMD des architectures de microprocesseurs modernes et d&rsquo;\u00e9liminer la surcharge colossale li\u00e9e \u00e0 l&rsquo;instanciation des objets Python.<\/p>\n<p>Cependant, le comptage des fr\u00e9quences d&rsquo;apparition d&rsquo;\u00e9l\u00e9ments au sein d&rsquo;une structure vectorielle pose un d\u00e9fi computationnel singulier. Dans le paradigme imp\u00e9ratif classique, le d\u00e9nombrement des occurrences s&rsquo;effectue au moyen d&rsquo;une table de hachage ou d&rsquo;un dictionnaire it\u00e9ratif. En Python pur, ce processus implique des allers-retours constants entre la machine virtuelle, le ramasse-miettes et le ramassage des types dynamiques, ce qui d\u00e9grade consid\u00e9rablement les d\u00e9bits de traitement lorsque la taille de l&rsquo;\u00e9chantillon franchit le seuil des centaines de milliers d&rsquo;\u00e9l\u00e9ments.<\/p>\n<p>L&rsquo;\u00e9cosyst\u00e8me NumPy compense l&rsquo;absence d&rsquo;une instruction \u00e9l\u00e9mentaire unique par des primitives vectoris\u00e9es d&rsquo;agr\u00e9gation et de tri hautement optimis\u00e9es, telles que <code>np.unique<\/code> et <code>np.bincount<\/code>. Ces fonctions d\u00e9portent la totalit\u00e9 du travail d&rsquo;it\u00e9ration et de comparaison au niveau du code compil\u00e9 sous-jacent en C, permettant d&rsquo;effectuer des calculs d&rsquo;histogrammes et d&rsquo;isoler les maximas de distribution avec une empreinte temporelle minimale, \u00e0 la condition expresse que l&rsquo;analyste comprenne pr\u00e9cis\u00e9ment les m\u00e9canismes internes r\u00e9gissant la manipulation des indices et la r\u00e9solution des conflits de fr\u00e9quence.<\/p>\n<h2>2. Pourquoi NumPy ne poss\u00e8de pas de fonction np.mode directe<\/h2>\n<p>Une question r\u00e9currente parmi les ing\u00e9nieurs et chercheurs manipulant des donn\u00e9es num\u00e9riques concerne l&rsquo;absence apparente d&rsquo;une m\u00e9thode unifi\u00e9e <code>numpy.mode<\/code> dans l&rsquo;espace de noms principal de la biblioth\u00e8que, contrastant avec l&rsquo;omnipr\u00e9sence de <code>numpy.mean<\/code>, <code>numpy.median<\/code>, <code>numpy.std<\/code> et <code>numpy.var<\/code>.<\/p>\n<h3>2.1 Philosophie de conception et s\u00e9paration des responsabilit\u00e9s dans SciPy\/NumPy<\/h3>\n<p>La raison premi\u00e8re de cette dichotomie r\u00e9side dans l&rsquo;histoire architecturale et la d\u00e9limitation stricte du champ d&rsquo;application de NumPy par rapport \u00e0 l&rsquo;\u00e9cosyst\u00e8me plus vaste h\u00e9berg\u00e9 sous l&rsquo;\u00e9gide du consortium <a rel=\"noopener noreferrer\" href=\"https:\/\/scipy.org\/\">SciPy<\/a>. D\u00e8s la formalisation de NumPy par Travis Oliphant en 2005, une d\u00e9cision fondamentale de gouvernance technique a \u00e9t\u00e9 arr\u00eat\u00e9e : NumPy devait demeurer le moteur de calcul matriciel minimal, compact et robuste du monde Python, en concentrant ses efforts exclusifs sur l&rsquo;alg\u00e8bre lin\u00e9aire fondamentale, les transformations de Fourier, la manipulation des formes tensorielles et les op\u00e9rations arithm\u00e9tiques par \u00e9l\u00e9ments.<\/p>\n<p>Toutes les routines statistiques avanc\u00e9es, les m\u00e9thodes d&rsquo;inf\u00e9rence, les tests d&rsquo;hypoth\u00e8ses et les fonctions d&rsquo;estimation de densit\u00e9s ont \u00e9t\u00e9 explicitement d\u00e9volues \u00e0 la biblioth\u00e8que sp\u00e9cialis\u00e9e <code>scipy.stats<\/code>. L&rsquo;incorporation d&rsquo;une fonction de mode au sein du noyau C de NumPy aurait n\u00e9cessit\u00e9 l&rsquo;int\u00e9gration de biblioth\u00e8ques annexes de gestion de structures de donn\u00e9es dynamiques plus complexes, augmentant la surface de maintenance logicielle, complexifiant la compilation crois\u00e9e sur des plateformes mat\u00e9rielles exotiques et alourdissant inutilement l&#8217;empreinte m\u00e9moire du package de base pour des op\u00e9rations qui rel\u00e8vent conceptuellement de la mod\u00e9lisation statistique inf\u00e9rentielle plut\u00f4t que de l&rsquo;alg\u00e8bre vectorielle pure.<\/p>\n<h3>2.2 L&rsquo;ambigu\u00eft\u00e9 math\u00e9matique du mode dans les distributions multidimensionnelles<\/h3>\n<p>Au-del\u00e0 des consid\u00e9rations logicielles, la principale justification de cette absence rel\u00e8ve de l&rsquo;ambigu\u00eft\u00e9 math\u00e9matique inh\u00e9rente \u00e0 la nature m\u00eame du mode. Contrairement \u00e0 la moyenne arithm\u00e9tique ou \u00e0 la m\u00e9diane le long d&rsquo;une tranche ordonn\u00e9e, qui poss\u00e8dent l&rsquo;assurance formelle d&rsquo;une existence scalaire unique au sein des espaces r\u00e9els continus ou discrets (\u00e0 une convention pr\u00e8s pour la m\u00e9diane paire), le mode n&rsquo;est pas une fonction injective et souffre fr\u00e9quemment de non-unicit\u00e9.<\/p>\n<p>Une distribution peut ais\u00e9ment \u00eatre bimodale, trimodale ou uniform\u00e9ment plate. Dans ce dernier sc\u00e9nario, chaque \u00e9l\u00e9ment distinct n&rsquo;appara\u00eet qu&rsquo;une seule fois, conf\u00e9rant th\u00e9oriquement \u00e0 l&rsquo;ensemble du support exp\u00e9rimental le statut de mode. Si NumPy impl\u00e9mentait une fonction scalaire retournant aveugl\u00e9ment une valeur unique, quel crit\u00e8re d&rsquo;arbitrage devrait \u00eatre adopt\u00e9 ? Devrait-on renvoyer la plus petite valeur observ\u00e9e, la premi\u00e8re survenue chronologiquement dans la s\u00e9quence d&rsquo;entr\u00e9e, la valeur la plus proche de la moyenne, ou lever une exception d&rsquo;ex\u00e9cution ?<\/p>\n<p>Cette complexit\u00e9 devient exponentielle lors de l&rsquo;application de r\u00e9ductions tensorielles le long d&rsquo;axes sp\u00e9cifiques au sein de matrices d&rsquo;ordre sup\u00e9rieur. Consid\u00e9rons un tenseur tridimensionnel de dimension <span class=\"arabpsy-math-inline\" data-latex=\"M \\times N \\times P\">$M \\times N \\times P$<\/span>. La r\u00e9duction le long de l&rsquo;axe z\u00e9ro peut g\u00e9n\u00e9rer, pour certaines cellules de la matrice de sortie de dimension <span class=\"arabpsy-math-inline\" data-latex=\"N \\times P\">$N \\times P$<\/span>, un mode unique, tandis que d&rsquo;autres cellules pr\u00e9sentent simultan\u00e9ment trois modes concurrents de m\u00eame fr\u00e9quence maximale. Un tableau NumPy ayant par d\u00e9finition une forme dimensionnelle rectangulaire rigide et un type homog\u00e8ne, il est structurellement incapable d&rsquo;h\u00e9berger des cellules contenant des scalaires c\u00f4te \u00e0 c\u00f4te avec des sous-tableaux de longueurs variables sans forcer l&rsquo;utilisation de tableaux d&rsquo;objets (<code>dtype=object<\/code>), ce qui an\u00e9antit instantan\u00e9ment tous les b\u00e9n\u00e9fices de la vectorisation. Les concepteurs ont donc pr\u00e9f\u00e9r\u00e9 obliger les d\u00e9veloppeurs \u00e0 expliciter math\u00e9matiquement leurs intentions algorithmiques en assemblant des op\u00e9rations primitives adapt\u00e9es \u00e0 leurs hypoth\u00e8ses de recherche.<\/p>\n<h2>3. M\u00e9thode canonique : utilisation de np.unique avec return_counts<\/h2>\n<p>Pour calculer le mode d&rsquo;un tableau unidimensionnel en restant strictement confin\u00e9 au p\u00e9rim\u00e8tre de NumPy, la m\u00e9thodologie la plus standard, \u00e9l\u00e9gante et universellement applicable repose sur la combinaison synergique de la fonction <code>np.unique<\/code> et des op\u00e9rateurs d&rsquo;extraction d&rsquo;indices extremums.<\/p>\n<h3>3.1 D\u00e9composition algorithmique de np.unique<\/h3>\n<p>La primitive <code>numpy.unique<\/code> op\u00e8re une transformation fondamentale sur le tenseur d&rsquo;entr\u00e9e : elle r\u00e9duit l&rsquo;ensemble des \u00e9l\u00e9ments \u00e0 ses constituants mutuellement exclusifs tout en offrant la possibilit\u00e9 de quantifier pr\u00e9cis\u00e9ment le nombre d&rsquo;occurrences associ\u00e9 \u00e0 chacun de ces constituants gr\u00e2ce \u00e0 l&rsquo;activation du param\u00e8tre formel <code>return_counts=True<\/code>. Le fonctionnement interne de cette fonction m\u00e9rite d&rsquo;\u00eatre diss\u00e9qu\u00e9 avec pr\u00e9cision pour comprendre ses implications en termes de performances d&rsquo;ex\u00e9cution.<\/p>\n<p>Lorsque <code>np.unique<\/code> est invoqu\u00e9e sur un tableau non structur\u00e9, l&rsquo;algorithme sous-jacent commence par aplatir implicitement la structure dimensionnelle si aucun axe sp\u00e9cifique n&rsquo;est stipul\u00e9. Ensuite, il soumet ce vecteur unidimensionnel \u00e0 une routine de tri interne ex\u00e9cut\u00e9e en C. Par d\u00e9faut, NumPy utilise l&rsquo;algorithme <a rel=\"noopener noreferrer\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Quicksort\">Quicksort<\/a> ou un d\u00e9riv\u00e9 hybride de type Introsort pour les types num\u00e9riques primaires, affichant une complexit\u00e9 temporelle asymptotique moyenne de l&rsquo;ordre de <span class=\"arabpsy-math-inline\" data-latex=\"O(N log N)\">$O(N log N)$<\/span>, o\u00f9 <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> repr\u00e9sente la cardinalit\u00e9 totale du tableau. Une fois le tableau rigoureusement ordonn\u00e9, les \u00e9l\u00e9ments identiques se retrouvent cantonn\u00e9s dans des segments m\u00e9moires contigus.<\/p>\n<p>L&rsquo;algorithme parcourt ensuite ce tableau ordonn\u00e9 en une seule passe lin\u00e9aire de complexit\u00e9 temporelle <span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span> afin d&rsquo;identifier les transitions d&rsquo;\u00e9tat, c&rsquo;est-\u00e0-dire les positions m\u00e9moires o\u00f9 la valeur de l&rsquo;\u00e9l\u00e9ment courant diff\u00e8re de celle de l&rsquo;\u00e9l\u00e9ment pr\u00e9c\u00e9dent. Les indices de ces transitions marquent \u00e0 la fois la d\u00e9limitation des valeurs uniques et permettent de d\u00e9duire, par simple soustraction arithm\u00e9tique des indices cons\u00e9cutifs, le d\u00e9compte exact des occurrences associ\u00e9es. La fonction renvoie alors un tuple compos\u00e9 de deux nouveaux tableaux NumPy contigus : le tableau ordonn\u00e9 des valeurs distinctes et le tableau des effectifs absolus correspondants.<\/p>\n<h3>3.2 Extraction de l&rsquo;indice maximal avec np.argmax et np.argwhere<\/h3>\n<p>D\u00e8s lors que le vecteur des fr\u00e9quences absolues a \u00e9t\u00e9 instanci\u00e9, la d\u00e9termination du mode se r\u00e9sume math\u00e9matiquement \u00e0 la recherche de la position occup\u00e9e par la fr\u00e9quence maximale au sein de ce sous-ensemble. \u00c0 cette \u00e9tape, deux chemins algorithmiques divergents s&rsquo;offrent au concepteur, en fonction des postulats th\u00e9oriques admis sur la distribution des donn\u00e9es.<\/p>\n<p>Si l&rsquo;analyste postule de mani\u00e8re cat\u00e9gorique que la distribution observ\u00e9e est strictement unimodale, ou s&rsquo;il accepte d\u00e9lib\u00e9r\u00e9ment de tronquer l&rsquo;analyse en ne capturant que le premier mode identifi\u00e9 chronologiquement dans l&rsquo;ordre de tri des valeurs, il fait appel \u00e0 la fonction <code>numpy.argmax<\/code>. Appliqu\u00e9e directement sur le tableau des fr\u00e9quences, cette fonction ex\u00e9cute une recherche s\u00e9quentielle ultra-rapide optimis\u00e9e par instructions vectorielles pour retourner l&rsquo;indice scalaire correspondant \u00e0 la premi\u00e8re occurrence de la valeur maximale observ\u00e9e. Ce processus op\u00e8re en temps lin\u00e9aire <span class=\"arabpsy-math-inline\" data-latex=\"O(K)\">$O(K)$<\/span>, o\u00f9 <span class=\"arabpsy-math-inline\" data-latex=\"K\">$K$<\/span> d\u00e9signe le nombre de valeurs uniques, ce qui est n\u00e9gligeable devant le co\u00fbt initial du tri.<\/p>\n<p>En revanche, dans une optique de rigueur scientifique o\u00f9 l&rsquo;hypoth\u00e8se de multimodalit\u00e9 ne peut \u00eatre \u00e9cart\u00e9e a priori, l&#8217;emploi de <code>np.argmax<\/code> s&rsquo;av\u00e8re m\u00e9thodologiquement dangereux. Il convient alors de recourir \u00e0 une comparaison matricielle vectoris\u00e9e coupl\u00e9e \u00e0 la fonction <code>numpy.argwhere<\/code> ou \u00e0 l&rsquo;op\u00e9rateur de condition bool\u00e9enne standard. En formulant l&rsquo;instruction logique <code>counts == np.max(counts)<\/code>, NumPy g\u00e9n\u00e8re instantan\u00e9ment un masque bool\u00e9en de m\u00eame dimension que le vecteur des d\u00e9comptes. L&rsquo;application de <code>np.argwhere<\/code> sur ce masque permet de collecter l&rsquo;ensemble exhaustif des indices pointant vers tous les \u00e9l\u00e9ments partageant ex \u00e6quo la fr\u00e9quence d&rsquo;apparition la plus \u00e9lev\u00e9e, garantissant ainsi qu&rsquo;aucun sommet de densit\u00e9 n&rsquo;est occult\u00e9 lors de l&rsquo;\u00e9valuation.<\/p>\n<h3>3.3 Reconstruction de la valeur modale \u00e0 partir des index filtr\u00e9s<\/h3>\n<p>La derni\u00e8re phase op\u00e9ratoire consiste \u00e0 r\u00e9tablir la correspondance bijective entre les indices critiques isol\u00e9s dans le vecteur des occurrences et les valeurs mat\u00e9rielles correspondantes stock\u00e9es dans le tableau des valeurs uniques g\u00e9n\u00e9r\u00e9 initialement par <code>np.unique<\/code>. Cette \u00e9tape met en jeu les m\u00e9canismes d&rsquo;indexation avanc\u00e9e (fancy indexing) de NumPy.<\/p>\n<p>Si la strat\u00e9gie unimodale a \u00e9t\u00e9 retenue, la valeur du mode s&rsquo;obtient simplement par l&rsquo;expression <code>valeurs[indice_max]<\/code>. L&rsquo;\u00e9l\u00e9ment ainsi extrait h\u00e9rite fid\u00e8lement du <code>dtype<\/code> sous-jacent du tableau d&rsquo;origine, qu&rsquo;il s&rsquo;agisse d&rsquo;un entier sign\u00e9, d&rsquo;un flottant double pr\u00e9cision ou d&rsquo;un encodage textuel. Si la strat\u00e9gie multimodale a \u00e9t\u00e9 d\u00e9ploy\u00e9e, l&rsquo;indexation par tableau d&rsquo;indices ou par masque bool\u00e9en produit un nouveau tableau NumPy contenant l&rsquo;ensemble des modes concurrents. Pour normaliser cette sortie et faciliter son int\u00e9gration dans des architectures logicielles tierces, il est courant d&rsquo;appliquer la m\u00e9thode <code>.flatten()<\/code> afin de garantir la dimensionnalit\u00e9 du conteneur r\u00e9sultant, voire de transf\u00e9rer ces entit\u00e9s vers les structures scalaires natives du langage h\u00f4te par le biais de l&rsquo;instruction <code>.tolist()<\/code>, pr\u00e9venant ainsi les probl\u00e8mes de s\u00e9rialisation ult\u00e9rieurs.<\/p>\n<h2>4. Calcul du mode d&rsquo;un tableau NumPy unimodal (Exemple pratique d\u00e9taill\u00e9)<\/h2>\n<p>Afin d&rsquo;ancrer ces d\u00e9veloppements th\u00e9oriques dans la r\u00e9alit\u00e9 pratique du d\u00e9veloppement logiciel, nous allons proc\u00e9der \u00e0 l&rsquo;\u00e9laboration d\u00e9taill\u00e9e et comment\u00e9e d&rsquo;un script d&rsquo;analyse statistique complet appliqu\u00e9 \u00e0 un \u00e9chantillon exp\u00e9rimental unidimensionnel unimodal.<\/p>\n<h3>4.1 Construction de l&rsquo;\u00e9chantillon exp\u00e9rimental<\/h3>\n<p>Imaginons un sc\u00e9nario de recherche op\u00e9rationnelle dans lequel nous mesurons le nombre de requ\u00eates simultan\u00e9es re\u00e7ues par une passerelle d&rsquo;acc\u00e8s r\u00e9seau au cours de diff\u00e9rents intervalles de temps discrets. Ce type de m\u00e9trique discr\u00e8te produit typiquement une distribution asym\u00e9trique orient\u00e9e \u00e0 droite o\u00f9 une charge sp\u00e9cifique se manifeste avec une r\u00e9currence notable.<\/p>\n<p>Nous initialisons notre tableau NumPy en important la biblioth\u00e8que conventionnellement sous l&rsquo;alias <code>np<\/code>. Nous instancions ensuite un vecteur unidimensionnel contenant des mesures de requ\u00eates r\u00e9seau sous forme d&rsquo;entiers cod\u00e9s sur 64 bits :<\/p>\n<p><code>import numpy as np<\/code><\/p>\n<p><code>echantillon = np.array([12, 15, 12, 18, 14, 12, 19, 15, 12, 22, 14, 12, 16], dtype=np.int64)<\/code><\/p>\n<p>L&rsquo;inspection pr\u00e9alable de notre jeu d&rsquo;\u00e9chantillons confirme que nous sommes en pr\u00e9sence d&rsquo;un tableau de treize observations enti\u00e8res. Un examen manuel trivial met en lumi\u00e8re la pr\u00e9pond\u00e9rance du nombre 12, qui appara\u00eet \u00e0 cinq reprises au sein de la s\u00e9quence, tandis que les autres valeurs ne se manifestent qu&rsquo;une ou deux fois chacune. L&rsquo;objectif est d\u00e9sormais de faire identifier cette structure de mani\u00e8re enti\u00e8rement automatis\u00e9e et vectoris\u00e9e par le moteur NumPy.<\/p>\n<h3>4.2 Ex\u00e9cution pas \u00e0 pas du script canonique<\/h3>\n<p>Nous d\u00e9roulons notre m\u00e9thodologie canonique en sollicitant en premier lieu la fonction de r\u00e9duction et de d\u00e9compte :<\/p>\n<p><code>valeurs_uniques, occurrences = np.unique(echantillon, return_counts=True)<\/code><\/p>\n<p>\u00c0 l&rsquo;issue de cette instruction, la variable <code>valeurs_uniques<\/code> contient le tableau tri\u00e9 des \u00e9l\u00e9ments sans r\u00e9p\u00e9tition : <code>array([12, 14, 15, 16, 18, 19, 22])<\/code>. Simultan\u00e9ment, la variable <code>occurrences<\/code> h\u00e9berge le tableau de dimension identique d\u00e9nombrant la fr\u00e9quence absolue associ\u00e9e \u00e0 chaque \u00e9l\u00e9ment distinct : <code>array([5, 2, 2, 1, 1, 1, 1])<\/code>.<\/p>\n<p>Nous proc\u00e9dons alors \u00e0 la d\u00e9termination de la valeur modale par d\u00e9tection de l&rsquo;indice de pr\u00e9pond\u00e9rance :<\/p>\n<p><code>indice_mode = np.argmax(occurrences)<\/code><br \/>\n<code>valeur_mode = valeurs_uniques[indice_mode]<\/code><br \/>\n<code>frequence_mode = occurrences[indice_mode]<\/code><\/p>\n<p>L&rsquo;instruction <code>np.argmax(occurrences)<\/code> inspecte le vecteur <code>[5, 2, 2, 1, 1, 1, 1]<\/code> et localise imm\u00e9diatement la position du maximum au niveau de l&rsquo;indice z\u00e9ro. En propageant cet indice dans le tableau <code>valeurs_uniques<\/code>, la valeur 12 est isol\u00e9e avec une fr\u00e9quence d&rsquo;occurrence \u00e9gale \u00e0 5. Le script parvient \u00e0 extraire avec une exactitude absolue le sommet de la distribution sans jamais avoir recours \u00e0 une boucle it\u00e9rative explicite de niveau utilisateur.<\/p>\n<h3>4.3 Interpr\u00e9tation quantitative du r\u00e9sultat<\/h3>\n<p>L&rsquo;\u00e9valuation quantitative des m\u00e9triques descriptives concurrentes sur ce m\u00eame jeu de donn\u00e9es permet de mettre en lumi\u00e8re la singularit\u00e9 informative apport\u00e9e par le mode. En soumettant notre \u00e9chantillon aux fonctions <code>np.mean(echantillon)<\/code> et <code>np.median(echantillon)<\/code>, nous obtenons une moyenne arithm\u00e9tique approximative de 14.85 et une m\u00e9diane statistique \u00e9tablie \u00e0 14.0.<\/p>\n<p>Dans ce sc\u00e9nario repr\u00e9sentatif, la moyenne est substantiellement tir\u00e9e vers le haut par les \u00e9v\u00e9nements rares de forte intensit\u00e9, en l&rsquo;occurrence les observations isol\u00e9es 19 et 22 requ\u00eates. La m\u00e9diane fournit un point de s\u00e9paration ordonn\u00e9, mais ne refl\u00e8te en rien le ph\u00e9nom\u00e8ne mat\u00e9riel sous-jacent : le serveur est programm\u00e9 et calibr\u00e9 de mani\u00e8re optimale pour fonctionner sous un r\u00e9gime de 12 requ\u00eates simultan\u00e9es, r\u00e9gime qui constitue l&rsquo;\u00e9tat stationnaire dominant de l&rsquo;infrastructure. Si les ing\u00e9nieurs d&rsquo;infrastructure dimensionnaient les ressources sur la base de la moyenne arithm\u00e9tique arrondie \u00e0 15, ils sur\u00e9valueraient syst\u00e9matiquement le besoin nominal d&rsquo;ex\u00e9cution de pr\u00e8s de 25% par rapport \u00e0 l&rsquo;\u00e9tat le plus probable du syst\u00e8me.<\/p>\n<h2>5. Gestion des distributions multimodales : d\u00e9tection exhaustive de plusieurs modes<\/h2>\n<p>L&rsquo;un des \u00e9cueils majeurs rencontr\u00e9s dans la litt\u00e9rature technique simplifi\u00e9e r\u00e9side dans la pr\u00e9somption syst\u00e9matique d&rsquo;unimodalit\u00e9. Dans les domaines des sciences exp\u00e9rimentales, de la g\u00e9n\u00e9tique des populations ou de l&rsquo;analyse du trafic Web, les distributions multimodales constituent la norme plut\u00f4t que l&rsquo;exception.<\/p>\n<h3>5.1 Ph\u00e9nom\u00e9nologie des distributions bivari\u00e9es et multivari\u00e9es<\/h3>\n<p>Une distribution est qualifi\u00e9e de bivari\u00e9e ou de multivari\u00e9e lorsqu&rsquo;elle r\u00e9sulte de l&rsquo;agr\u00e9gation non discrimin\u00e9e de plusieurs sous-populations r\u00e9gies par des param\u00e8tres directeurs distincts. Par exemple, l&rsquo;enregistrement des mesures biom\u00e9triques d&rsquo;une esp\u00e8ce au sein d&rsquo;une aire g\u00e9ographique sans distinction pr\u00e9alable du dimorphisme sexuel g\u00e9n\u00e8re classiquement une distribution bimodale de la masse corporelle, chaque pic correspondant \u00e0 la moyenne locale d&rsquo;un des deux sexes.<\/p>\n<p>Dans un tel contexte, r\u00e9duire arbitrairement la caract\u00e9risation de la tendance centrale \u00e0 une valeur unique via l&rsquo;application aveugle de <code>np.argmax<\/code> introduit un biais d&rsquo;\u00e9chantillonnage d\u00e9vastateur. Non seulement l&rsquo;analyste ignore l&rsquo;existence de la seconde sous-population, mais la s\u00e9lection op\u00e9r\u00e9e par <code>np.argmax<\/code> sera r\u00e9gie par des artefacts purement techniques, \u00e0 savoir le mode de tri interne sous-jacent qui privil\u00e9giera la valeur num\u00e9rique la plus basse ou la position m\u00e9moire initiale dans le tableau. Le protocole d&rsquo;extraction se doit donc d&rsquo;\u00eatre math\u00e9matiquement neutre et d&rsquo;adopter une formulation capable de capturer l&rsquo;ensemble des extrema de m\u00eame amplitude.<\/p>\n<h3>5.2 Impl\u00e9mentation d&rsquo;une routine de d\u00e9tection multimodale robuste<\/h3>\n<p>Pour construire une fonction p\u00e9renne, compatible avec n&rsquo;importe quelle distribution discr\u00e8te multidimensionnelle pr\u00e9alablement lin\u00e9aris\u00e9e, nous devons concevoir un algorithme reposant sur l&rsquo;\u00e9valuation vectorielle des pr\u00e9dicats logiques. La structure algorithmique s&rsquo;articule comme suit :<\/p>\n<p>1. D\u00e9composition du tableau en vecteurs de valeurs uniques et de comptages associ\u00e9s au moyen de <code>np.unique(..., return_counts=True)<\/code>.<br \/>\n2. Calcul de la fr\u00e9quence maximale absolue observ\u00e9e au sein du vecteur des effectifs via <code>np.max(occurrences)<\/code>.<br \/>\n3. G\u00e9n\u00e9ration d&rsquo;un vecteur logique d&rsquo;\u00e9galit\u00e9 stricte : <code>masque_modes = (occurrences == max_frequence)<\/code>.<br \/>\n4. Application de ce masque bool\u00e9en sur le tableau des valeurs uniques pour extraire le sous-ensemble exhaustif des composantes modales : <code>modes = valeurs_uniques[masque_modes]<\/code>.<\/p>\n<p>Cette logique garantit formellement que quel que soit le nombre de modes ex \u00e6quo pr\u00e9sents dans la structure d&rsquo;entr\u00e9e, la totalit\u00e9 des sommets de distribution sera pr\u00e9serv\u00e9e et renvoy\u00e9e sous la forme d&rsquo;un tableau NumPy d\u00e9di\u00e9, pr\u00eat pour des analyses structurales plus pouss\u00e9es.<\/p>\n<h3>5.3 Exemple concret avec tableau bimodal et trimodal<\/h3>\n<p>Pour valider exp\u00e9rimentalement cette architecture, synth\u00e9tisons un tableau exp\u00e9rimental comportant une multimodalit\u00e9 contr\u00f4l\u00e9e. D\u00e9finissons un \u00e9chantillon dans lequel les entiers 10 et 20 apparaissent chacun exactement quatre fois, tandis que les autres valeurs pr\u00e9sentent des fr\u00e9quences strictement inf\u00e9rieures :<\/p>\n<p><code>echantillon_bimodal = np.array([10, 5, 20, 10, 8, 20, 10, 20, 3, 10, 20, 7], dtype=np.int32)<\/code><\/p>\n<p>Appliquons notre proc\u00e9dure vectoris\u00e9e robuste :<\/p>\n<p><code>valeurs, comptes = np.unique(echantillon_bimodal, return_counts=True)<\/code><br \/>\n<code>frequence_maximale = np.max(comptes)<\/code><br \/>\n<code>modes_identifies = valeurs[comptes == frequence_maximale]<\/code><\/p>\n<p>L&rsquo;ex\u00e9cution de cette s\u00e9quence nous renvoie pour <code>modes_identifies<\/code> le tableau <code>array([10, 20])<\/code>, associ\u00e9 \u00e0 une fr\u00e9quence partag\u00e9e de 4 occurrences. Si nous avions utilis\u00e9 l&rsquo;instruction naive <code>valeurs[np.argmax(comptes)]<\/code>, le r\u00e9sultat aurait \u00e9t\u00e9 exclusivement le scalaire <code>10<\/code>, gommant int\u00e9gralement la nature bimodale du syst\u00e8me mesur\u00e9.<\/p>\n<p>Il est par ailleurs fondamental d&rsquo;analyser le cas limite canonique d&rsquo;une distribution uniform\u00e9ment plate, o\u00f9 tous les \u00e9l\u00e9ments poss\u00e8dent une cardinalit\u00e9 unitaire (par exemple un tableau g\u00e9n\u00e9r\u00e9 par <code>np.arange(10)<\/code>). Dans une telle configuration, <code>np.max(comptes)<\/code> prend la valeur 1, et l&rsquo;\u00e9valuation de l&rsquo;\u00e9galit\u00e9 logique s\u00e9lectionne la totalit\u00e9 des \u00e9l\u00e9ments du vecteur d&rsquo;origine. L&rsquo;algorithme retourne l&rsquo;int\u00e9gralit\u00e9 du tableau initial, signalant ainsi avec exactitude math\u00e9matique l&rsquo;absence de pic pr\u00e9pond\u00e9rant et confirmant que tous les \u00e9tats poss\u00e8dent la m\u00eame densit\u00e9 d&rsquo;occupation.<\/p>\n<h2>6. Calcul du mode le long d&rsquo;un axe sur des matrices multidimensionnelles (2D et plus)<\/h2>\n<p>Dans les applications r\u00e9elles de traitement matriciel, telles que l&rsquo;analyse spatio-temporelle ou l&rsquo;ing\u00e9nierie des caract\u00e9ristiques en apprentissage supervis\u00e9, les donn\u00e9es ne sont presque jamais restreintes \u00e0 des vecteurs unidimensionnels simples. Elles se pr\u00e9sentent sous la forme de matrices bidimensionnelles, de volumes d&rsquo;imagerie m\u00e9dicale 3D ou de tenseurs d&rsquo;ordre sup\u00e9rieur.<\/p>\n<h3>6.1 La probl\u00e9matique de l&rsquo;axe (axis=0 versus axis=1)<\/h3>\n<p>Lorsque des donn\u00e9es sont structur\u00e9es sous forme de matrice 2D, la s\u00e9mantique de l&rsquo;analyse statistique impose de pr\u00e9ciser le sens de progression le long duquel l&rsquo;agr\u00e9gation doit s&rsquo;op\u00e9rer. Dans le cadre conventionnel d&rsquo;une matrice d&rsquo;observations o\u00f9 les lignes repr\u00e9sentent des individus statistiques ind\u00e9pendants et les colonnes d\u00e9signent des variables mesur\u00e9es au cours du temps, deux questions analytiques distinctes se posent :<\/p>\n<p>Le calcul du mode selon l&rsquo;axe z\u00e9ro (<code>axis=0<\/code>) consiste \u00e0 op\u00e9rer une agr\u00e9gation transversale : pour chaque colonne individuelle, l&rsquo;algorithme calcule le mode \u00e0 travers l&rsquo;ensemble des lignes. Cette op\u00e9ration permet par exemple d&rsquo;identifier la r\u00e9ponse majoritaire de l&rsquo;ensemble d&rsquo;un groupe d&rsquo;individus \u00e0 une question pr\u00e9cise d&rsquo;un protocole d&rsquo;\u00e9valuation.<\/p>\n<p>\u00c0 l&rsquo;inverse, l&rsquo;\u00e9valuation du mode selon l&rsquo;axe un (<code>axis=1<\/code>) consiste \u00e0 projeter l&rsquo;agr\u00e9gation horizontalement le long des colonnes pour chaque ligne de mani\u00e8re autonome. Ce traitement permet d&rsquo;isoler le comportement pr\u00e9pond\u00e9rant ou l&rsquo;\u00e9tat le plus fr\u00e9quent pr\u00e9sent\u00e9 par un individu particulier au cours des multiples mesures de son historique exp\u00e9rimental.<\/p>\n<p>Or, la fonction <code>np.unique<\/code> souffre d&rsquo;une limitation architecturale majeure : elle ne permet pas d&rsquo;appliquer une r\u00e9duction statistique vectoris\u00e9e ind\u00e9pendante le long d&rsquo;un axe sp\u00e9cifique pour en extraire des d\u00e9comptes locaux sans modifier la g\u00e9om\u00e9trie globale du tableau. Si l&rsquo;on passe un argument <code>axis<\/code> \u00e0 <code>np.unique<\/code>, la fonction cherche les sous-tableaux ou lignes uniques compl\u00e8tes, et non pas le mode univari\u00e9 de chaque sous-vecteur individuel.<\/p>\n<h3>6.2 Solutions matricielles pures avec NumPy<\/h3>\n<p>Pour contourner cette contrainte g\u00e9om\u00e9trique tout en demeurant au sein du framework NumPy, plusieurs strat\u00e9gies algorithmiques peuvent \u00eatre d\u00e9ploy\u00e9es.<\/p>\n<p>La premi\u00e8re m\u00e9thode, d&rsquo;une grande flexibilit\u00e9 conceptuelle, repose sur la fonction <code>numpy.apply_along_axis<\/code>. Cette primitive prend en charge l&rsquo;orchestration interne des tranches de matrices multidimensionnelles en appliquant une fonction univari\u00e9e personnalis\u00e9e le long de l&rsquo;axe cibl\u00e9. Bien que cette approche pr\u00e9sente une syntaxe concise et propre, il convient de noter qu&rsquo;elle ne constitue pas une vectorisation mat\u00e9rielle pure au niveau C. En coulisses, <code>apply_along_axis<\/code> ex\u00e9cute une boucle s\u00e9quentielle dans la couche Python pour balayer les dimensions compl\u00e9mentaires, ce qui peut induire un surco\u00fbt computationnel notable lorsque la matrice comporte des dizaines de milliers de lignes.<\/p>\n<p>La seconde approche, hautement performante mais r\u00e9serv\u00e9e aux donn\u00e9es constitu\u00e9es de nombres entiers non n\u00e9gatifs born\u00e9s par un intervalle mod\u00e9r\u00e9, fait appel \u00e0 la vectorisation matricielle par encodage binaire ou \u00e0 la manipulation d&rsquo;histogrammes 2D. En projetant les dimensions discr\u00e8tes sur une grille creuse ou en adaptant les structures de d\u00e9compte, il devient possible d&rsquo;exploiter la puissance des calculs matriciels purs pour r\u00e9soudre la fr\u00e9quence maximale sur tous les axes en une passe m\u00e9moire unique.<\/p>\n<h3>6.3 D\u00e9monstration matricielle sur donn\u00e9es bidimensionnelles<\/h3>\n<p>Consid\u00e9rons la mise en \u0153uvre pratique de la premi\u00e8re approche au moyen d&rsquo;un encapsulateur modulaire. D\u00e9finissons une matrice de dimension <span class=\"arabpsy-math-inline\" data-latex=\"4 \\times 5\">$4 \\times 5$<\/span>, repr\u00e9sentant par exemple les notations discr\u00e8tes attribu\u00e9es par quatre juges \u00e0 cinq crit\u00e8res distincts :<\/p>\n<p><code>matrice_donnees = np.array([<br \/>\n    [1, 2, 2, 3, 2],<br \/>\n    [4, 4, 1, 4, 2],<br \/>\n    [3, 3, 3, 3, 1],<br \/>\n    [2, 5, 5, 2, 5]<br \/>\n])<\/code><\/p>\n<p>D\u00e9finissons une fonction univari\u00e9e charg\u00e9e d&rsquo;extraire le premier mode dominant d&rsquo;un segment unidimensionnel arbitraire :<\/p>\n<p><code>def extraire_mode_1d(vecteur):<br \/>\n    vals, counts = np.unique(vecteur, return_counts=True)<br \/>\n    return vals[np.argmax(counts)]<\/code><\/p>\n<p>Pour obtenir le profil modal de chaque juge (le long des colonnes, donc <code>axis=1<\/code>), nous sollicitons l&rsquo;op\u00e9rateur de r\u00e9duction de NumPy :<\/p>\n<p><code>modes_lignes = np.apply_along_axis(extraire_mode_1d, axis=1, arr=matrice_donnees)<\/code><\/p>\n<p>L&rsquo;\u00e9valuation produit le vecteur <code>array([2, 4, 3, 5])<\/code>. Pour la premi\u00e8re ligne, la valeur 2 appara\u00eet 3 fois et s&rsquo;impose logiquement. Pour la seconde ligne, le chiffre 4 est majoritaire. Pour la troisi\u00e8me ligne, le 3 pr\u00e9domine. Enfin, pour la quatri\u00e8me ligne, la valeur 5 l&#8217;emporte avec trois apparitions. Le tenseur r\u00e9sultant s&rsquo;int\u00e8gre harmonieusement dans les matrices de caract\u00e9ristiques subs\u00e9quentes, apportant une r\u00e9ponse synth\u00e9tique robuste aux probl\u00e9matiques de r\u00e9duction dimensionnelle transversale.<\/p>\n<h2>7. L&rsquo;alternative sp\u00e9cialis\u00e9e : scipy.stats.mode<\/h2>\n<p>Lorsque les exigences de d\u00e9veloppement imposent le traitement r\u00e9current d&rsquo;axes matriciels multidimensionnels ou que l&rsquo;on recherche une fonction standardis\u00e9e support\u00e9e par une suite scientifique majeure, la fonction <code>scipy.stats.mode<\/code> repr\u00e9sente l&rsquo;alternative canonique de r\u00e9f\u00e9rence.<\/p>\n<h3>7.1 Architecture et syntaxe de la fonction scipy.stats.mode<\/h3>\n<p>La biblioth\u00e8que <code>scipy.stats<\/code> h\u00e9berge un module d\u00e9di\u00e9 \u00e0 l&rsquo;inf\u00e9rence statistique contenant la fonction hautement optimis\u00e9e <code>mode<\/code>. Con\u00e7ue sp\u00e9cifiquement pour op\u00e9rer sur des structures <code>numpy.ndarray<\/code>, cette fonction int\u00e8gre nativement la gestion vectoris\u00e9e des axes multiples et le maintien optionnel des formes dimensionnelles via le param\u00e8tre <code>keepdims<\/code>.<\/p>\n<p>La signature standard de la fonction dans les versions contemporaines de SciPy se pr\u00e9sente sous la forme :<\/p>\n<p><code>scipy.stats.mode(a, axis=0, nan_policy='propagate', keepdims=None)<\/code><\/p>\n<p>L&rsquo;appel de cette routine ne retourne pas un simple scalaire ou un tableau nu, mais une structure de donn\u00e9es formalis\u00e9e sous la forme d&rsquo;un objet nomm\u00e9 <code>ModeResult<\/code>. Ce conteneur expose deux attributs vectoriels indissociables : <code>mode<\/code>, qui contient les valeurs modales extraites le long de l&rsquo;axe stipul\u00e9, et <code>count<\/code>, qui h\u00e9berge les effectifs d&rsquo;apparition correspondants. Cette dualit\u00e9 \u00e9limine toute ambigu\u00eft\u00e9 sur la repr\u00e9sentativit\u00e9 statistique du mode extrait, permettant \u00e0 l&rsquo;analyste de confronter imm\u00e9diatement la valeur modale \u00e0 son poids r\u00e9el au sein de la sous-population consid\u00e9r\u00e9e.<\/p>\n<p>Il importe de souligner une \u00e9volution syntaxique fondamentale introduite \u00e0 partir des versions 1.9 de SciPy : le param\u00e8tre <code>keepdims<\/code>, auparavant positionn\u00e9 implicitement \u00e0 <code>True<\/code>, doit d\u00e9sormais \u00eatre explicitement param\u00e9tr\u00e9 pour \u00e9viter des avertissements d&rsquo;obsolescence (DeprecationWarnings). Lorsque <code>keepdims=True<\/code> est activ\u00e9, la matrice r\u00e9sultante conserve un rang tensoriel strictement identique \u00e0 la matrice d&rsquo;origine, ins\u00e9rant des dimensions de longueur unitaire le long de l&rsquo;axe r\u00e9duit, ce qui simplifie consid\u00e9rablement les op\u00e9rations ult\u00e9rieures de diffusion (broadcasting).<\/p>\n<h3>7.2 Comportement face aux modes multiples dans SciPy<\/h3>\n<p>Un aspect critique de la fonction <code>scipy.stats.mode<\/code> concerne sa strat\u00e9gie d\u00e9terministe de r\u00e9solution des conflits d&rsquo;\u00e9quivalence en situation de multimodalit\u00e9. Les sp\u00e9cifications de SciPy stipulent de mani\u00e8re immuable que si plusieurs valeurs distinctes partagent la fr\u00e9quence d&rsquo;apparition maximale, l&rsquo;algorithme s\u00e9lectionne et renvoie syst\u00e9matiquement la plus petite valeur num\u00e9rique parmi l&rsquo;ensemble des modes ex \u00e6quo.<\/p>\n<p>Cette convention de conception logicielle assure la reproductibilit\u00e9 stricte des calculs, mais rec\u00e8le un risque \u00e9pist\u00e9mologique substantiel. Si une cohorte m\u00e9dicale pr\u00e9sente une distribution parfaitement bimodale avec deux concentrations massives de patients respectivement aux \u00e9chelons de s\u00e9v\u00e9rit\u00e9 1 et 5, <code>scipy.stats.mode<\/code> retournera invariablement l&rsquo;\u00e9chelon 1 sans \u00e9mettre le moindre avertissement d&rsquo;ex\u00e9cution (warning). L&rsquo;analyste non averti pourrait conclure de mani\u00e8re erron\u00e9e que la pathologie est b\u00e9nigne au sein de l&rsquo;\u00e9chantillon, alors qu&rsquo;une moiti\u00e9 exacte des effectifs se trouve en d\u00e9tresse critique. Il est donc fondamental de v\u00e9rifier la forme globale des histogrammes lorsque <code>scipy.stats.mode<\/code> est utilis\u00e9 dans des contextes d\u00e9cisionnels sensibles.<\/p>\n<h3>7.3 Benchmark comparatif : NumPy pur versus scipy.stats.mode<\/h3>\n<p>D&rsquo;un point de vue de l&rsquo;ing\u00e9nierie logicielle et de l&rsquo;optimisation des temps de calcul (profiling), le choix entre une solution NumPy pure bas\u00e9e sur <code>np.unique<\/code> et la fonction <code>scipy.stats.mode<\/code> d\u00e9pend \u00e9troitement de la volum\u00e9trie globale et de la dimensionnalit\u00e9 des tableaux trait\u00e9s.<\/p>\n<p>Sur des vecteurs unidimensionnels de taille interm\u00e9diaire (<span class=\"arabpsy-math-inline\" data-latex=\"10^3\">$10^3$<\/span> \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"10^5\">$10^5$<\/span> \u00e9l\u00e9ments), la m\u00e9thode canonique NumPy <code>valeurs[np.argmax(counts)]<\/code> s&rsquo;av\u00e8re fr\u00e9quemment plus rapide que <code>scipy.stats.mode<\/code> d&rsquo;un facteur 1.5 \u00e0 3. Ce diff\u00e9rentiel de performance s&rsquo;explique par la l\u00e9g\u00e8ret\u00e9 structurelle de NumPy, qui \u00e9vite le surco\u00fbt li\u00e9 aux v\u00e9rifications d\u00e9fensives d&rsquo;arguments, au traitement des m\u00e9tadonn\u00e9es de dimensionnalit\u00e9 et \u00e0 l&rsquo;instanciation de l&rsquo;objet formel <code>ModeResult<\/code> op\u00e9r\u00e9s par SciPy.<\/p>\n<p>En revanche, d\u00e8s lors que l&rsquo;on traite des matrices denses bidimensionnelles ou tridimensionnelles le long d&rsquo;un axe sp\u00e9cifique sans pouvoir exploiter <code>bincount<\/code>, <code>scipy.stats.mode<\/code> prend un avantage algorithmique \u00e9crasant. En s&rsquo;appuyant sur des routines de tri partiel hautement optimis\u00e9es compil\u00e9es en C et C++, SciPy \u00e9vite les boucles it\u00e9ratives de <code>np.apply_along_axis<\/code> et optimise drastiquement les acc\u00e8s \u00e0 la m\u00e9moire cache du processeur, rendant son ex\u00e9cution nettement plus performante sur des tenseurs volumineux multi-axes.<\/p>\n<h2>8. Calcul du mode sur des tableaux de nombres \u00e0 virgule flottante (Floats)<\/h2>\n<p>L&rsquo;\u00e9valuation du mode sur des variables quantitatives continues repr\u00e9sent\u00e9es informatiquement par des nombres \u00e0 virgule flottante (types <code>float32<\/code> et <code>float64<\/code>) constitue l&rsquo;un des d\u00e9fis les plus redoutables de l&rsquo;analyse num\u00e9rique.<\/p>\n<h3>8.1 L&rsquo;\u00e9cueil de la pr\u00e9cision machine (IEEE 754)<\/h3>\n<p>Sur le plan th\u00e9orique continu, la probabilit\u00e9 qu&rsquo;une variable al\u00e9atoire continue prenne exactement une valeur ponctuelle pr\u00e9cise est formellement nulle (<span class=\"arabpsy-math-inline\" data-latex=\"P(X = x) = 0\">$P(X = x) = 0$<\/span>). Dans le monde computationnel discret r\u00e9gi par la norme <a rel=\"noopener noreferrer\" href=\"https:\/\/standards.ieee.org\/\">IEEE 754<\/a>, les nombres r\u00e9els sont approch\u00e9s par une mantisse et un exposant binaire. En cons\u00e9quence directe de cette repr\u00e9sentation discr\u00e8te finie, des op\u00e9rations arithm\u00e9tiques math\u00e9matiquement \u00e9quivalentes produisent d&rsquo;infimes divergences au niveau des bits de poids faible.<\/p>\n<p>Si deux capteurs physiques mesurent une temp\u00e9rature identique de <span class=\"arabpsy-math-inline\" data-latex=\"23.4^circ\\text{C}\">$23.4^circ\\text{C}$<\/span>, des bruits d&rsquo;\u00e9chantillonnage infinit\u00e9simaux ou des conversions analogique-num\u00e9rique asynchrones peuvent g\u00e9n\u00e9rer en m\u00e9moire les valeurs scalaires <code>23.400000000000002<\/code> et <code>23.399999999999998<\/code>. Pour la fonction <code>np.unique<\/code>, qui s&rsquo;appuie sur une \u00e9galit\u00e9 binaire stricte, ces deux valeurs constituent des entit\u00e9s distinctes irr\u00e9conciliables. Ainsi, le calcul aveugle du mode sur un tableau dense de flottants non pr\u00e9trait\u00e9s renvoie g\u00e9n\u00e9ralement une distribution d\u00e9g\u00e9n\u00e9r\u00e9e o\u00f9 chaque \u00e9l\u00e9ment appara\u00eet exactement une seule fois, rendant la notion m\u00eame de mode op\u00e9rationnellement caduque.<\/p>\n<h3>8.2 Discr\u00e9tisation et regroupement en classes (Binning)<\/h3>\n<p>Pour extraire un mode robuste et repr\u00e9sentatif d&rsquo;une distribution de nombres r\u00e9els, il est imp\u00e9ratif d&rsquo;op\u00e9rer une discr\u00e9tisation contr\u00f4l\u00e9e de l&rsquo;espace continu, processus d\u00e9sign\u00e9 dans la litt\u00e9rature sous le terme de discr\u00e9tisation ou de partitionnement en classes (binning).<\/p>\n<p>La premi\u00e8re strat\u00e9gie de discr\u00e9tisation, simple et efficace, repose sur l&rsquo;arrondissement num\u00e9rique \u00e0 un nombre pr\u00e9d\u00e9termin\u00e9 de d\u00e9cimales significatives via la fonction <code>numpy.round<\/code>. En neutralisant les micro-fluctuations d&rsquo;arrondi machine, les mesures adjacentes sont fusionn\u00e9es au sein de valeurs scalaires discr\u00e8tes communes, sur lesquelles la routine canonique <code>np.unique<\/code> peut \u00eatre imm\u00e9diatement appliqu\u00e9e avec succ\u00e8s.<\/p>\n<p>La seconde strat\u00e9gie, plus formalis\u00e9e statistiquement, utilise la fonction <code>numpy.histogram<\/code>. Au lieu de rechercher une \u00e9galit\u00e9 de valeur stricte, l&rsquo;espace continu est segment\u00e9 en <span class=\"arabpsy-math-inline\" data-latex=\"B\">$B$<\/span> intervalles contigus r\u00e9guliers ou adaptatifs. Le code segmente la distribution, comptabilise les occurrences au sein de chaque intervalle et identifie l&rsquo;intervalle h\u00e9bergeant la fr\u00e9quence maximale :<\/p>\n<p><code>counts, bin_edges = np.histogram(flottants, bins='auto')<\/code><br \/>\n<code>max_bin_idx = np.argmax(counts)<\/code><br \/>\n<code>mode_intervalle = (bin_edges[max_bin_idx], bin_edges[max_bin_idx + 1])<\/code><br \/>\n<code>mode_centre = (bin_edges[max_bin_idx] + bin_edges[max_bin_idx + 1]) \/ 2.0<\/code><\/p>\n<p>Cette approche fournit une approximation solide de la zone de densit\u00e9 maximale, le centre de la classe modale constituant une approximation fiable de la valeur dominante continue.<\/p>\n<h3>8.3 Estimation par noyau de densit\u00e9 (KDE) pour variables continues<\/h3>\n<p>Pour les applications de haute pr\u00e9cision o\u00f9 le partitionnement en classes est jug\u00e9 trop arbitraire ou d\u00e9pendant de l&rsquo;origine de la grille de segmentation, la m\u00e9thodologie th\u00e9orique optimale consiste \u00e0 transiter vers l&rsquo;analyse fonctionnelle continue par le biais de l&rsquo;estimation de densit\u00e9 par noyau (Kernel Density Estimation ou KDE).<\/p>\n<p>Dans ce paradigme math\u00e9matique, chaque point de mesure r\u00e9el <span class=\"arabpsy-math-inline\" data-latex=\"x_i\">$x_i$<\/span> est remplac\u00e9 par une fonction de densit\u00e9 continue sym\u00e9trique centr\u00e9e en ce point, g\u00e9n\u00e9ralement une gaussienne d&rsquo;\u00e9cart-type <span class=\"arabpsy-math-inline\" data-latex=\"h\">$h$<\/span> (appel\u00e9 largeur de bande ou bandwidth). La superposition matricielle de ces noyaux \u00e9l\u00e9mentaires g\u00e9n\u00e8re une fonction de densit\u00e9 continue globale <span class=\"arabpsy-math-inline\" data-latex=\"\\hat{f}(x)\">$\\hat{f}(x)$<\/span> parfaitement diff\u00e9rentiable sur l&rsquo;ensemble de la droite r\u00e9elle. Le mode continu correspond alors rigoureusement au point d&rsquo;annulation de la d\u00e9riv\u00e9e premi\u00e8re de la fonction o\u00f9 la d\u00e9riv\u00e9e seconde est strictement n\u00e9gative :<\/p>\n<p><span class=\"arabpsy-math-display\" data-latex=\"\\hat{M}_o = arg\\max_{x in \\mathbb{R}} \\hat{f}(x) = arg\\max_{x in \\mathbb{R}} \\frac{1}{N h} \\sum_{i=1}^N K\\left(\\frac{x - x_i}{h}\\right)\">$$\\hat{M}_o = arg\\max_{x in \\mathbb{R}} \\hat{f}(x) = arg\\max_{x in \\mathbb{R}} \\frac{1}{N h} \\sum_{i=1}^N K\\left(\\frac{x &#8211; x_i}{h}\\right)$$<\/span><\/p>\n<p>Bien que cette m\u00e9thode n\u00e9cessite l&rsquo;appel \u00e0 des optimiseurs d&rsquo;optimisation non lin\u00e9aire (tels que ceux fournis par <code>scipy.optimize<\/code>) pour localiser le z\u00e9ro du gradient, elle constitue la seule formulation math\u00e9matiquement rigoureuse de la recherche du mode sur des distributions v\u00e9ritablement continues, affranchissant l&rsquo;analyse des biais li\u00e9s \u00e0 la taille des intervalles d&rsquo;histogramme.<\/p>\n<h2>9. Traitement des valeurs non num\u00e9riques, bool\u00e9ens et valeurs manquantes (NaN)<\/h2>\n<p>Les donn\u00e9es empiriques brutes issues de collectes industrielles ou de bases de donn\u00e9es transactionnelles sont rarement parfaitement assainies. Elles h\u00e9bergent fr\u00e9quemment des aberrations arithm\u00e9tiques, des marqueurs d&rsquo;absence d&rsquo;information et des formats h\u00e9t\u00e9rog\u00e8nes qui perturbent l&rsquo;ex\u00e9cution normale des calculs.<\/p>\n<h3>9.1 Impact des NaN (Not a Number) sur le calcul modale<\/h3>\n<p>La manipulation des valeurs manquantes repr\u00e9sent\u00e9es par le standard flottant <code>np.nan<\/code> engendre des comportements particuli\u00e8rement pernicieux au sein des algorithmes de r\u00e9duction statistique. L&rsquo;origine de cette difficult\u00e9 r\u00e9side dans le postulat fondamental de la norme IEEE 754 selon lequel la valeur sp\u00e9ciale NaN poss\u00e8de la propri\u00e9t\u00e9 de non-r\u00e9flexivit\u00e9 absolue : l&rsquo;assertion logique <code>np.nan == np.nan<\/code> est syst\u00e9matiquement \u00e9valu\u00e9e \u00e0 <code>False<\/code>.<\/p>\n<p>Lors de l&rsquo;appel \u00e0 <code>np.unique<\/code> sur un tableau contenant des occurrences multiples de NaN, les algorithmes de tri sous-jacents adoptent un comportement sp\u00e9cifique. Par convention dans les algorithmes de tri r\u00e9cents de NumPy, les NaN sont syst\u00e9matiquement pouss\u00e9s \u00e0 la fin du tableau tri\u00e9. Cependant, selon les sous-routines compil\u00e9es sollicit\u00e9es, la pr\u00e9sence de valeurs non r\u00e9flexives peut d\u00e9stabiliser la logique d&rsquo;identification des transitions de valeurs uniques. Pour garantir une int\u00e9grit\u00e9 absolue du r\u00e9sultat, il est m\u00e9thodologiquement indispensable de proc\u00e9der \u00e0 un filtrage pr\u00e9alable explicite des donn\u00e9es en utilisant la n\u00e9gation du masque de validit\u00e9 fourni par <code>np.isnan<\/code> :<\/p>\n<p><code>tableau_nettoye = tableau_corrompu[~np.isnan(tableau_corrompu)]<\/code><\/p>\n<p>Si la strat\u00e9gie de mod\u00e9lisation exige au contraire de traiter le statut de donn\u00e9e manquante comme une cat\u00e9gorie informative \u00e0 part enti\u00e8re susceptible de constituer le mode pr\u00e9dominant du syst\u00e8me, le tableau doit \u00eatre au pr\u00e9alable converti vers un format supportant la r\u00e9flexivit\u00e9 ou faire l&rsquo;objet d&rsquo;un remplacement sentinelle explicite vers une constante hors du domaine d&rsquo;observation (par exemple une valeur n\u00e9gative arbitraire non ambigu\u00eb).<\/p>\n<h3>9.2 Calcul du mode sur des tableaux bool\u00e9ens<\/h3>\n<p>Le traitement des tableaux bool\u00e9ens (<code>dtype=bool<\/code>) constitue un cas particulier remarquable dans lequel la machinerie algorithmique g\u00e9n\u00e9rale de <code>np.unique<\/code> ou de <code>scipy.stats.mode<\/code> est totalement surdimensionn\u00e9e. Puisque l&rsquo;espace d&rsquo;\u00e9tat d&rsquo;une variable bool\u00e9enne est strictement binaire et restreint au couple <span class=\"arabpsy-math-inline\" data-latex=\"{\\text{False}, \\text{True}}\">${\\text{False}, \\text{True}}$<\/span>, le calcul du mode se r\u00e9sout de mani\u00e8re analytique instantan\u00e9e par une simple op\u00e9ration d&rsquo;accumulation sommatoire.<\/p>\n<p>En exploitant le fait qu&rsquo;en m\u00e9moire informatique la valeur <code>True<\/code> est repr\u00e9sent\u00e9e par le chiffre 1 et <code>False<\/code> par le chiffre 0, l&rsquo;instruction <code>np.sum(tableau_booleen)<\/code> retourne exactement le nombre d&rsquo;occurrences de la valeur <code>True<\/code>. Soit <span class=\"arabpsy-math-inline\" data-latex=\"N\">$N$<\/span> la longueur totale du tableau. Si la somme des \u00e9l\u00e9ments v\u00e9rifie l&rsquo;in\u00e9galit\u00e9 stricte <span class=\"arabpsy-math-inline\" data-latex=\"\\sum x_i &gt; N \/ 2\">$\\sum x_i > N \/ 2$<\/span>, le mode est obligatoirement <code>True<\/code>. Si $sum x_i < N \/ 2$, le mode est cat\u00e9goriquement <code>False<\/code>. Si la somme est exactement \u00e9gale \u00e0 la moiti\u00e9 des effectifs, le tableau est parfaitement bimodal.<\/p>\n<p>Cette approche sommatoire vectoris\u00e9e contourne int\u00e9gralement la complexit\u00e9 <span class=\"arabpsy-math-inline\" data-latex=\"O(N log N)\">$O(N log N)$<\/span> du tri pr\u00e9alable pour op\u00e9rer en complexit\u00e9 lin\u00e9aire stricte <span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span> avec une utilisation optimale des instructions SIMD, multipliant les d\u00e9bits d&rsquo;ex\u00e9cution par des facteurs souvent sup\u00e9rieurs \u00e0 100 sur de gigantesques volumes de donn\u00e9es binaires.<\/p>\n<h3>9.3 Application aux tableaux de cha\u00eenes de caract\u00e8res (Strings)<\/h3>\n<p>NumPy dispose d&rsquo;un support natif complet pour les types de cha\u00eenes de caract\u00e8res \u00e0 longueur fixe, d\u00e9sign\u00e9s par les sp\u00e9cificateurs de types <code><U<\/code> (caract\u00e8res Unicode) et <code><S<\/code> (cha\u00eenes d'octets ASCII). L'analyse modale s'applique naturellement sur ces tableaux textuels pour isoler des descripteurs dominants au sein de variables nominales pures.<\/p>\n<p>Lors de l'application de <code>np.unique(..., return_counts=True)<\/code> sur un tableau de cha\u00eenes, NumPy ex\u00e9cute un tri lexicographique bas\u00e9 sur les points de code des caract\u00e8res. Cette op\u00e9ration s'ex\u00e9cute avec une remarquable efficacit\u00e9, mais impose une discipline d'ing\u00e9nierie rigoureuse quant au nettoyage pr\u00e9alable de la casse et des s\u00e9parateurs. En effet, NumPy traite des repr\u00e9sentations telles que <code>\"Paris\"<\/code>, <code>\"paris\"<\/code> et <code>\"Paris \"<\/code> (comportant une espace r\u00e9siduelle) comme trois entit\u00e9s nominales disjointes. Une phase de normalisation vectoris\u00e9e via le sous-module <code>numpy.char<\/code> (notamment par l'utilisation de <code>np.char.strip<\/code> et <code>np.char.lower<\/code>) s'av\u00e8re indispensable en amont de toute identification modale cat\u00e9gorielle.<\/p>\n<h2>10. Optimisation des performances computationnelles pour le Big Data<\/h2>\n<p>Lorsque la volum\u00e9trie des donn\u00e9es \u00e0 traiter d\u00e9passe les dizaines de millions d'enregistrements ou que l'extraction du mode doit \u00eatre ex\u00e9cut\u00e9e des millions de fois au sein d'une boucle d'optimisation it\u00e9rative (telle qu'une simulation de Monte-Carlo), l'approche standard bas\u00e9e sur <code>np.unique<\/code> atteint rapidement ses limites mat\u00e9rielles.<\/p>\n<h3>10.1 Limites algorithmiques de np.unique \u00e0 grande \u00e9chelle<\/h3>\n<p>L'inconv\u00e9nient fondamental de l'algorithme <code>np.unique<\/code> r\u00e9side dans sa d\u00e9pendance fonctionnelle \u00e0 l'\u00e9gard de l'op\u00e9ration de tri complet du tableau d'entr\u00e9e. Bien que le Quicksort compil\u00e9 en C de NumPy soit d'une efficacit\u00e9 chirurgicale, sa complexit\u00e9 computationnelle th\u00e9orique demeure born\u00e9e inf\u00e9rieurement par le seuil asymptotique de comparaison de <span class=\"arabpsy-math-inline\" data-latex=\"\\Omega(N \\log N)\">$\\Omega(N \\log N)$<\/span>.<\/p>\n<p>Sur un tableau contenant <span class=\"arabpsy-math-inline\" data-latex=\"10^8\">$10^8$<\/span> \u00e9l\u00e9ments, le terme <span class=\"arabpsy-math-inline\" data-latex=\"N log N\">$N log N$<\/span> impose environ <span class=\"arabpsy-math-inline\" data-latex=\"2.6 \\times 10^9\">$2.6 \\times 10^9$<\/span> op\u00e9rations de comparaison \u00e9l\u00e9mentaires. De surcro\u00eet, le tri r\u00e9ordonne massivement les pointeurs m\u00e9moires ou d\u00e9place physiquement de gigantesques blocs de donn\u00e9es au sein de la m\u00e9moire vive, ce qui provoque des d\u00e9fauts de cache r\u00e9currents (cache misses) au niveau des registres L2 et L3 des architectures de processeurs x86_64 modernes. \u00c0 cette p\u00e9nalit\u00e9 temporelle s'ajoute une p\u00e9nalit\u00e9 spatiale : le tri et l'allocation des tableaux de sortie imposent des copies de travail volumineuses qui peuvent saturer la m\u00e9moire disponible et d\u00e9clencher l'utilisation intempestive du fichier d'\u00e9change (swap) sur disque dur, effondrant dramatiquement les d\u00e9bits de traitement.<\/p>\n<h3>10.2 Acc\u00e9l\u00e9ration avec np.bincount pour les entiers positifs<\/h3>\n<p>Pour s'affranchir du goulet d'\u00e9tranglement du tri sur les donn\u00e9es discr\u00e8tes compos\u00e9es de valeurs enti\u00e8res positives born\u00e9es, NumPy met \u00e0 disposition une primitive algorithmique d'une efficacit\u00e9 monumentale : <code>numpy.bincount<\/code>.<\/p>\n<p>La fonction <code>numpy.bincount<\/code> repose sur le paradigme du tri par d\u00e9compte direct (Counting Sort). Au lieu de r\u00e9ordonner les \u00e9l\u00e9ments par comparaisons successives, l'algorithme alloue une plage de m\u00e9moire contigu\u00eb dont la taille correspond exactement \u00e0 la valeur de l'entier maximal pr\u00e9sent dans le tableau d'entr\u00e9e plus un (<span class=\"arabpsy-math-inline\" data-latex=\"V_{\\max} + 1\">$V_{\\max} + 1$<\/span>). Il parcourt ensuite le tableau d'entr\u00e9e en une seule et unique passe lin\u00e9aire d'ordre <span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span> : pour chaque entier lu, il incr\u00e9mente directement la case m\u00e9moire correspondant \u00e0 cet indice dans le tableau d'accumulation.<\/p>\n<p>Le calcul du mode d'un vecteur d'entiers positifs prend d\u00e8s lors la forme d'un idiome compact d'une rapidit\u00e9 fulgurante :<\/p>\n<p><code>mode_ultra_rapide = np.argmax(np.bincount(tableau_entiers))<\/code><\/p>\n<p>La complexit\u00e9 temporelle globale de cette op\u00e9ration est de l'ordre de <span class=\"arabpsy-math-inline\" data-latex=\"O(N + V_{\\max})\">$O(N + V_{\\max})$<\/span>. Si la valeur maximale <span class=\"arabpsy-math-inline\" data-latex=\"V_{\\max}\">$V_{\\max}$<\/span> est de dimension raisonnable par rapport \u00e0 la taille de l'\u00e9chantillon (ce qui est typiquement le cas pour des \u00e2ges, des codes postaux restreints, des classes d'adh\u00e9sion ou des indices de quantification num\u00e9rique), <code>bincount<\/code> surpasse <code>np.unique<\/code> de plusieurs ordres de grandeur, transformant des calculs de plusieurs dizaines de secondes en routines ex\u00e9cut\u00e9es en quelques millisecondes.<\/p>\n<p>Une mise en garde fondamentale doit cependant \u00eatre formul\u00e9e quant \u00e0 l'usage de cette technique : si le tableau d'entr\u00e9e contient des entiers dont la valeur absolue est immense (par exemple si l'on tente d'analyser un tableau contenant le chiffre 0 et le chiffre 10 milliards), <code>bincount<\/code> tentera d'allouer un tableau d'accumulation interm\u00e9diaire de 10 milliards de cases m\u00e9moires, provoquant instantan\u00e9ment une erreur critique d'\u00e9puisement de m\u00e9moire (<code>MemoryError<\/code>). De plus, cette fonction exige formellement des entiers positifs ou nuls ; la pr\u00e9sence d'un seul entier n\u00e9gatif d\u00e9clenche une exception d'ex\u00e9cution (<code>ValueError<\/code>).<\/p>\n<h3>10.3 Parall\u00e9lisation et compilation JIT avec Numba<\/h3>\n<p>Pour les sc\u00e9narios o\u00f9 les donn\u00e9es d\u00e9passent les contraintes impos\u00e9es par <code>np.bincount<\/code> (pr\u00e9sence de r\u00e9els continus pr\u00e9trait\u00e9s, entiers n\u00e9gatifs arbitraires ou matrices massives n\u00e9cessitant des r\u00e9ductions axiales parall\u00e8les complexes), le recours \u00e0 la compilation juste-\u00e0-temps (JIT) via la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/numba.pydata.org\/\">Numba<\/a> constitue la solution industrielle par excellence.<\/p>\n<p>En d\u00e9corant une fonction it\u00e9rative Python imp\u00e9rative avec l'op\u00e9rateur <code>@njit(parallel=True)<\/code>, Numba compile le flux d'instructions directement en code machine natif via la suite logicielle LLVM. Il devient alors possible d'\u00e9crire des boucles imbriqu\u00e9es explicites pour parcourir les tableaux tout en b\u00e9n\u00e9ficiant de la parall\u00e9lisation automatique sur l'ensemble des c\u0153urs physiques du microprocesseur gr\u00e2ce \u00e0 l'infrastructure OpenMP sous-jacente :<\/p>\n<p>Les benchmarks de performance d\u00e9montrent que pour des op\u00e9rations de d\u00e9compte de mode sur des grilles multidimensionnelles denses, une routine Numba parall\u00e9lis\u00e9e s'ex\u00e9cute \u00e0 des vitesses tutoyant les limites th\u00e9oriques de la bande passante de la m\u00e9moire vive mat\u00e9rielle (memory-bound throughput), surclassant toute combinaison d'appels NumPy interpr\u00e9t\u00e9s standards.<\/p>\n<h2>11. Application empirique : analyse du profil modal dans les donn\u00e9es comportementales et psychom\u00e9triques<\/h2>\n<p>Pour illustrer l'utilit\u00e9 m\u00e9thodologique concr\u00e8te de l'analyse du mode au sein des protocoles scientifiques r\u00e9els, examinons son application dans le traitement de donn\u00e9es comportementales, cliniques et psychom\u00e9triques issues de cohortes d'exp\u00e9rimentation humaine.<\/p>\n<h3>11.1 Traitement des \u00e9chelles ordinales de type Likert<\/h3>\n<p>Dans les domaines de la psychologie quantitative, de l'ergonomie cognitive et de l'\u00e9valuation des politiques publiques, les instruments de collecte de donn\u00e9es reposent massivement sur des \u00e9chelles de Likert standardis\u00e9es (g\u00e9n\u00e9ralement gradu\u00e9es de 1 \u00e0 5 ou de 1 \u00e0 7, traduisant des degr\u00e9s d'assentiment allant de \u00ab Pas du tout d'accord \u00bb \u00e0 \u00ab Tout \u00e0 fait d'accord \u00bb).<\/p>\n<p>L'erreur la plus r\u00e9pandue dans le traitement de ces jeux de donn\u00e9es consiste \u00e0 appliquer sans pr\u00e9caution la moyenne arithm\u00e9tique pour quantifier l'opinion d'un groupe. Sur le plan de la th\u00e9orie formelle de la mesure, les \u00e9chelons de Likert sont des variables strictement ordinales : la distance s\u00e9mantique et psychologique s\u00e9parant \u00ab Pas du tout d'accord \u00bb et \u00ab Neutre \u00bb n'a aucune garantie de lin\u00e9arit\u00e9 avec celle s\u00e9parant \u00ab Neutre \u00bb et \u00ab Tout \u00e0 fait d'accord \u00bb. Calculer une \u00ab moyenne de satisfaction de 3.42 \u00bb constitue une aberration \u00e9pist\u00e9mologique qui masque la structure des r\u00e9ponses.<\/p>\n<p>L'extraction du mode au moyen de tableaux NumPy permet au contraire de restituer fid\u00e8lement le consensus psychologique majoritaire. Plus fondamentalement, l'analyse multimodale joue ici un r\u00f4le d'alerte diagnostique inestimable : l'identification d'une distribution bimodale pr\u00e9sentant deux pics simultan\u00e9s aux \u00e9chelons 1 et 5 r\u00e9v\u00e8le imm\u00e9diatement une polarisation profonde de la population d'\u00e9tude ou une formulation ambigu\u00eb de la question d'enqu\u00eate, information capitale qu'une moyenne arithm\u00e9tique factice de 3.0 aurait totalement occult\u00e9e en sugg\u00e9rant une fausse neutralit\u00e9 d'opinion.<\/p>\n<h3>11.2 \u00c9tude de cas : matrice de temps de r\u00e9action et comportement dominant<\/h3>\n<p>Consid\u00e9rons un protocole exp\u00e9rimental de neurosciences cognitives \u00e9valuant la prise de d\u00e9cision sous contrainte temporelle. Une cohorte de cinquante participants est soumise \u00e0 cent essais cons\u00e9cutifs d'une t\u00e2che de discrimination visuelle. Pour chaque essai, le comportement de choix discret du sujet est encod\u00e9 par des entiers identifiant la modalit\u00e9 de r\u00e9ponse (par exemple : 1 pour l'\u00e9vitement, 2 pour la neutralisation, 3 pour la confrontation active).<\/p>\n<p>Les donn\u00e9es sont structur\u00e9es au sein d'une matrice NumPy bidimensionnelle <code>reponses_sujets<\/code> de dimensions <span class=\"arabpsy-math-inline\" data-latex=\"50 \\times 100\">$50 \\times 100$<\/span>. L'objectif analytique consiste \u00e0 isoler, pour chaque sujet individuel, la strat\u00e9gie motrice dominante mise en place au fil de l'exp\u00e9rience, tout en quantifiant la consistance comportementale associ\u00e9e :<\/p>\n<p>En formulant une routine vectoris\u00e9e par ligne, les chercheurs extraient pour chaque individu le vecteur modal qui r\u00e9sume sa signature d\u00e9cisionnelle stable. L'analyse de la consistance, mesur\u00e9e par le ratio entre le nombre d'occurrences de ce mode et le nombre total d'essais (<span class=\"arabpsy-math-inline\" data-latex=\"N=100\">$N=100$<\/span>), permet de discriminer statistiquement les sujets ayant adopt\u00e9 un comportement automatis\u00e9 rigide (consistance sup\u00e9rieure \u00e0 80%) de ceux pr\u00e9sentant une ind\u00e9cision stochastique permanente caract\u00e9ris\u00e9e par une dispersion multimodale ou uniforme.<\/p>\n<h3>11.3 Nettoyage et imputation statistique par la valeur modale<\/h3>\n<p>Dans la cha\u00eene de pr\u00e9paration des donn\u00e9es (data preprocessing) pr\u00e9c\u00e9dant l'entra\u00eenement d'algorithmes d'apprentissage supervis\u00e9, tels que les for\u00eats al\u00e9atoires ou les r\u00e9seaux de neurones profonds, la gestion des donn\u00e9es manquantes constitue une \u00e9tape n\u00e9vralgique. Consid\u00e9rons une matrice de variables cat\u00e9gorielles encod\u00e9es num\u00e9riquement repr\u00e9sentant des comorbidit\u00e9s m\u00e9dicales associ\u00e9es \u00e0 des patients.<\/p>\n<p>L'injection de valeurs par la moyenne arithm\u00e9tique pour combler des cellules manquantes g\u00e9n\u00e9rerait des codes d'affections fractionnaires inexistants, corrompant la structure logique des classificateurs subs\u00e9quents. L'imputation modale consiste \u00e0 identifier, pour chaque colonne de comorbidit\u00e9, la modalit\u00e9 dominante au sein de la sous-population partageant les m\u00eames descripteurs d\u00e9mographiques, puis \u00e0 ins\u00e9rer cette valeur modale exacte dans les positions m\u00e9moires identifi\u00e9es par le masque d'absence bool\u00e9en.<\/p>\n<p>Cette approche pr\u00e9serve l'int\u00e9grit\u00e9 cat\u00e9gorielle du syst\u00e8me d'information, respecte les postulats de distribution discr\u00e8te et stabilise l'apprentissage statistique en \u00e9vitant d'introduire des \u00e9tats imaginaires dans les repr\u00e9sentations vectorielles denses des mod\u00e8les pr\u00e9dictifs.<\/p>\n<h2>12. Synth\u00e8se architecturale, erreurs courantes et tableau r\u00e9capitulatif des m\u00e9thodes<\/h2>\n<p>L'analyse rigoureuse men\u00e9e tout au long de cet ouvrage d\u00e9montre que le calcul du mode dans les structures NumPy, loin d'\u00eatre une op\u00e9ration \u00e9l\u00e9mentaire banale, requiert une analyse technique pointue conciliant contraintes math\u00e9matiques, pr\u00e9cision mat\u00e9rielle et imp\u00e9ratifs d'optimisation.<\/p>\n<h3>12.1 Erreurs fr\u00e9quentes et comment les \u00e9viter<\/h3>\n<p>Au terme de cette analyse, nous pouvons cataloguer les trois erreurs de conception les plus critiques et r\u00e9currentes rencontr\u00e9es dans le code de production scientifique :<\/p>\n<p>1. <strong>La pr\u00e9somption d'unimodalit\u00e9 universelle :<\/strong> Utiliser aveugl\u00e9ment <code>valeurs[np.argmax(counts)]<\/code> sans v\u00e9rifier pr\u00e9alablement si d'autres indices partagent la fr\u00e9quence maximale. Cette pratique efface purement et simplement les composantes secondaires des syst\u00e8mes bimodaux ou multimodaux, introduisant un biais silencieux dans les conclusions exp\u00e9rimentales.<br \/>\n2. <strong>La confusion entre indice modal et valeur modale :<\/strong> Une b\u00e9vue syntaxique fr\u00e9quente consiste \u00e0 interpr\u00e9ter la sortie scalaire de <code>np.argmax(occurrences)<\/code> comme \u00e9tant la valeur du mode elle-m\u00eame, au lieu de s'en servir comme pointeur d'indexation pour interroger le tableau des valeurs uniques pr\u00e9alablement ordonn\u00e9es.<br \/>\n3. <strong>L'application directe de tests d'\u00e9galit\u00e9 sur des nombres r\u00e9els :<\/strong> Tenter de calculer le mode sur des tableaux de type <code>float32<\/code> ou <code>float64<\/code> sans phase de discr\u00e9tisation ou de partitionnement d'histogramme, ce qui conduit in\u00e9vitablement \u00e0 des r\u00e9sultats incoh\u00e9rents en raison des limitations de la pr\u00e9cision machine IEEE 754.<\/p>\n<h3>12.2 Tableau d\u00e9cisionnel comparatif des diff\u00e9rentes approches<\/h3>\n<p>Le tableau comparatif suivant synth\u00e9tise les propri\u00e9t\u00e9s architecturales, les contraintes fonctionnelles et les domaines d'\u00e9lection de chacune des m\u00e9thodologies pr\u00e9sent\u00e9es dans ce guide :<\/p>\n<table border=\"1\" cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse: collapse; width: 100%; text-align: left; margin: 20px 0;\">\n<thead>\n<tr style=\"background-color: #f2f2f2;\">\n<th>M\u00e9thode Computationnelle<\/th>\n<th>Types de donn\u00e9es cibles<\/th>\n<th>Complexit\u00e9 Temporelle<\/th>\n<th>Complexit\u00e9 Spatiale<\/th>\n<th>Gestion Multimodale<\/th>\n<th>Cas d'usage pr\u00e9f\u00e9rentiel<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>np.unique + argmax \/ boolean<\/strong><\/td>\n<td>Tous types (int, float, str, obj)<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N log N)\">$O(N log N)$<\/span><\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span><\/td>\n<td>Totale (avec masque)<\/td>\n<td>Analyse exploratoire g\u00e9n\u00e9rale, distribution unimodale ou multimodale 1D<\/td>\n<\/tr>\n<tr>\n<td><strong>np.bincount + argmax<\/strong><\/td>\n<td>Entiers positifs born\u00e9s uniquement<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N + V_{\\max})\">$O(N + V_{\\max})$<\/span><\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(V_{\\max})\">$O(V_{\\max})$<\/span><\/td>\n<td>Partielle (premier mode)<\/td>\n<td>Tr\u00e8s grands tableaux d'entiers positifs, pipelines de haute performance<\/td>\n<\/tr>\n<tr>\n<td><strong>scipy.stats.mode<\/strong><\/td>\n<td>Num\u00e9riques et discrets<\/td>\n<td>Variable selon l'axe<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span><\/td>\n<td>D\u00e9terministe (valeur min)<\/td>\n<td>R\u00e9ductions axiales multidimensionnelles (2D, 3D), int\u00e9gration SciPy<\/td>\n<\/tr>\n<tr>\n<td><strong>Discr\u00e9tisation (Histogram\/Binning)<\/strong><\/td>\n<td>Nombres flottants continus<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span> \u00e0 <span class=\"arabpsy-math-inline\" data-latex=\"O(N log N)\">$O(N log N)$<\/span><\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(B)\">$O(B)$<\/span> (<span class=\"arabpsy-math-inline\" data-latex=\"B\">$B$<\/span> classes)<\/td>\n<td>Approximate (selon classes)<\/td>\n<td>Mesures analogiques continues, signaux physiques, donn\u00e9es bruit\u00e9es<\/td>\n<\/tr>\n<tr>\n<td><strong>Boucles Numba compil\u00e9es JIT<\/strong><\/td>\n<td>Num\u00e9riques (int, float)<\/td>\n<td><span class=\"arabpsy-math-inline\" data-latex=\"O(N)\">$O(N)$<\/span> (parall\u00e9lis\u00e9)<\/td>\n<td>Minimale <span class=\"arabpsy-math-inline\" data-latex=\"O(1)\">$O(1)$<\/span><\/td>\n<td>Personnalisable<\/td>\n<td>Calculs intensifs Big Data, parall\u00e9lisme mat\u00e9riel multicoeur<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>12.3 Recommandations m\u00e9thodologiques pour la recherche computationnelle<\/h3>\n<p>Pour assurer la p\u00e9rennit\u00e9, la lisibilit\u00e9 et l'exactitude des cha\u00eenes de traitement analytique dans les environnements de recherche computationnelle et d'ing\u00e9nierie logicielle avanc\u00e9e, il est vivement recommand\u00e9 d'encapsuler la d\u00e9tection du mode au sein d'une fonction utilitaire modulaire normalis\u00e9e. Cette fonction doit valider d\u00e9fensivement les types d'entr\u00e9e, appliquer le filtrage des valeurs manquantes, s\u00e9lectionner dynamiquement la strat\u00e9gie algorithmique optimale en fonction de l'intervalle de valeurs et de l'homog\u00e9n\u00e9it\u00e9 du tenseur, et retourner une structure de donn\u00e9es explicite sp\u00e9cifiant \u00e0 la fois la liste compl\u00e8te des modes observ\u00e9s et leur cardinalit\u00e9 respective.<\/p>\n<p>En articulant de la sorte rigueur conceptuelle, compr\u00e9hension intime des structures m\u00e9moires et ma\u00eetrise des primitives de l'\u00e9cosyst\u00e8me NumPy et SciPy, le chercheur transforme une apparente lacune de la biblioth\u00e8que en une opportunit\u00e9 de concevoir des architectures d'analyse de donn\u00e9es hautement optimis\u00e9es, r\u00e9silientes et scientifiquement irr\u00e9prochables.<\/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., Wieser, E., Taylor, J., Berg, S., Smith, N. J., Kern, R., Picus, M., Hoyer, S., van Kerkwijk, M. H., Brett, M., Haldane, A., del R\u00edo, J. F., Wiebe, M., Peterson, P., \u2026 Oliphant, T. E. (2020). Array programming with NumPy. <em>Nature<\/em>, 585(7825), 357\u2013362. <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>Virtanen, P., Gommers, R., Oliphant, T. E., Haberland, M., Reddy, T., Cournapeau, D., Burovski, E., Peterson, P., Weckesser, W., Bright, J., van der Walt, S. J., Brett, M., Wilson, J., Millman, K. J., Mayorov, N., Nelson, A. R. J., Jones, E., Kern, R., Larson, E., \u2026 SciPy 1.0 Contributors. (2020). SciPy 1.0: Fundamental algorithms for scientific computing in Python. <em>Nature Methods<\/em>, 17(3), 261\u2013272. <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>Lam, S. K., Pitrou, A., &amp; Seibert, S. (2015). Numba: A LLVM-based Python JIT compiler. In <em>Proceedings of the Second Workshop on the LLVM Compiler Infrastructure in HPC<\/em> (pp. 1\u20136). Association for Computing Machinery. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1145\/2833157.2833162\">https:\/\/doi.org\/10.1145\/2833157.2833162<\/a><\/li>\n<li>IEEE. (2019). <em>IEEE Standard for Floating-Point Arithmetic<\/em> (IEEE Std 754-2019). IEEE Computer Society. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1109\/IEEESTD.2019.8766229\">https:\/\/doi.org\/10.1109\/IEEESTD.2019.8766229<\/a><\/li>\n<li>Stevens, S. S. (1946). On the theory of scales of measurement. <em>Science<\/em>, 103(2684), 677\u2013680. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1126\/science.103.2684.677\">https:\/\/doi.org\/10.1126\/science.103.2684.677<\/a><\/li>\n<li>Silverman, B. W. (1986). <em>Density estimation for statistics and data analysis<\/em>. Chapman and Hall\/CRC. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1201\/9781315140919\">https:\/\/doi.org\/10.1201\/9781315140919<\/a><\/li>\n<li>Cormen, T. H., Leiserson, C. E., Rivest, R. L., &amp; Stein, C. (2009). <em>Introduction to algorithms<\/em> (3rd ed.). MIT Press.<\/li>\n<li>NumPy Developers. (2023). <em>NumPy user guide and reference documentation (Release 1.26.0)<\/em>. NumPy Organization. <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/\">https:\/\/numpy.org\/doc\/stable\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Guide acad\u00e9mique complet pour calculer le mode d&rsquo;un tableau NumPy avec np.unique et scipy.stats. Exemples d\u00e9taill\u00e9s pour distributions uni et multimodales.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","categories":[4351,7836],"tags":[1884,3874,2960,2468,2069],"class_list":["post-6050","psych_stat","type-psych_stat","status-publish","hentry","category-programmation-scientifique","category-statistiques-numeriques","tag-analyse-de-donnees","tag-mode-statistique","tag-numpy","tag-python","tag-statistique-descriptive"],"_links":{"self":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6050","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=6050"}],"version-history":[{"count":1,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6050\/revisions"}],"predecessor-version":[{"id":16788,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/6050\/revisions\/16788"}],"wp:attachment":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}