{"id":13405,"date":"2026-10-14T18:02:37","date_gmt":"2026-10-14T18:02:37","guid":{"rendered":"http:\/\/french.arabpsychology.com\/statistics\/comment-trier-un-tableau-numpy-par-colonne-avec-exemples\/"},"modified":"2026-10-14T18:02:37","modified_gmt":"2026-10-14T18:02:37","slug":"comment-trier-un-tableau-numpy-par-colonne-avec-exemples","status":"publish","type":"psych_stat","link":"https:\/\/french.arabpsychology.com\/?psych_stat=comment-trier-un-tableau-numpy-par-colonne-avec-exemples","title":{"rendered":"Comment trier un tableau NumPy par colonne (avec exemples)"},"content":{"rendered":"<p>Dans l&rsquo;\u00e9cosyst\u00e8me du calcul scientifique en langage Python, la biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/\">NumPy<\/a> occupe une place fondamentale en tant que socle de l&rsquo;ensemble des architectures de traitement num\u00e9rique, d&rsquo;apprentissage automatique et de mod\u00e9lisation stochastique. Sa structure de donn\u00e9es \u00e9l\u00e9mentaire, le tableau multidimensionnel, permet d&rsquo;ex\u00e9cuter des op\u00e9rations vectoris\u00e9es \u00e0 des vitesses comparables \u00e0 celles de routines compil\u00e9es en C ou en Fortran. Toutefois, d\u00e8s lors qu&rsquo;il s&rsquo;agit d&rsquo;ordonner des matrices de donn\u00e9es selon une dimension sp\u00e9cifique, de nombreux praticiens se heurtent \u00e0 des \u00e9cueils conceptuels majeurs, confondant fr\u00e9quemment la r\u00e9organisation des scalaires internes et le r\u00e9ordonnancement structurel des enregistrements vectoriels.<\/p>\n<p>Le tri d&rsquo;une matrice bidimensionnelle selon les valeurs prises par une colonne donn\u00e9e constitue une op\u00e9ration r\u00e9currente en analyse de donn\u00e9es, en pr\u00e9traitement de s\u00e9ries temporelles et en alg\u00e8bre lin\u00e9aire appliqu\u00e9e. Contrairement aux structures de donn\u00e9es de plus haut niveau telles que les trames de donn\u00e9es de la biblioth\u00e8que Pandas, qui encapsulent cette fonctionnalit\u00e9 au sein de m\u00e9thodes explicites, NumPy requiert une manipulation programmatique plus granulaire. Cette approche directe exige de comprendre pr\u00e9cis\u00e9ment la dissociation entre l&rsquo;\u00e9valuation d&rsquo;un ordre de grandeur au sein d&rsquo;un vecteur et l&rsquo;application de la permutation r\u00e9sultante \u00e0 l&rsquo;ensemble du volume matriciel sous-jacent.<\/p>\n<p>Le pr\u00e9sent article propose une exploration exhaustive, m\u00e9thodique et math\u00e9matiquement rigoureuse des m\u00e9canismes permettant de trier un tableau bidimensionnel NumPy selon une ou plusieurs colonnes. Nous d\u00e9taillerons les fondements architecturaux de la m\u00e9moire vive r\u00e9gissant le stockage de ces structures, les principes algorithmiques du tri indirect mat\u00e9rialis\u00e9 par les fonctions de permutation d&rsquo;indices, les techniques d&rsquo;inversion d&rsquo;ordre, la gestion des ex \u00e6quo via l&rsquo;ordonnancement lexicographique, ainsi que les implications computationnelles et mat\u00e9rielles de telles transformations. L&rsquo;objectif est de fournir une r\u00e9f\u00e9rence technique int\u00e9grale, accessible et rigoureuse pour l&rsquo;ensemble des analystes quantitatifs, ing\u00e9nieurs de donn\u00e9es et chercheurs scientifiques.<\/p>\n<h2>1. Introduction aux structures multidimensionnelles NumPy et \u00e0 l&rsquo;ordonnancement matriciel<\/h2>\n<h3>1.1 Nature et architecture en m\u00e9moire des objets ndarray<\/h3>\n<p>L&rsquo;objet central au sein de l&rsquo;environnement NumPy est le <strong>ndarray<\/strong> (tableau \u00e0 N dimensions). Contrairement aux listes natives de l&rsquo;interpr\u00e9teur Python, qui constituent en r\u00e9alit\u00e9 des tableaux de pointeurs vers des objets dynamiquement allou\u00e9s et dispers\u00e9s au sein de la m\u00e9moire du syst\u00e8me, le ndarray repose sur une architecture de bloc de m\u00e9moire tampon contigu. Cette zone de m\u00e9moire lin\u00e9aire continue, allou\u00e9e au niveau du tas via l&rsquo;allocateur syst\u00e8me standard, contient les donn\u00e9es brutes dans leur repr\u00e9sentation binaire primitive, qu&rsquo;il s&rsquo;agisse d&rsquo;entiers cod\u00e9s sur soixante-quatre bits, de nombres \u00e0 virgule flottante conformes \u00e0 la norme IEEE 754 ou de valeurs bool\u00e9ennes compact\u00e9es.<\/p>\n<p>Cette organisation physique implique une dissociation formelle entre la s\u00e9quence lin\u00e9aire des octets en m\u00e9moire et la vue logique multidimensionnelle expos\u00e9e au d\u00e9veloppeur. Cette abstraction est assur\u00e9e par deux m\u00e9tadonn\u00e9es fondamentales : la forme du tableau, qui d\u00e9finit la cardinalit\u00e9 de chaque axe g\u00e9om\u00e9trique, et les pas m\u00e9moire (ou <em>strides<\/em>), qui indiquent le nombre exact d&rsquo;octets devant \u00eatre franchis pour passer d&rsquo;un \u00e9l\u00e9ment au suivant le long d&rsquo;une dimension donn\u00e9e. Selon que l&rsquo;agencement m\u00e9moire privil\u00e9gie la contigu\u00eft\u00e9 des lignes (convention du langage C, dite <em>row-major<\/em>) ou celle des colonnes (convention historique du langage Fortran, dite <em>column-major<\/em>), les performances d&rsquo;acc\u00e8s s\u00e9quentiel et les op\u00e9rations d&rsquo;it\u00e9ration le long d&rsquo;un axe varieront consid\u00e9rablement en fonction des m\u00e9canismes de pr\u00e9chargement de la m\u00e9moire cache du microprocesseur.<\/p>\n<p>L&rsquo;exigence d&rsquo;un typage strictement homog\u00e8ne constitue la pierre angulaire de cette efficience computationnelle. En garantissant que chaque cellule du tableau occupe une empreinte m\u00e9moire rigoureusement identique, NumPy s&rsquo;affranchit du co\u00fbt d&rsquo;inspection dynamique des types lors de l&rsquo;ex\u00e9cution, autorisant la vectorisation directe des calculs par le jeu d&rsquo;instructions SIMD (Single Instruction, Multiple Data) des processeurs contemporains. Par cons\u00e9quent, toute transformation globale, telle qu&rsquo;une op\u00e9ration de tri, doit \u00eatre con\u00e7ue en tenant compte de cette structure contigu\u00eb afin de maximiser la bande passante m\u00e9moire et de minimiser les d\u00e9fauts de cache lors des permutations d&rsquo;\u00e9l\u00e9ments.<\/p>\n<h3>1.2 Importance th\u00e9orique du tri par colonne dans l&rsquo;analyse matricielle<\/h3>\n<p>Dans le paradigme du traitement matriciel appliqu\u00e9 aux sciences des donn\u00e9es, une matrice bidimensionnelle de dimensions M par N est quasi syst\u00e9matiquement interpr\u00e9t\u00e9e comme un ensemble de M observations statistiques distribu\u00e9es le long des lignes horizontales, chacune \u00e9tant caract\u00e9ris\u00e9e par N variables quantitatives ou qualitatives dispos\u00e9es le long des colonnes verticales. Cette interpr\u00e9tation impose une contrainte ontologique absolue : la ligne repr\u00e9sente une entit\u00e9 logique indivisible, telle qu&rsquo;un patient dans un essai clinique, un instantan\u00e9 temporel de capteurs environnementaux, ou un actif financier au sein d&rsquo;un portefeuille.<\/p>\n<p>D\u00e8s lors, trier un tableau NumPy par colonne ne signifie aucunement ordonner les valeurs de cette colonne de mani\u00e8re isol\u00e9e sans modifier les colonnes adjacentes. Une telle op\u00e9ration d\u00e9synchroniserait irr\u00e9versiblement les attributs des observations, aboutissant \u00e0 une corruption compl\u00e8te du jeu de donn\u00e9es o\u00f9 la premi\u00e8re caract\u00e9ristique d&rsquo;un sujet se retrouverait arbitrairement associ\u00e9e \u00e0 la seconde caract\u00e9ristique d&rsquo;un sujet enti\u00e8rement distinct. L&rsquo;enjeu du tri par colonne consiste donc \u00e0 r\u00e9organiser l&rsquo;ensemble des M lignes du tableau en fonction de la relation d&rsquo;ordre \u00e9tablie sur les valeurs scalaires pr\u00e9sentes dans la colonne d&rsquo;arbitrage choisie.<\/p>\n<p>Cette pr\u00e9servation de la coh\u00e9sion horizontale conditionne l&rsquo;efficacit\u00e9 des pipelines de mod\u00e9lisation quantitative. Qu&rsquo;il s&rsquo;agisse de pr\u00e9parer des partitions pour la validation crois\u00e9e stratifi\u00e9e, d&rsquo;aligner des s\u00e9ries chronologiques en vue de calculer des fen\u00eatres glissantes causales, ou de trier des nuages de points multidimensionnels pour acc\u00e9l\u00e9rer la recherche des plus proches voisins via des arbres de partitionnement spatial, l&rsquo;aptitude \u00e0 permuter des lignes enti\u00e8res en maintenant leur stricte int\u00e9grit\u00e9 est une n\u00e9cessit\u00e9 th\u00e9orique et op\u00e9rationnelle absolue.<\/p>\n<h3>1.3 Distinction formelle entre tri in-situ et tri indirect par indexation<\/h3>\n<p>L&rsquo;API de NumPy met \u00e0 disposition du d\u00e9veloppeur deux approches conceptuellement dissemblables pour op\u00e9rer un tri : le tri in-situ, mat\u00e9rialis\u00e9 par la m\u00e9thode native <strong>ndarray.sort()<\/strong>, et le tri indirect, orchestr\u00e9 par les fonctions g\u00e9n\u00e9ratrices d&rsquo;indices telles que <strong>numpy.argsort()<\/strong>. Comprendre la fronti\u00e8re math\u00e9matique et logicielle entre ces deux strat\u00e9gies est indispensable pour \u00e9viter des anomalies subtiles dans les flux de calcul scientifique.<\/p>\n<p>La m\u00e9thode <strong>ndarray.sort()<\/strong> op\u00e8re directement sur le bloc m\u00e9moire du tableau r\u00e9cepteur, modifiant son contenu de mani\u00e8re destructive sans allouer de copie int\u00e9grale. Toutefois, lorsqu&rsquo;elle est appliqu\u00e9e \u00e0 une matrice bidimensionnelle, son param\u00e8tre d&rsquo;axe force l&rsquo;algorithme \u00e0 trier ind\u00e9pendamment chaque sous-vecteur le long de la dimension sp\u00e9cifi\u00e9e. Si l&rsquo;on applique cette m\u00e9thode sur l&rsquo;axe des colonnes (axe z\u00e9ro), chaque colonne se voit ordonn\u00e9e de fa\u00e7on autonome, d\u00e9truisant instantan\u00e9ment la correspondance entre les lignes. \u00c0 l&rsquo;inverse, si l&rsquo;on tente de l&rsquo;appliquer sur l&rsquo;axe des lignes (axe un), les valeurs internes de chaque observation sont permut\u00e9es entre elles, ce qui s&rsquo;av\u00e8re tout aussi destructeur. Il est donc structurellement impossible d&rsquo;utiliser directement cette m\u00e9thode native in-situ pour r\u00e9aliser un tri par colonne pr\u00e9servant la coh\u00e9sion des rang\u00e9es.<\/p>\n<p>Face \u00e0 cette limite fonctionnelle, la communaut\u00e9 scientifique a consacr\u00e9 le paradigme du <em>tri indirect<\/em>. Le tri indirect consiste \u00e0 ne pas d\u00e9placer les donn\u00e9es brutes dans un premier temps, mais \u00e0 \u00e9valuer la s\u00e9quence ordonn\u00e9e des adresses ou des positions relatives des \u00e9l\u00e9ments au sein de la colonne directrice. En extrayant une permutation sous la forme d&rsquo;un tableau unidimensionnel d&rsquo;indices entiers, on obtient un op\u00e9rateur de transformation r\u00e9utilisable. Cet op\u00e9rateur peut ensuite \u00eatre appliqu\u00e9 \u00e0 la matrice originale par indexation vectorielle avanc\u00e9e pour produire une nouvelle disposition g\u00e9om\u00e9trique ordonn\u00e9e, maintenant intacte l&rsquo;int\u00e9grit\u00e9 de chaque enregistrement horizontal.<\/p>\n<h2>2. Fondements algorithmiques et m\u00e9caniques de numpy.argsort()<\/h2>\n<h3>2.1 Principe math\u00e9matique et logique de la permutation d&rsquo;indices<\/h3>\n<p>D&rsquo;un point de vue math\u00e9matique formel, consid\u00e9rons un vecteur de scalaires V de taille M, index\u00e9 par l&rsquo;ensemble discret {0, 1, &#8230;, M-1}. Le probl\u00e8me du tri consiste \u00e0 d\u00e9terminer une bijection, ou permutation f de l&rsquo;ensemble d&rsquo;indices sur lui-m\u00eame, telle que pour toute paire d&rsquo;indices (i, j) respectant i &lt; j, la relation d&rsquo;ordre V[f(i)] &le; V[f(j)] soit scrupuleusement v\u00e9rifi\u00e9e au sens large (pour un ordre croissant standard). La fonction <strong>numpy.argsort()<\/strong> mat\u00e9rialise algorithmiquement cette permutation canonique.<\/p>\n<p>Au lieu de renvoyer les valeurs du vecteur V apr\u00e8s r\u00e9ordonnancement, la fonction inspecte les valeurs et retourne un nouveau vecteur P d&rsquo;entiers cod\u00e9s sur 64 bits (intp ou int64) de dimension M, o\u00f9 chaque \u00e9l\u00e9ment P[k] d\u00e9signe l&rsquo;indice originel de l&rsquo;observation devant occuper le rang k dans l&rsquo;ensemble ordonn\u00e9. Les donn\u00e9es de r\u00e9f\u00e9rence ne subissent aucune mutation ; leur allocation d&rsquo;origine demeure inchang\u00e9e. L&rsquo;immutabilit\u00e9 structurelle du tableau source est ainsi pr\u00e9serv\u00e9e au cours de cette \u00e9tape pr\u00e9liminaire.<\/p>\n<p>Cette correspondance bijective entre l&rsquo;espace des indices d&rsquo;origine et l&rsquo;espace des rangs tri\u00e9s conf\u00e8re une flexibilit\u00e9 op\u00e9rationnelle immense. Le vecteur d&rsquo;indices r\u00e9sultant n&rsquo;est pas uniquement restreint \u00e0 la colonne qui l&rsquo;a engendr\u00e9 : il s&rsquo;agit d&rsquo;un masque de r\u00e9organisation universel capable d&rsquo;\u00eatre projet\u00e9 sur n&rsquo;importe quel tableau annexe partageant la m\u00eame cardinalit\u00e9 d&rsquo;axe. Cette propri\u00e9t\u00e9 math\u00e9matique est largement exploit\u00e9e pour ordonner simultan\u00e9ment des matrices de donn\u00e9es et des vecteurs de cibles dans les architectures supervis\u00e9es d&rsquo;apprentissage statistique.<\/p>\n<h3>2.2 Param\u00e8tres et variantes de configuration de la fonction argsort<\/h3>\n<p>La fonction <strong>numpy.argsort()<\/strong> int\u00e8gre une s\u00e9rie de param\u00e8tres formels permettant d&rsquo;adapter pr\u00e9cis\u00e9ment son comportement aux particularit\u00e9s de l&rsquo;ensemble de donn\u00e9es trait\u00e9. Le param\u00e8tre central est <strong>axis<\/strong>, qui prend par d\u00e9faut la valeur -1 (soit le dernier axe de la structure). Lorsqu&rsquo;on applique cette fonction \u00e0 une extraction unidimensionnelle d&rsquo;une colonne (par exemple une tranche de forme (M,)), le param\u00e8tre d&rsquo;axe est g\u00e9n\u00e9ralement fix\u00e9 \u00e0 z\u00e9ro ou omis, car l&rsquo;\u00e9valuation s&rsquo;op\u00e8re sur une structure \u00e0 dimension unique.<\/p>\n<p>Un autre param\u00e8tre d\u00e9terminant pour le calcul scientifique est l&rsquo;argument <strong>kind<\/strong>, qui explicite le choix de l&rsquo;algorithme sous-jacent. NumPy propose historiquement trois moteurs de tri principaux : le tri rapide (<em>quicksort<\/em>, impl\u00e9ment\u00e9 sous une variante dual-pivot tr\u00e8s efficiente), le tri par fusion (<em>mergesort<\/em>) et le tri par tas (<em>heapsort<\/em>). Une variante hybride moderne, le <em>radixsort<\/em> ou le <em>timsort<\/em>, est \u00e9galement employ\u00e9e de mani\u00e8re transparente selon les configurations scalaires.<\/p>\n<p>Le choix de l&rsquo;algorithme sous-jacent influe directement sur la <em>stabilit\u00e9<\/em> de l&rsquo;ordonnancement. Un algorithme de tri est qualifi\u00e9 de stable s&rsquo;il pr\u00e9serve scrupuleusement la position relative originelle des \u00e9l\u00e9ments poss\u00e9dant des valeurs strictement identiques. Le <em>quicksort<\/em> et le <em>heapsort<\/em> sont fondamentalement instables : si deux lignes pr\u00e9sentent la m\u00eame valeur dans la colonne analys\u00e9e, leur ordre d&rsquo;apparition final est ind\u00e9termin\u00e9 et peut varier selon l&rsquo;architecture mat\u00e9rielle ou les optimisations du compilateur. Si l&rsquo;application requiert une pr\u00e9dictibilit\u00e9 absolue ou un comportement d\u00e9terministe lors de tris hi\u00e9rarchiques successifs, le d\u00e9veloppeur doit imp\u00e9rativement forcer l&rsquo;usage du param\u00e8tre kind=&rsquo;mergesort&rsquo; (ou kind=&rsquo;stable&rsquo;), garantissant une conservation formelle des rangs relatifs des \u00e9l\u00e9ments ex \u00e6quo.<\/p>\n<h3>2.3 Indexation avanc\u00e9e (Fancy Indexing) appliqu\u00e9e au r\u00e9ordonnancement<\/h3>\n<p>Une fois le vecteur de permutation d&rsquo;indices g\u00e9n\u00e9r\u00e9 par la fonction, la r\u00e9organisation concr\u00e8te du tableau bidimensionnel repose sur le m\u00e9canisme de l&rsquo;<a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/user\/basics.indexing.html\">indexation avanc\u00e9e<\/a>, d\u00e9sign\u00e9 dans la litt\u00e9rature technique par l&rsquo;anglicisme <em>Fancy Indexing<\/em>. Contrairement au d\u00e9coupage standard par tranches (<em>slicing<\/em>), qui produit simplement une vue alternative sans duplication des octets sous-jacents, l&rsquo;indexation par un tableau d&rsquo;entiers d\u00e9clenche imp\u00e9rativement une allocation m\u00e9moire nouvelle.<\/p>\n<p>Lorsque l&rsquo;on fournit un tableau unidimensionnel d&rsquo;indices P pour indexer l&rsquo;axe des lignes d&rsquo;une matrice bidimensionnelle X, l&rsquo;interpr\u00e9teur interne de NumPy parcourt s\u00e9quentiellement les entiers contenus dans P. Pour chaque indice entier p pr\u00e9sent \u00e0 la position k dans P, le moteur extrait une copie int\u00e9grale de la p-i\u00e8me ligne de X et l&rsquo;\u00e9crit \u00e0 la k-i\u00e8me rang\u00e9e du tableau r\u00e9sultat. Le r\u00e9sultat produit est ainsi un ndarray totalement ind\u00e9pendant, d\u00e9tenant son propre bloc contigu de m\u00e9moire tampon.<\/p>\n<p>Ce comportement pr\u00e9sente des implications logistiques majeures qu&rsquo;il convient d&rsquo;anticiper dans le cadre du calcul \u00e0 haute performance. D&rsquo;une part, l&rsquo;ind\u00e9pendance de la matrice ordonn\u00e9e r\u00e9sultante prot\u00e8ge les donn\u00e9es sources contre tout effet de bord ind\u00e9sirable : toute modification subs\u00e9quente apport\u00e9e aux cellules du tableau tri\u00e9 n&rsquo;affectera en rien le tableau initial. D&rsquo;autre part, la n\u00e9cessit\u00e9 de cloner int\u00e9gralement les donn\u00e9es implique une allocation spatiale proportionnelle \u00e0 la taille totale du tableau d&rsquo;origine, susceptible de saturer la m\u00e9moire vive lors de la manipulation de jeux de donn\u00e9es massifs.<\/p>\n<h2>3. M\u00e9thode fondamentale : Tri d&rsquo;un tableau NumPy par colonne en ordre croissant<\/h2>\n<h3>3.1 Syntaxe canonique de l&rsquo;indexation par argsort<\/h3>\n<p>La formulation syntaxique canonique pour trier une matrice bidimensionnelle <strong>X<\/strong> selon les valeurs ascendantes de sa <strong>j<\/strong>-i\u00e8me colonne s&rsquo;exprime sous la forme \u00e9l\u00e9gante et compacte : <strong>X[X[:, j].argsort()]<\/strong>. Cette expression, bien que condens\u00e9e en une unique instruction Python, articule en r\u00e9alit\u00e9 trois op\u00e9rations distinctes et hautement vectoris\u00e9es orchestr\u00e9es au niveau compil\u00e9 de la biblioth\u00e8que.<\/p>\n<p>La premi\u00e8re phase de l&rsquo;expression, <strong>X[:, j]<\/strong>, r\u00e9alise un d\u00e9coupage matriciel par tranche. Les deux-points sp\u00e9cifient que la s\u00e9lection englobe l&rsquo;int\u00e9gralit\u00e9 des lignes de la matrice, tandis que le scalaire <strong>j<\/strong> cible l&rsquo;indice de la colonne de r\u00e9f\u00e9rence. Cette op\u00e9ration produit une vue unidimensionnelle de taille M repr\u00e9sentant le profil vectoriel de la variable s\u00e9lectionn\u00e9e, sans engendrer de duplication m\u00e9moire superflue.<\/p>\n<p>La deuxi\u00e8me phase consiste en l&rsquo;\u00e9valuation de la m\u00e9thode <strong>.argsort()<\/strong> sur ce vecteur extrait. Celle-ci parcourt la s\u00e9quence num\u00e9rique unidimensionnelle, d\u00e9termine la relation d&rsquo;ordre entre ses scalaires et retourne le tableau d&rsquo;indices de permutation correspondant. Enfin, la troisi\u00e8me phase transmet ce vecteur d&rsquo;indices au s\u00e9lecteur de lignes du tableau d&rsquo;origine <strong>X[&#8230;]<\/strong>. L&rsquo;interpr\u00e9teur de NumPy applique alors le m\u00e9canisme d&rsquo;indexation avanc\u00e9e, ordonnant les blocs horizontaux de lignes selon la s\u00e9quence sp\u00e9cifi\u00e9e et renvoyant une nouvelle matrice parfaitement align\u00e9e.<\/p>\n<h3>3.2 Exemple pratique pas \u00e0 pas sur une matrice 3&#215;3<\/h3>\n<p>Afin de d\u00e9composer concr\u00e8tement ce flux d&rsquo;ex\u00e9cution, examinons une matrice carr\u00e9e d&rsquo;entiers de dimensions 3&#215;3. Imaginons que cette matrice, d\u00e9sign\u00e9e par la variable <strong>donnees<\/strong>, soit initialis\u00e9e avec la premi\u00e8re ligne contenant les valeurs 8, 2 et 5 ; la seconde ligne contenant les valeurs 3, 9 et 1 ; et la troisi\u00e8me ligne contenant les valeurs 6, 4 et 7. Nous souhaitons ordonner l&rsquo;ensemble des observations selon les valeurs ascendantes de la deuxi\u00e8me colonne, correspondant \u00e0 l&rsquo;indice informatique 1.<\/p>\n<p>L&rsquo;extraction de cette colonne par l&rsquo;instruction <strong>donnees[:, 1]<\/strong> isole le vecteur unidimensionnel compos\u00e9 des scalaires 2, 9 et 4. L&rsquo;\u00e9valuation de la relation d&rsquo;ordre croissant sur ces scalaires indique imm\u00e9diatement que la plus petite valeur est 2 (situ\u00e9e \u00e0 l&rsquo;indice d&rsquo;origine 0), suivie par 4 (situ\u00e9e \u00e0 l&rsquo;indice d&rsquo;origine 2), et enfin 9 (situ\u00e9e \u00e0 l&rsquo;indice d&rsquo;origine 1). L&rsquo;appel \u00e0 la fonction <strong>donnees[:, 1].argsort()<\/strong> produit donc un tableau d&rsquo;entiers contenant exactement la s\u00e9quence [0, 2, 1].<\/p>\n<p>En appliquant ce tableau d&rsquo;indices \u00e0 la matrice initiale via l&rsquo;instruction <strong>donnees[donnees[:, 1].argsort()]<\/strong>, NumPy r\u00e9organise les rang\u00e9es. La ligne d&rsquo;indice 0 (8, 2, 5) demeure \u00e0 la premi\u00e8re position. La ligne d&rsquo;indice 2 (6, 4, 7) est ensuite d\u00e9plac\u00e9e en deuxi\u00e8me position. Enfin, la ligne d&rsquo;indice 1 (3, 9, 1) est rel\u00e9gu\u00e9e en troisi\u00e8me et derni\u00e8re position. La matrice finale pr\u00e9sente d\u00e9sormais dans sa colonne centrale la s\u00e9quence parfaitement ascendante 2, 4, 9, attestant de la r\u00e9ussite de l&rsquo;ordonnancement sans la moindre alt\u00e9ration des triplets de valeurs qui composent chaque enregistrement.<\/p>\n<h3>3.3 Validation formelle de l&rsquo;int\u00e9grit\u00e9 des lignes apr\u00e8s op\u00e9ration<\/h3>\n<p>La validation de l&rsquo;int\u00e9grit\u00e9 des lignes constitue une \u00e9tape critique dans tout protocole d&rsquo;ing\u00e9nierie des donn\u00e9es. Sur le plan g\u00e9om\u00e9trique, une matrice peut \u00eatre visualis\u00e9e comme une collection de points dans un espace euclidien \u00e0 N dimensions, o\u00f9 chaque ligne repr\u00e9sente les coordonn\u00e9es d&rsquo;un point distinct. Le tri par colonne correspond formellement \u00e0 une translation des points le long de l&rsquo;axe des ordonn\u00e9es discr\u00e8tes des rang\u00e9es, sans modifier la position g\u00e9om\u00e9trique relative des coordonn\u00e9es entre elles au sein d&rsquo;un m\u00eame point.<\/p>\n<p>Pour v\u00e9rifier cette pr\u00e9servation, il convient de constater que la fonction <strong>argsort<\/strong> op\u00e8re une permutation globale de l&rsquo;axe z\u00e9ro sans jamais fragmenter les axes orthogonaux. Lors de l&rsquo;indexation avanc\u00e9e, l&rsquo;interpr\u00e9teur extrait la totalit\u00e9 des \u00e9l\u00e9ments contigus d&rsquo;une ligne donn\u00e9e dans le tampon source et les r\u00e9\u00e9crit fid\u00e8lement dans le tampon de destination. Les d\u00e9pendances statistiques internes, telles que les covariances intra-individuelles, les ratios entre variables ou les identifiants cat\u00e9goriels appari\u00e9s, restent donc int\u00e9gralement conserv\u00e9es.<\/p>\n<p>Dans les pipelines industriels de mod\u00e9lisation pr\u00e9dictive, ce comportement garantit qu&rsquo;un vecteur de caract\u00e9ristiques physiques (par exemple la masse, la temp\u00e9rature et la pression d&rsquo;un r\u00e9acteur chimique) reste strictement associ\u00e9 \u00e0 l&rsquo;horodatage ou au num\u00e9ro de lot correspondant. L&rsquo;utilisation du tri indirect par argsort fournit une garantie math\u00e9matique robuste contre les corruptions structurelles des jeux de donn\u00e9es multidimensionnels.<\/p>\n<h2>4. Inversion de l&rsquo;ordre : Tri par colonne en ordre d\u00e9croissant<\/h2>\n<h3>4.1 Utilisation du d\u00e9coupage n\u00e9gatif avec le pas inverse [::-1]<\/h3>\n<p>Dans de nombreuses applications analytiques, il est indispensable de classer les entit\u00e9s selon une hi\u00e9rarchie descendante, par exemple pour isoler les scores de performance les plus \u00e9lev\u00e9s ou identifier les anomalies d&rsquo;amplitude maximale. La syntaxe canonique de NumPy permet de r\u00e9aliser cette op\u00e9ration avec une efficacit\u00e9 optimale en combinant l&rsquo;extraction d&rsquo;indices avec le d\u00e9coupage n\u00e9gatif au moyen de la syntaxe <strong>[::-1]<\/strong>.<\/p>\n<p>L&rsquo;expression s&rsquo;\u00e9nonce ainsi : <strong>X[X[:, j].argsort()[::-1]]<\/strong>. L&rsquo;op\u00e9ration s&rsquo;articule de mani\u00e8re s\u00e9quentielle. Tout d&rsquo;abord, la fonction <strong>X[:, j].argsort()<\/strong> g\u00e9n\u00e8re le vecteur des indices correspondant \u00e0 l&rsquo;ordre strictement croissant. Imm\u00e9diatement apr\u00e8s cette \u00e9tape, le modificateur de pas <strong>[::-1]<\/strong> est appliqu\u00e9 au tableau d&rsquo;indices lui-m\u00eame. En vertu des r\u00e8gles de d\u00e9coupage de NumPy, l&rsquo;omission des bornes de d\u00e9part et de fin coupl\u00e9e \u00e0 un pas n\u00e9gatif de -1 a pour effet de renverser l&rsquo;ordre des \u00e9l\u00e9ments du tableau d&rsquo;indices.<\/p>\n<p>Ce renversement d&rsquo;indices pr\u00e9sente un co\u00fbt computationnel marginal. En effet, l&rsquo;application du d\u00e9coupage n\u00e9gatif sur un tableau unidimensionnel n&rsquo;engendre pas d&rsquo;allocation de copie : elle retourne une simple vue dont les pas m\u00e9moire (strides) sont invers\u00e9s au niveau des m\u00e9tadonn\u00e9es du tableau. Ce n&rsquo;est qu&rsquo;au moment de l&rsquo;indexation finale sur la matrice X que la r\u00e9organisation concr\u00e8te des donn\u00e9es est ex\u00e9cut\u00e9e, positionnant imm\u00e9diatement en t\u00eate du tableau r\u00e9sultat la ligne dont la valeur dans la colonne <strong>j<\/strong> \u00e9tait maximale.<\/p>\n<h3>4.2 Alternative arithm\u00e9tique : L&rsquo;inversion de signe pour les scalaires num\u00e9riques<\/h3>\n<p>Une alternative largement r\u00e9pandue dans la litt\u00e9rature empirique repose sur la manipulation arithm\u00e9tique directe des valeurs de la colonne cible avant l&rsquo;\u00e9valuation du tri. Cette m\u00e9thode exploite la propri\u00e9t\u00e9 fondamentale selon laquelle la relation d&rsquo;ordre est strictement invers\u00e9e lors de la multiplication par un scalaire n\u00e9gatif. La syntaxe correspondante s&rsquo;\u00e9crit : <strong>X[(-X[:, j]).argsort()]<\/strong>.<\/p>\n<p>Dans cette formulation, l&rsquo;op\u00e9rateur unaire de n\u00e9gation est appliqu\u00e9 de fa\u00e7on vectoris\u00e9e sur l&rsquo;ensemble des \u00e9l\u00e9ments de la colonne s\u00e9lectionn\u00e9e. La valeur maximale devient la valeur minimale absolue, et inversement. Par cons\u00e9quent, l&rsquo;appel subs\u00e9quent \u00e0 <strong>argsort()<\/strong> classe ces valeurs invers\u00e9es par ordre croissant, ce qui \u00e9quivaut rigoureusement \u00e0 classer les valeurs originelles par ordre d\u00e9croissant. Cette approche \u00e9vite le recours explicite \u00e0 la syntaxe de slicing inverse et produit un code visuellement direct.<\/p>\n<p>N\u00e9anmoins, cette approche comporte des contraintes s\u00e9v\u00e8res sur le plan de la robustesse num\u00e9rique. D&rsquo;une part, elle est strictement inapplicable aux types non num\u00e9riques, tels que les colonnes de cha\u00eenes de caract\u00e8res ou les types temporels natifs. D&rsquo;autre part, sur les types entiers sign\u00e9s \u00e0 largeur fixe (comme int8 ou int64), l&rsquo;inversion de signe de la plus petite valeur repr\u00e9sentable (par exemple -2^63 pour un entier de 64 bits) provoque un d\u00e9passement de capacit\u00e9 arithm\u00e9tique (<em>integer overflow<\/em>), entra\u00eenant un comportement ind\u00e9fini ou une erreur de tri silencieuse. Pour les types entiers non sign\u00e9s (uint), l&rsquo;op\u00e9rateur unaire est formellement interdit ou g\u00e9n\u00e8re des valeurs aberrantes. La m\u00e9thode du slicing <strong>[::-1]<\/strong> demeure donc universellement recommand\u00e9e pour son universalit\u00e9 de type et sa neutralit\u00e9 arithm\u00e9tique.<\/p>\n<h3>4.3 Exemple comparatif appliqu\u00e9 \u00e0 une matrice num\u00e9rique dense<\/h3>\n<p>Consid\u00e9rons une matrice dense simulant des mesures spectroscopiques, dot\u00e9e de quatre lignes et trois colonnes de nombres \u00e0 virgule flottante. Supposons que la colonne d&rsquo;arbitrage situ\u00e9e \u00e0 l&rsquo;indice 2 contienne les valeurs r\u00e9elles 12.4, 45.1, 3.8 et 89.6. Nous cherchons \u00e0 ordonner cette matrice pour afficher les observations par intensit\u00e9 d\u00e9croissante de signal.<\/p>\n<p>L&rsquo;utilisation de la syntaxe par d\u00e9coupage inverse <strong>donnees[donnees[:, 2].argsort()[::-1]]<\/strong> d\u00e9clenche l&rsquo;\u00e9valuation de <strong>argsort()<\/strong> sur le vecteur [12.4, 45.1, 3.8, 89.6]. L&rsquo;ordre croissant g\u00e9n\u00e8re le tableau d&rsquo;indices [2, 0, 1, 3] (correspondant aux valeurs 3.8, 12.4, 45.1, 89.6). L&rsquo;application imm\u00e9diate du pas inverse transforme ce vecteur en [3, 1, 0, 2]. Lors de l&rsquo;indexation avanc\u00e9e, la ligne 3 (associ\u00e9e \u00e0 89.6) est allou\u00e9e au premier rang, suivie de la ligne 1 (45.1), de la ligne 0 (12.4) et enfin de la ligne 2 (3.8).<\/p>\n<p>Sur le plan des performances, le benchmarking syst\u00e9matique de ces deux approches r\u00e9v\u00e8le des divergences notables sur des matrices massives. L&rsquo;inversion arithm\u00e9tique <strong>-X[:, j]<\/strong> requiert l&rsquo;allocation d&rsquo;un tampon interm\u00e9diaire temporaire pour h\u00e9berger les oppos\u00e9s arithm\u00e9tiques avant de lancer l&rsquo;algorithme de tri, augmentant ainsi l&#8217;empreinte m\u00e9moire \u00e9ph\u00e9m\u00e8re et sollicitant inutilement la bande passante du bus syst\u00e8me. En revanche, le slicing direct <strong>[::-1]<\/strong> modifie simplement les m\u00e9tadonn\u00e9es de pas d&rsquo;un tableau d&rsquo;indices d\u00e9j\u00e0 allou\u00e9, confirmant sa sup\u00e9riorit\u00e9 technique dans les environnements de calcul intensif.<\/p>\n<h2>5. S\u00e9lection dynamique et g\u00e9n\u00e9ralisation aux colonnes arbitraires<\/h2>\n<h3>5.1 Tri selon la premi\u00e8re colonne ou la derni\u00e8re colonne<\/h3>\n<p>L&rsquo;une des grandes forces du syst\u00e8me d&rsquo;indexation de Python r\u00e9side dans sa prise en charge native des indices n\u00e9gatifs pour le r\u00e9f\u00e9rencement relatif depuis la fin des dimensions. Cette flexibilit\u00e9 permet d&rsquo;adresser des colonnes d&rsquo;int\u00e9r\u00eat sans n\u00e9cessairement conna\u00eetre au pr\u00e9alable le nombre total de variables composant la matrice.<\/p>\n<p>Pour ordonner un tableau selon sa premi\u00e8re colonne, la syntaxe standard sp\u00e9cifie l&rsquo;indice z\u00e9ro : <strong>X[X[:, 0].argsort()]<\/strong>. Ce cas d&rsquo;usage est typique des matrices dont la premi\u00e8re dimension h\u00e9berge un identifiant temporel ou une cl\u00e9 primaire num\u00e9rique. \u00c0 l&rsquo;oppos\u00e9, lorsque l&rsquo;on souhaite trier la structure selon sa derni\u00e8re colonne, l&rsquo;indice -1 est employ\u00e9 : <strong>X[X[:, -1].argsort()]<\/strong>. Cette notation s&rsquo;av\u00e8re particuli\u00e8rement utile dans les contextes d&rsquo;apprentissage statistique o\u00f9 la variable cible ou le score pr\u00e9dictif est classiquement adjoint \u00e0 la toute fin de la matrice de caract\u00e9ristiques.<\/p>\n<p>Pour int\u00e9grer ces m\u00e9caniques au sein de modules r\u00e9utilisables, il est d&rsquo;usage de concevoir une fonction d&rsquo;encapsulation g\u00e9n\u00e9rique acceptant un param\u00e8tre d&rsquo;indice de colonne arbitraire ainsi qu&rsquo;un indicateur de direction de tri. Une telle fonction s\u00e9curise le flux applicatif en validant la conformit\u00e9 de l&rsquo;indice fourni au regard du nombre r\u00e9el de colonnes de la matrice cible, pr\u00e9venant ainsi les lev\u00e9es d&rsquo;exceptions inattendues au cours de longs traitements par lots.<\/p>\n<h3>5.2 Application aux matrices rectangulaires non carr\u00e9es<\/h3>\n<p>Dans les applications concr\u00e8tes de calcul scientifique, les matrices manipul\u00e9es sont tr\u00e8s rarement carr\u00e9es. Elles pr\u00e9sentent le plus souvent des formes asym\u00e9triques dict\u00e9es par la nature des exp\u00e9riences men\u00e9es. Deux configurations arch\u00e9typales s&rsquo;opposent fr\u00e9quemment : les matrices pr\u00e9sentant un volume massif d&rsquo;observations pour un nombre restreint de variables (M &gt;&gt; N), courantes en m\u00e9trologie et traitement de flux de donn\u00e9es, et les matrices \u00e0 haute dimensionnalit\u00e9 comportant un nombre d&rsquo;attributs consid\u00e9rablement sup\u00e9rieur au nombre d&rsquo;individus observ\u00e9s (N &gt;&gt; M), typiques des \u00e9tudes g\u00e9nomiques et transcriptomiques.<\/p>\n<p>L&rsquo;algorithme de tri indirect par argsort pr\u00e9sente un comportement parfaitement robuste face \u00e0 ces configurations asym\u00e9triques. L&rsquo;extraction <strong>X[:, j]<\/strong> produisant syst\u00e9matiquement un vecteur de dimension M (le nombre d&rsquo;observations), le tableau d&rsquo;indices produit par <strong>argsort()<\/strong> est rigoureusement de taille M, quelle que soit la largeur N de la matrice. L&rsquo;indexation avanc\u00e9e <strong>X[indices]<\/strong> projette ensuite ce tableau de taille M sur l&rsquo;axe z\u00e9ro, r\u00e9arrangeant l&rsquo;int\u00e9gralit\u00e9 des rang\u00e9es sans aucune ambigu\u00eft\u00e9 de cardinalit\u00e9.<\/p>\n<p>Une vigilance particuli\u00e8re s&rsquo;impose n\u00e9anmoins lors de la manipulation de matrices N &gt;&gt; M. Tenter d&rsquo;indexer une colonne en utilisant un indice sup\u00e9rieur ou \u00e9gal \u00e0 la largeur r\u00e9elle d\u00e9clenche une exception de type <strong>IndexError: index out of bounds<\/strong>. L&rsquo;impl\u00e9mentation de contr\u00f4les rigoureux des bornes dimensionnelles via l&rsquo;attribut <strong>shape<\/strong> du ndarray avant tout ordonnancement indirect constitue une pratique essentielle pour garantir la robustesse des flux de traitement automatique.<\/p>\n<h3>5.3 Extension aux tableaux multidimensionnels d&rsquo;ordre sup\u00e9rieur (3D et tenseurs)<\/h3>\n<p>Lorsque l&rsquo;on manipule des structures de rang tensoriel sup\u00e9rieur \u00e0 deux (par exemple des tenseurs tridimensionnels de forme (P, M, N) repr\u00e9sentant des images hyperspectrales ou des s\u00e9ries temporelles multivari\u00e9es de plusieurs capteurs), la notion de tri par colonne n\u00e9cessite une red\u00e9finition g\u00e9om\u00e9trique formelle. On ne cherche plus \u00e0 ordonner une matrice unique, mais \u00e0 ordonner des matrices bidimensionnelles imbriqu\u00e9es le long d&rsquo;un hyperplan sp\u00e9cifique.<\/p>\n<p>L&rsquo;application directe de la syntaxe matricielle standard sur un tenseur d&rsquo;ordre 3 \u00e9choue ou produit des r\u00e9organisations inattendues des hyperplans frontaux. Pour trier chaque tranche matricielle d&rsquo;un tenseur selon l&rsquo;une de ses colonnes, il est n\u00e9cessaire d&rsquo;it\u00e9rer de mani\u00e8re contr\u00f4l\u00e9e le long du premier axe, ou d&rsquo;exploiter la fonction vectoris\u00e9e <strong>numpy.apply_along_axis()<\/strong>. Cette derni\u00e8re permet de diffuser une fonction de tri indirect le long des axes souhait\u00e9s tout en maintenant la coh\u00e9rence dimensionnelle globale de la structure.<\/p>\n<p>Une autre alternative consiste \u00e0 remodeler temporairement le tenseur via la m\u00e9thode <strong>reshape()<\/strong> afin d&rsquo;agr\u00e9ger les dimensions non cibl\u00e9es en un plan bidimensionnel \u00e9quivalent, d&rsquo;ex\u00e9cuter la permutation vectorielle standard, puis de restaurer la topologie originelle du tenseur. Cette approche exige une ma\u00eetrise rigoureuse de la contigu\u00eft\u00e9 m\u00e9moire pour \u00e9viter des op\u00e9rations de duplication massives qui d\u00e9graderaient l&rsquo;efficience computationnelle de l&rsquo;application.<\/p>\n<h2>6. Tri hi\u00e9rarchique : Ordonnancement selon plusieurs colonnes avec numpy.lexsort()<\/h2>\n<h3>6.1 Limites conceptuelles de argsort pour le tri multi-crit\u00e8res<\/h3>\n<p>Dans de nombreuses situations concr\u00e8tes d&rsquo;analyse matricielle, le tri selon une variable unique s&rsquo;av\u00e8re insuffisant en raison de l&rsquo;existence de valeurs identiques (ex \u00e6quo). Lorsqu&rsquo;une pluralit\u00e9 d&rsquo;observations partagent exactement la m\u00eame modalit\u00e9 sur la colonne directrice primaire, il devient indispensable d&rsquo;introduire une colonne directrice secondaire pour d\u00e9partager les ex \u00e6quo, voire une colonne tertiaire en cas de nouvelles \u00e9galit\u00e9s.<\/p>\n<p>Tenter de r\u00e9soudre ce probl\u00e8me par des appels cons\u00e9cutifs \u00e0 la fonction <strong>argsort()<\/strong> constitue une erreur m\u00e9thodologique classique. Si l&rsquo;on trie d&rsquo;abord la matrice selon la colonne secondaire, puis qu&rsquo;on la trie ensuite selon la colonne primaire au moyen d&rsquo;un algorithme instable comme le <em>quicksort<\/em> standard, l&rsquo;ordre pr\u00e9c\u00e9demment \u00e9tabli sur la colonne secondaire sera partiellement d\u00e9truit lors de la seconde permutation. M\u00eame en utilisant un algorithme stable tel que le <em>mergesort<\/em>, l&rsquo;encha\u00eenement de passes d&rsquo;indexation successives induit des allocations de copies matricielles r\u00e9p\u00e9t\u00e9es et hautement inefficaces.<\/p>\n<p>L&rsquo;alg\u00e8bre relationnelle impose le recours \u00e0 un <em>ordre lexicographique strict<\/em>, concept math\u00e9matique analogue \u00e0 l&rsquo;ordonnancement des mots dans un dictionnaire selon leurs lettres successives. Pour r\u00e9pondre \u00e0 cette exigence formelle avec une performance optimale, NumPy int\u00e8gre une fonction sp\u00e9cialis\u00e9e hautement optimis\u00e9e : <strong>numpy.lexsort()<\/strong>.<\/p>\n<h3>6.2 Fonctionnement interne et syntaxe contre-intuitive de lexsort<\/h3>\n<p>La fonction <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/reference\/generated\/numpy.lexsort.html\">numpy.lexsort()<\/a> calcule les indices de permutation r\u00e9sultant d&rsquo;un tri lexicographique appliqu\u00e9 sur une collection de cl\u00e9s. Toutefois, sa syntaxe pr\u00e9sente une particularit\u00e9 qui d\u00e9concerte fr\u00e9quemment les utilisateurs non avertis : <strong>l&rsquo;ordre de passage des cl\u00e9s dans le tuple d&rsquo;arguments est invers\u00e9 par rapport \u00e0 leur ordre de priorit\u00e9 hi\u00e9rarchique r\u00e9el<\/strong>.<\/p>\n<p>Formellement, si l&rsquo;on transmet \u00e0 la fonction un tuple de colonnes (C_secondaire, C_primaire), la fonction \u00e9value en r\u00e9alit\u00e9 <strong>C_primaire<\/strong> comme le crit\u00e8re de tri principal, et n&rsquo;utilise <strong>C_secondaire<\/strong> que comme cl\u00e9 de d\u00e9partage pour les lignes o\u00f9 C_primaire pr\u00e9sente des valeurs strictement \u00e9gales. Cette conception d\u00e9rive de l&rsquo;impl\u00e9mentation algorithmique historique du tri lexicographique inspir\u00e9e du tri par base (<em>radix sort<\/em>), qui proc\u00e8de de la cl\u00e9 la moins significative vers la cl\u00e9 la plus significative.<\/p>\n<p>Consid\u00e9rons une matrice bidimensionnelle <strong>X<\/strong> dont nous souhaitons ordonner les lignes selon la colonne 0 en priorit\u00e9 principale, et selon la colonne 2 en cas d&rsquo;\u00e9galit\u00e9 sur la premi\u00e8re. La syntaxe exacte s&rsquo;exprime ainsi : <strong>indices = np.lexsort((X[:, 2], X[:, 0]))<\/strong>. Le tableau d&rsquo;indices produit peut ensuite \u00eatre imm\u00e9diatement projet\u00e9 sur la matrice par l&rsquo;indexation avanc\u00e9e <strong>X[indices]<\/strong>. Si l&rsquo;utilisateur inverse par m\u00e9garde la position des cl\u00e9s dans le tuple, l&rsquo;arbitrage sera erron\u00e9 et accordera la priorit\u00e9 absolue \u00e0 la colonne 2, faussant la hi\u00e9rarchie attendue.<\/p>\n<h3>6.3 \u00c9tude de cas : R\u00e9solution d&rsquo;\u00e9galit\u00e9s sur une variable par une colonne d&rsquo;arbitrage<\/h3>\n<p>Afin d&rsquo;illustrer la pertinence de ce m\u00e9canisme, consid\u00e9rons un tableau de relev\u00e9s exp\u00e9rimentaux comprenant quatre individus et trois variables quantitatives. La premi\u00e8re colonne contient des identifiants de cat\u00e9gories (par exemple les entiers 1, 2, 1, 2) ; la seconde colonne enregistre des scores d&rsquo;\u00e9valuation continue (par exemple 85.0, 72.0, 94.0, 68.0) ; et la troisi\u00e8me colonne consigne des dur\u00e9es d&rsquo;ex\u00e9cution. Nous souhaitons classer les sujets d&rsquo;abord selon leur groupe cat\u00e9goriel (colonne 0), et pour chaque groupe, classer les sujets par score croissant (colonne 1).<\/p>\n<p>En observant la colonne 0, nous constatons deux ex \u00e6quo pour la cat\u00e9gorie 1 (lignes 0 et 2) et deux ex \u00e6quo pour la cat\u00e9gorie 2 (lignes 1 et 3). L&rsquo;appel \u00e0 <strong>np.lexsort((donnees[:, 1], donnees[:, 0]))<\/strong> transmet en premi\u00e8re position la cl\u00e9 de d\u00e9partage (colonne 1) et en seconde position la cl\u00e9 principale (colonne 0). L&rsquo;algorithme analyse l&rsquo;ensemble des vecteurs de mani\u00e8re conjointe au niveau C et retourne la permutation d&rsquo;indices [0, 2, 3, 1].<\/p>\n<p>En appliquant cette permutation \u00e0 la matrice originale via <strong>donnees[indices]<\/strong>, les deux observations de la classe 1 sont positionn\u00e9es en t\u00eate. Entre ces deux lignes, celle d\u00e9tenant le score 85.0 pr\u00e9c\u00e8de fid\u00e8lement celle affichant 94.0. Ensuite apparaissent les observations de la classe 2, o\u00f9 la ligne d\u00e9tenant le score 68.0 devance celle d\u00e9tenant 72.0. La r\u00e9solution des ex \u00e6quo s&rsquo;est op\u00e9r\u00e9e de mani\u00e8re rigoureuse, en une passe algorithmique unique, sans recourir \u00e0 des transformations matricielles redondantes.<\/p>\n<h2>7. Gestion des valeurs sp\u00e9ciales, donn\u00e9es manquantes et types h\u00e9t\u00e9rog\u00e8nes<\/h2>\n<h3>7.1 Comportement du tri en pr\u00e9sence de valeurs NaN (Not a Number)<\/h3>\n<p>Dans les jeux de donn\u00e9es scientifiques r\u00e9els, l&rsquo;occurrence de donn\u00e9es manquantes ou ind\u00e9termin\u00e9es, repr\u00e9sent\u00e9es par le marqueur \u00e0 virgule flottante standard <strong>numpy.nan<\/strong>, est un ph\u00e9nom\u00e8ne omnipr\u00e9sent. La norme internationale IEEE 754 relative au calcul en virgule flottante stipule express\u00e9ment qu&rsquo;une valeur NaN ne poss\u00e8de aucune relation d&rsquo;ordre : toute comparaison logique impliquant un NaN (qu&rsquo;il s&rsquo;agisse d&rsquo;une inf\u00e9riorit\u00e9, d&rsquo;une sup\u00e9riorit\u00e9 ou m\u00eame d&rsquo;une \u00e9galit\u00e9 stricte de NaN avec lui-m\u00eame) s&rsquo;\u00e9value syst\u00e9matiquement \u00e0 <em>Faux<\/em>.<\/p>\n<p>Cette absence de comparabilit\u00e9 pose un d\u00e9fi th\u00e9orique majeur pour les algorithmes de tri traditionnels fond\u00e9s sur des partitions d&rsquo;in\u00e9galit\u00e9s. Pour garantir un comportement d\u00e9terministe, NumPy impl\u00e9mente une convention de gestion interne sp\u00e9cifique : <strong>les valeurs NaN sont syst\u00e9matiquement rel\u00e9gu\u00e9es \u00e0 la fin du tableau lors d&rsquo;un tri croissant<\/strong>. L&rsquo;algorithme isole les valeurs ind\u00e9termin\u00e9es et les positionne aux indices les plus \u00e9lev\u00e9s du tableau d&rsquo;indices produit par <strong>argsort()<\/strong>.<\/p>\n<p>Toutefois, un pi\u00e8ge subtil surgit lors de l&rsquo;inversion de l&rsquo;ordre de tri pour obtenir une s\u00e9quence descendante. Si l&rsquo;on applique le d\u00e9coupage inverse direct <strong>[::-1]<\/strong> sur les indices produits, les valeurs NaN, qui \u00e9taient situ\u00e9es en queue de peloton, se retrouvent m\u00e9caniquement projet\u00e9es en toute premi\u00e8re position de la matrice tri\u00e9e. Si l&rsquo;analyste souhaite classer ses donn\u00e9es par ordre d\u00e9croissant tout en maintenant les valeurs manquantes \u00e0 la fin du tableau, il est n\u00e9cessaire de concevoir un pr\u00e9-filtrage logique ou de partitionner la matrice en combinant la d\u00e9tection bool\u00e9enne via <strong>numpy.isnan()<\/strong> et l&rsquo;indexation conditionnelle.<\/p>\n<h3>7.2 Tri de colonnes contenant des cha\u00eenes de caract\u00e8res ou des objets mixtes<\/h3>\n<p>Bien que NumPy soit prioritairement optimis\u00e9 pour le calcul num\u00e9rique continu, il permet la d\u00e9finition de tableaux h\u00e9bergeant des donn\u00e9es textuelles sous des types primitifs de longueur fixe tels que les cha\u00eenes d&rsquo;octets (type <strong>string_<\/strong> ou &lsquo;S&rsquo;) et les cha\u00eenes de caract\u00e8res Unicode (type <strong>unicode_<\/strong> ou &lsquo;U&rsquo;). Lorsque l&rsquo;on proc\u00e8de au tri d&rsquo;une matrice selon une colonne textuelle, NumPy applique scrupuleusement l&rsquo;ordre lexicographique bas\u00e9 sur les points de code binaires ou Unicode des caract\u00e8res composant chaque cha\u00eene.<\/p>\n<p>La situation devient en revanche critique lorsque le tableau est instanci\u00e9 avec le type g\u00e9n\u00e9rique <strong>dtype=&rsquo;object&rsquo;<\/strong>. Ce type de repli permet d&rsquo;int\u00e9grer dans le ndarray des objets Python h\u00e9t\u00e9rog\u00e8nes arbitraires, tels que des dictionnaires, des listes ou des cha\u00eenes de longueurs variables. Lors de l&rsquo;\u00e9valuation d&rsquo;un <strong>argsort()<\/strong> sur une colonne de type &lsquo;object&rsquo;, NumPy est contraint de d\u00e9sactiver ses routines optimis\u00e9es en C et d&rsquo;appeler s\u00e9quentiellement la m\u00e9thode de comparaison interne <strong>__lt__()<\/strong> de chaque objet via l&rsquo;interpr\u00e9teur Python.<\/p>\n<p>Ce basculement induit une d\u00e9gradation catastrophique des performances d&rsquo;ex\u00e9cution, augmentant les temps de calcul de plusieurs ordres de grandeur. De surcro\u00eet, si la colonne d&rsquo;arbitrage de type &lsquo;object&rsquo; contient des \u00e9l\u00e9ments dont les types respectifs sont mutuellement incomparables (par exemple une imbrication d&rsquo;entiers et de cha\u00eenes de caract\u00e8res sous Python 3), l&rsquo;ex\u00e9cution de l&rsquo;op\u00e9ration l\u00e8vera imm\u00e9diatement une exception bloquante de type <strong>TypeError: &lsquo;&lt;&lsquo; not supported between instances<\/strong>. Il est donc indispensable d&rsquo;assurer l&rsquo;homog\u00e9n\u00e9it\u00e9 stricte des types de donn\u00e9es en amont de toute tentative de tri indirect.<\/p>\n<h3>7.3 Utilisation des tableaux masqu\u00e9s (numpy.ma) pour exclure certaines entr\u00e9es<\/h3>\n<p>Pour g\u00e9rer les donn\u00e9es corrompues, aberrantes ou manquantes sans alt\u00e9rer physiquement l&rsquo;int\u00e9grit\u00e9 volumique de la matrice de travail, le sous-module sp\u00e9cialis\u00e9 <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/reference\/maskedarray.generic.html\">numpy.ma<\/a> met \u00e0 disposition la structure du tableau masqu\u00e9 (<em>MaskedArray<\/em>). Cette structure associe au tableau de donn\u00e9es sous-jacent un tableau bool\u00e9en de m\u00eame dimension, servant de filtre logique pour occulter certaines entr\u00e9es lors des calculs statistiques.<\/p>\n<p>Lorsqu&rsquo;un tableau masqu\u00e9 est soumis \u00e0 un tri par colonne, le moteur algorithmique neutralise automatiquement les cellules identifi\u00e9es comme invalides. La m\u00e9thode <strong>numpy.ma.argsort()<\/strong> int\u00e8gre un param\u00e8tre sp\u00e9cialis\u00e9 nomm\u00e9 <strong>fill_value<\/strong>, qui permet de stipuler la valeur de substitution th\u00e9orique attribu\u00e9e aux \u00e9l\u00e9ments masqu\u00e9s lors de l&rsquo;\u00e9valuation de la relation d&rsquo;ordre, permettant de choisir pr\u00e9cis\u00e9ment si les donn\u00e9es occult\u00e9es doivent \u00eatre rejet\u00e9es en d\u00e9but ou en fin de s\u00e9quence.<\/p>\n<p>L&rsquo;utilisation des tableaux masqu\u00e9s offre une alternative particuli\u00e8rement \u00e9l\u00e9gante aux op\u00e9rations de suppression et r\u00e9insertion de lignes. Elle permet \u00e0 l&rsquo;ing\u00e9nieur de donn\u00e9es d&rsquo;isoler temporairement des observations atypiques, d&rsquo;ordonner les rang\u00e9es selon les seules observations jug\u00e9es fiables, puis de lever le masque sur l&rsquo;ensemble du tableau r\u00e9sultat sans jamais avoir bris\u00e9 la topologie des structures de stockage.<\/p>\n<h2>8. Alternative par tableaux structur\u00e9s (Structured Arrays) et champs nomm\u00e9s<\/h2>\n<h3>8.1 D\u00e9finition formelle des types compos\u00e9s (dtypes composites)<\/h3>\n<p>NumPy int\u00e8gre une fonctionnalit\u00e9 puissante et souvent sous-estim\u00e9e, situ\u00e9e \u00e0 mi-chemin entre la matrice homog\u00e8ne brute et la trame de donn\u00e9es relationnelle : les <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/user\/basics.rec.html\">tableaux structur\u00e9s<\/a> (<em>Structured Arrays<\/em>). Contrairement aux matrices classiques o\u00f9 chaque cellule est identifi\u00e9e uniquement par ses coordonn\u00e9es spatiales (ligne, colonne) et partage un type identique, les tableaux structur\u00e9s permettent de concevoir des types de donn\u00e9es composites (<em>compound dtypes<\/em>) au sein desquels chaque colonne est pourvue d&rsquo;un identifiant textuel et d&rsquo;un type primitif ind\u00e9pendant.<\/p>\n<p>Pour mat\u00e9rialiser cette structure, on d\u00e9finit formellement un descripteur de type sous forme d&rsquo;une liste de tuples associant le nom du champ \u00e0 son format m\u00e9moire (par exemple &lsquo;f8&rsquo; pour un flottant 64 bits, &lsquo;i4&rsquo; pour un entier 32 bits, ou &lsquo;U10&rsquo; pour une cha\u00eene Unicode de dix caract\u00e8res). La matrice cesse alors conceptuellement d&rsquo;\u00eatre un tableau bidimensionnel pour devenir un <strong>tableau unidimensionnel d&rsquo;enregistrements compos\u00e9s<\/strong> (similaire \u00e0 une structure <em>struct<\/em> en langage C).<\/p>\n<p>Cette approche unifie la manipulation de colonnes aux caract\u00e9ristiques typologiques disparates au sein d&rsquo;un bloc contigu unique. L&rsquo;enregistrement horizontal est encapsul\u00e9 en tant qu&rsquo;unit\u00e9 atomique, ce qui modifie substantiellement la m\u00e9canique et la syntaxe des op\u00e9rations de tri.<\/p>\n<h3>8.2 Utilisation de numpy.sort() avec le param\u00e8tre &lsquo;order&rsquo;<\/h3>\n<p>L&rsquo;avantage cardinal des tableaux structur\u00e9s r\u00e9side dans la r\u00e9habilitation directe de la m\u00e9thode native <strong>numpy.sort()<\/strong> pour le tri par colonne. Puisque les colonnes sont formellement reconnues comme des champs d&rsquo;enregistrement nomm\u00e9s au sein d&rsquo;une structure unidimensionnelle, il n&rsquo;y a plus aucun risque de briser la coh\u00e9sion des rang\u00e9es par un tri scalaire ind\u00e9pendant.<\/p>\n<p>La syntaxe de tri s&rsquo;effectue en transmettant le nom du champ de r\u00e9f\u00e9rence au param\u00e8tre formel <strong>order<\/strong> : <strong>tableau_trie = np.sort(tableau_structure, order=&rsquo;nom_du_champ&rsquo;)<\/strong>. L&rsquo;algorithme sous-jacent inspecte le d\u00e9calage binaire (<em>offset<\/em>) du champ d\u00e9sign\u00e9 au sein de la structure m\u00e9moire de chaque enregistrement, \u00e9value les relations d&rsquo;ordre entre ces valeurs, et r\u00e9ordonne l&rsquo;ensemble des blocs d&rsquo;enregistrements contigus en une passe unifi\u00e9e.<\/p>\n<p>De surcro\u00eet, le param\u00e8tre <strong>order<\/strong> simplifie radicalement l&rsquo;expression du tri hi\u00e9rarchique multi-colonnes. Au lieu de manipuler la syntaxe invers\u00e9e de <strong>numpy.lexsort()<\/strong>, il suffit de fournir une liste s\u00e9quentielle de cha\u00eenes de caract\u00e8res sp\u00e9cifiant la hi\u00e9rarchie exacte des crit\u00e8res : <strong>np.sort(tableau_structure, order=[&lsquo;critere_primaire&rsquo;, &lsquo;critere_secondaire&rsquo;])<\/strong>. La lisibilit\u00e9 conceptuelle et la maintenabilit\u00e9 du code source au sein de grands projets logiciels s&rsquo;en trouvent consid\u00e9rablement renforc\u00e9es.<\/p>\n<h3>8.3 Comparaison technique : argsort vs tableaux structur\u00e9s<\/h3>\n<p>Le choix entre l&rsquo;approche canonique par <strong>argsort<\/strong> sur matrice dense et l&rsquo;usage des tableaux structur\u00e9s repose sur un compromis d&rsquo;ing\u00e9nierie entre souplesse de calcul et lisibilit\u00e9 applicative. L&rsquo;\u00e9valuation comparative de ces deux approches implique d&rsquo;examiner le co\u00fbt de conversion (<em>overhead<\/em>) et les sch\u00e9mas d&rsquo;acc\u00e8s m\u00e9moire ult\u00e9rieurs.<\/p>\n<p>La conversion d&rsquo;une matrice num\u00e9rique dense standard vers un tableau structur\u00e9 n&rsquo;est pas une simple op\u00e9ration logique gratuite : elle requiert la red\u00e9finition compl\u00e8te de l&rsquo;en-t\u00eate de type et implique fr\u00e9quemment une redistribution m\u00e9moire pour adapter l&rsquo;alignement des octets aux contraintes mat\u00e9rielles de la structure cible. De surcro\u00eet, une fois converti en tableau structur\u00e9, l&rsquo;objet perd son aptitude \u00e0 subir des op\u00e9rations d&rsquo;alg\u00e8bre lin\u00e9aire globales (telles que le produit matriciel <strong>np.dot<\/strong> ou la d\u00e9composition en valeurs singuli\u00e8res), les biblioth\u00e8ques BLAS\/LAPACK ne reconnaissant pas les types composites arbitraires.<\/p>\n<p>Par cons\u00e9quent, si le pipeline de donn\u00e9es consiste principalement en des op\u00e9rations math\u00e9matiques vectoris\u00e9es et que le tri n&rsquo;est qu&rsquo;une \u00e9tape interm\u00e9diaire ponctuelle, la m\u00e9thode par <strong>argsort()<\/strong> demeure la solution la plus performante et la plus \u00e9conome en ressources. En revanche, si le jeu de donn\u00e9es manipule intrins\u00e8quement des colonnes h\u00e9t\u00e9rog\u00e8nes (identifiants, cat\u00e9gories, grandeurs continues) et transite vers des phases d&rsquo;exportation ou de filtrage relationnel, les tableaux structur\u00e9s constituent une architecture \u00e9l\u00e9gante et performante.<\/p>\n<h2>9. Analyse de la complexit\u00e9 algorithmique et des performances computationnelles<\/h2>\n<h3>9.1 Complexit\u00e9 temporelle formelle du tri indirect<\/h3>\n<p>L&rsquo;\u00e9valuation des performances du tri indirect d&rsquo;une matrice bidimensionnelle de dimensions M lignes par N colonnes n\u00e9cessite d&rsquo;analyser la complexit\u00e9 asymptotique de ses deux \u00e9tapes cons\u00e9cutives : la g\u00e9n\u00e9ration de la permutation d&rsquo;indices via <strong>argsort()<\/strong> et la r\u00e9organisation spatiale des donn\u00e9es via le Fancy Indexing.<\/p>\n<p>La phase d&rsquo;extraction de la colonne directrice <strong>X[:, j]<\/strong> sous forme de vue unidimensionnelle s&rsquo;ex\u00e9cute en temps constant O(1). L&rsquo;application de <strong>argsort()<\/strong> sur ce vecteur de taille M rel\u00e8ve ensuite des algorithmes de tri comparatif standard. L&rsquo;impl\u00e9mentation par d\u00e9faut fond\u00e9e sur le <em>quicksort<\/em> affiche une complexit\u00e9 temporelle moyenne de l&rsquo;ordre de <strong>O(M log M)<\/strong>, avec un cas d\u00e9favorable th\u00e9orique quadratique en O(M^2) tr\u00e8s largement pr\u00e9venu par les heuristiques de choix de pivot. Si le d\u00e9veloppeur configure l&rsquo;argument <em>kind=&rsquo;mergesort&rsquo;<\/em>, la complexit\u00e9 temporelle est rigoureusement garantie en <strong>O(M log M)<\/strong> dans le pire des cas.<\/p>\n<p>La phase subs\u00e9quente de r\u00e9organisation par indexation avanc\u00e9e exige ensuite de copier M lignes compos\u00e9es chacune de N \u00e9l\u00e9ments scalaires vers le tampon r\u00e9cepteur. La complexit\u00e9 temporelle de cette projection est strictement lin\u00e9aire par rapport au volume total d&rsquo;\u00e9l\u00e9ments d\u00e9plac\u00e9s, soit <strong>O(M * N)<\/strong>. La complexit\u00e9 asymptotique globale de l&rsquo;op\u00e9ration compl\u00e8te s&rsquo;\u00e9tablit donc formellement \u00e0 :<\/p>\n<p><strong>T(M, N) = O(M log M + M * N) = O(M (log M + N))<\/strong><\/p>\n<p>Cette relation met en \u00e9vidence un comportement d&rsquo;\u00e9chelle crucial : lorsque le nombre de variables N devient tr\u00e8s \u00e9lev\u00e9 par rapport au nombre d&rsquo;observations M, le co\u00fbt de copie physique de la m\u00e9moire domine largement le co\u00fbt algorithmique du tri de la colonne directrice.<\/p>\n<h3>9.2 Impact spatial et gestion des allocations m\u00e9moire<\/h3>\n<p>L&rsquo;analyse de la complexit\u00e9 spatiale met en lumi\u00e8re des contraintes mat\u00e9rielles significatives. Alors que le tri in-situ d&rsquo;un tableau unidimensionnel pr\u00e9sente une empreinte m\u00e9moire additionnelle minimale (O(log M) pour la pile d&rsquo;appels r\u00e9cursifs du quicksort, ou O(M) pour les tampons auxiliaires du mergesort), le tri indirect d&rsquo;une matrice impose des allocations transitoires consid\u00e9rables.<\/p>\n<p>Dans un premier temps, la fonction <strong>argsort()<\/strong> doit mat\u00e9rialiser le vecteur des indices r\u00e9sultants, ce qui induit une allocation initiale de M entiers de 64 bits (soit 8 * M octets). Dans un second temps, en vertu des r\u00e8gles du Fancy Indexing, la r\u00e9organisation de la matrice engendre l&rsquo;allocation int\u00e9grale d&rsquo;un nouveau ndarray aux dimensions identiques \u00e0 la matrice source (M * N \u00e9l\u00e9ments). Durant l&rsquo;ex\u00e9cution de l&rsquo;op\u00e9ration, l&#8217;empreinte m\u00e9moire totale du processus atteint temporairement une valeur \u00e9quivalente \u00e0 :<\/p>\n<p><strong>Espace Total = Empreinte(X) + Empreinte(Indices) + Empreinte(X_tri\u00e9) &approx; 2 * (M * N * sizeof(dtype)) + 8 * M octets<\/strong><\/p>\n<p>Dans le cadre du traitement de donn\u00e9es volumineuses (<em>Big Data<\/em>) approchant la capacit\u00e9 maximale de la m\u00e9moire vive disponible, cette duplication int\u00e9grale du volume matriciel est susceptible de d\u00e9clencher une d\u00e9faillance de saturation m\u00e9moire (<em>MemoryError<\/em>) ou d&rsquo;entra\u00eener une d\u00e9gradation critique des performances par mise en m\u00e9moire virtuelle sur disque (<em>swapping<\/em>). L&rsquo;ing\u00e9nieur doit imp\u00e9rativement anticiper ce pic d&rsquo;allocation dans son dimensionnement d&rsquo;infrastructure.<\/p>\n<h3>9.3 Effets de l&rsquo;agencement m\u00e9moire : Formats C-contiguous vs Fortran-contiguous<\/h3>\n<p>La disposition physique des \u00e9l\u00e9ments au sein du tampon m\u00e9moire influe drastiquement sur le d\u00e9bit de traitement effectif lors du tri indirect. Comme \u00e9voqu\u00e9 pr\u00e9c\u00e9demment, NumPy prend en charge deux conventions fondamentales d&rsquo;agencement matriciel : l&rsquo;ordre C (lignes contigu\u00ebs) et l&rsquo;ordre Fortran (colonnes contigu\u00ebs).<\/p>\n<p>Dans une matrice agenc\u00e9e selon le format C (par d\u00e9faut), les \u00e9l\u00e9ments d&rsquo;une m\u00eame ligne sont plac\u00e9s \u00e0 des adresses m\u00e9moire strictement cons\u00e9cutives. Lors de la phase pr\u00e9liminaire d&rsquo;extraction de la colonne directrice <strong>X[:, j]<\/strong>, le processeur doit lire des \u00e9l\u00e9ments s\u00e9par\u00e9s par un pas m\u00e9moire \u00e9gal \u00e0 la largeur totale de la ligne en octets. Cette lecture non contigu\u00eb \u00e0 grands pas provoque de multiples d\u00e9fauts de cache (<em>cache misses<\/em>) au niveau des lignes de cache L1 et L2 du processeur, le m\u00e9canisme de pr\u00e9chargement mat\u00e9riel ne pouvant anticiper efficacement ces sauts r\u00e9guliers dans le bloc m\u00e9moire.<\/p>\n<p>\u00c0 l&rsquo;inverse, si la matrice est stock\u00e9e au format Fortran (F-contiguous), la colonne directrice forme un bloc d&rsquo;octets strictement continu en m\u00e9moire vive, permettant une lecture lin\u00e9aire optimale lors de l&rsquo;ex\u00e9cution de <strong>argsort()<\/strong>. Cependant, lors de la seconde phase de Fancy Indexing, la r\u00e9organisation des lignes devient \u00e0 son tour non contigu\u00eb sur une matrice F-order, inversant le goulot d&rsquo;\u00e9tranglement mat\u00e9riel. La compr\u00e9hension approfondie de ces compromis de bas niveau permet d&rsquo;optimiser les performances en appliquant judicieusement des transpositions pr\u00e9alables ou des conversions d&rsquo;ordre m\u00e9moire avant les op\u00e9rations massives de tri.<\/p>\n<h2>10. Comparaison approfondie avec les structures de donn\u00e9es concurrentes<\/h2>\n<h3>10.1 NumPy argsort versus Pandas DataFrame.sort_values()<\/h3>\n<p>La biblioth\u00e8que <a rel=\"noopener noreferrer\" href=\"https:\/\/pandas.pydata.org\/\">Pandas<\/a>, \u00e9difi\u00e9e sur les fondations structurelles de NumPy, propose une abstraction de plus haut niveau pour la manipulation de donn\u00e9es tabulaires : la structure <em>DataFrame<\/em>. Celle-ci int\u00e8gre nativement la m\u00e9thode d\u00e9clarative <strong>sort_values()<\/strong>, dont la finalit\u00e9 fonctionnelle est pr\u00e9cis\u00e9ment d&rsquo;ordonner les lignes selon une ou plusieurs colonnes \u00e9tiquet\u00e9es.<\/p>\n<p>Sur le plan conceptuel, <strong>DataFrame.sort_values()<\/strong> d\u00e9l\u00e8gue en r\u00e9alit\u00e9 l&rsquo;\u00e9valuation de l&rsquo;ordre aux algorithmes sous-jacents de NumPy ou d&rsquo;extensions \u00e9crites en Cython. Cependant, Pandas incorpore une couche substantielle de m\u00e9tadonn\u00e9es de gestion, incluant la maintenance d&rsquo;index d&rsquo;alignement explicites, la v\u00e9rification dynamique des types par colonne et la propagation automatique des masques de valeurs manquantes. Cette encapsulation sophistiqu\u00e9e induit un surco\u00fbt d&rsquo;ex\u00e9cution (<em>overhead<\/em>) mesurable.<\/p>\n<p>Sur des matrices de dimensions modestes \u00e0 interm\u00e9diaires soumises \u00e0 des it\u00e9rations intenses (par exemple au sein de boucles d&rsquo;optimisation num\u00e9rique ou de simulations de Monte-Carlo), l&rsquo;usage direct de <strong>numpy.argsort()<\/strong> se r\u00e9v\u00e8le significativement plus rapide que son \u00e9quivalent Pandas, affichant des gains de temps d&rsquo;ex\u00e9cution de l&rsquo;ordre de 5 \u00e0 20 fois. En revanche, pour des applications orient\u00e9es vers l&rsquo;exploration de donn\u00e9es h\u00e9t\u00e9rog\u00e8nes o\u00f9 la lisibilit\u00e9 du code pr\u00e9vaut sur la micro-latence, l&rsquo;expressivit\u00e9 de <strong>DataFrame.sort_values()<\/strong> demeure particuli\u00e8rement appr\u00e9ciable.<\/p>\n<h3>10.2 Interaction avec SciPy et les matrices creuses (Sparse Matrices)<\/h3>\n<p>Dans de multiples branches de la physique computationnelle et du traitement automatique du langage naturel, les matrices manipul\u00e9es pr\u00e9sentent un taux de clairsemance extr\u00eamement \u00e9lev\u00e9 (une immense majorit\u00e9 d&rsquo;\u00e9l\u00e9ments \u00e9tant nuls). L&rsquo;\u00e9cosyst\u00e8me SciPy fournit des structures d\u00e9di\u00e9es sous le module <strong>scipy.sparse<\/strong>, notamment les formats CSR (<em>Compressed Sparse Row<\/em>) et CSC (<em>Compressed Sparse Column<\/em>), afin de ne stocker que les coefficients non nuls.<\/p>\n<p>Tenter d&rsquo;appliquer directement la syntaxe <strong>X[X[:, j].argsort()]<\/strong> sur une matrice creuse de type CSR aboutit g\u00e9n\u00e9ralement \u00e0 une erreur ou \u00e0 un \u00e9croulement dramatique des performances. En effet, l&rsquo;extraction de colonne <strong>X[:, j]<\/strong> sur un format CSR convertit fr\u00e9quemment la s\u00e9lection en une sous-matrice creuse unidimensionnelle, sur laquelle l&rsquo;appel direct \u00e0 <strong>argsort()<\/strong> n&rsquo;est pas vectoris\u00e9 de la m\u00eame mani\u00e8re que sur un ndarray dense standard.<\/p>\n<p>Pour ordonner convenablement les lignes d&rsquo;une matrice creuse selon une colonne donn\u00e9e, la m\u00e9thodologie optimale consiste \u00e0 extraire la colonne sous forme d&rsquo;un tableau dense via <strong>toarray().flatten()<\/strong>, \u00e0 calculer le vecteur de permutation d&rsquo;indices au moyen de <strong>numpy.argsort()<\/strong>, puis \u00e0 appliquer ce tableau d&rsquo;indices aux lignes de la matrice creuse CSR. L&rsquo;indexation de tranches de lignes sur une structure CSR \u00e9tant optimis\u00e9e au niveau structurel, cette d\u00e9marche pr\u00e9serve la compression spatiale globale tout en garantissant un r\u00e9ordonnancement correct des observations clairsem\u00e9es.<\/p>\n<h3>10.3 Tri de listes imbriqu\u00e9es Python natives : Justification de l&rsquo;abandon du code pur<\/h3>\n<p>Il est instructif de comparer les performances du tri vectoris\u00e9 NumPy avec les solutions \u00e9crites en pur code Python manipulant des listes imbriqu\u00e9es. En Python standard, une matrice bidimensionnelle est usuellement repr\u00e9sent\u00e9e sous la forme d&rsquo;une liste de listes, et le tri par colonne s&rsquo;ex\u00e9cute classiquement via la fonction int\u00e9gr\u00e9e <strong>sorted()<\/strong> coupl\u00e9e \u00e0 une expression anonyme : <strong>sorted(matrice, key=lambda row: row[j])<\/strong>.<\/p>\n<p>Bien que cette syntaxe soit \u00e9l\u00e9gante et native, elle souffre de s\u00e9v\u00e8res p\u00e9nalit\u00e9s d&rsquo;ex\u00e9cution inh\u00e9rentes au mod\u00e8le d&rsquo;\u00e9valuation de l&rsquo;interpr\u00e9teur CPython. Pour chaque ligne de la matrice, l&rsquo;interpr\u00e9teur doit ex\u00e9cuter un appel de fonction Python (le lambda) afin d&rsquo;extraire la cl\u00e9 de tri, franchir les pointeurs dynamiques vers les scalaires encapsul\u00e9s dans des objets de type PyObject, et comparer ces structures via des m\u00e9canismes de liaison dynamique. De plus, la localit\u00e9 spatiale des listes de listes en m\u00e9moire vive est extr\u00eamement m\u00e9diocre en raison de la fragmentation du tas.<\/p>\n<p>D\u00e8s lors que le volume de donn\u00e9es franchit quelques milliers d&rsquo;enregistrements, le tri indirect ex\u00e9cut\u00e9 via <strong>numpy.argsort()<\/strong> surpasse le code natif Python par des facteurs d&rsquo;acc\u00e9l\u00e9ration atteignant fr\u00e9quemment deux ordres de grandeur. Cette sup\u00e9riorit\u00e9 absolue illustre la puissance du mod\u00e8le de donn\u00e9es compil\u00e9 et contigu de NumPy, rendant l&rsquo;usage du code Python pur inadapt\u00e9 aux exigences computationnelles contemporaines.<\/p>\n<h2>11. Erreurs courantes, pi\u00e8ges syntaxiques et strat\u00e9gies de d\u00e9bogage<\/h2>\n<h3>11.1 Confusion entre tri par ligne et tri au sein de chaque ligne<\/h3>\n<p>L&rsquo;une des erreurs les plus d\u00e9vastatrices et fr\u00e9quemment observ\u00e9es chez les praticiens novices consiste \u00e0 utiliser la fonction <strong>numpy.sort()<\/strong> en lui passant un argument d&rsquo;axe erron\u00e9 dans l&rsquo;espoir de trier une matrice selon une colonne. L&rsquo;instruction fautive s&rsquo;exprime typiquement ainsi : <strong>np.sort(X, axis=0)<\/strong>.<\/p>\n<p>Il est fondamental de rappeler ce qui se produit lors de cette invocation : NumPy parcourt ind\u00e9pendamment chaque colonne de la matrice et ordonne les scalaires qui la composent du plus petit au plus grand. Par cons\u00e9quent, les valeurs de la premi\u00e8re colonne sont tri\u00e9es de fa\u00e7on totalement isol\u00e9e par rapport aux valeurs de la seconde colonne ou de la troisi\u00e8me colonne. L&rsquo;int\u00e9grit\u00e9 relationnelle entre les variables d&rsquo;une m\u00eame ligne est ainsi irr\u00e9m\u00e9diablement rompue.<\/p>\n<p>Cette confusion provient d&rsquo;un amalgame linguistique entre l&rsquo;action d&rsquo;ordonner l&rsquo;ensemble des enregistrements vectoriels le long de l&rsquo;axe vertical (axe 0) et l&rsquo;action d&rsquo;ordonner les composantes internes de chaque vecteur ind\u00e9pendamment. Pour maintenir la coh\u00e9sion statistique d&rsquo;un jeu de donn\u00e9es, il convient de retenir une r\u00e8gle absolue : <strong>le tri d&rsquo;une matrice bidimensionnelle selon les valeurs d&rsquo;une colonne ne doit jamais \u00eatre ex\u00e9cut\u00e9 via un appel direct \u00e0 numpy.sort(X, axis=0)<\/strong>, mais imp\u00e9rativement par une proc\u00e9dure d&rsquo;indexation indirecte par permutation d&rsquo;indices.<\/p>\n<h3>11.2 Erreurs de dimensionnalit\u00e9 et d\u00e9coupage incorrect<\/h3>\n<p>Un autre pi\u00e8ge fr\u00e9quent r\u00e9side dans des omissions de ponctuation ou des formulations approximatives du d\u00e9coupage matriciel, conduisant \u00e0 des r\u00e9ductions dimensionnelles inattendues ou \u00e0 des erreurs de broadcast.<\/p>\n<p>Une confusion symptomatique oppose les deux \u00e9critures suivantes : <strong>X[X[:, j].argsort()]<\/strong> et <strong>X[X[:, j].argsort(), :]<\/strong>. Sur le plan de la s\u00e9mantique de NumPy, ces deux formulations sont formellement \u00e9quivalentes : en l&rsquo;absence de sp\u00e9cification du second axe, l&rsquo;indexation avanc\u00e9e consid\u00e8re implicitement que l&rsquo;int\u00e9gralit\u00e9 des dimensions restantes doit \u00eatre conserv\u00e9e dans son ordre naturel. N\u00e9anmoins, l&rsquo;omission des deux-points \u00e0 l&rsquo;int\u00e9rieur de l&rsquo;extraction de la colonne directrice elle-m\u00eame, comme dans <strong>X[j].argsort()<\/strong>, produit un comportement radicalement erron\u00e9 : cette syntaxe extrait en r\u00e9alit\u00e9 la j-i\u00e8me ligne de la matrice et non sa j-i\u00e8me colonne, aboutissant \u00e0 un r\u00e9ordonnancement totalement d\u00e9connect\u00e9 de l&rsquo;objectif analytique vis\u00e9.<\/p>\n<p>Par ailleurs, lors de l&rsquo;application de conditions logiques combin\u00e9es pour s\u00e9lectionner dynamiquement l&rsquo;indice de la colonne, il arrive que l&rsquo;utilisateur obtienne un tableau d&rsquo;indices de forme (M, 1) au lieu d&rsquo;un vecteur plat de forme (M,). La transmission d&rsquo;un tel tableau bidimensionnel d&rsquo;indices d\u00e9clenche des m\u00e9canismes d&rsquo;alignement multidimensionnel complexes (<em>broadcasting<\/em>), aboutissant soit \u00e0 la lev\u00e9e d&rsquo;une exception <strong>IndexError: too many indices for array<\/strong>, soit \u00e0 la production d&rsquo;un tableau tri\u00e9 dont les dimensions g\u00e9om\u00e9triques sont corrompues. L&rsquo;utilisation syst\u00e9matique de l&rsquo;aplatissement via <strong>flatten()<\/strong> ou <strong>squeeze()<\/strong> sur le vecteur d&rsquo;indices permet de s\u00e9curiser le typage dimensionnel.<\/p>\n<h3>11.3 Probl\u00e8mes li\u00e9s aux vues et \u00e0 la mutabilit\u00e9 involontaire<\/h3>\n<p>La distinction entre la cr\u00e9ation d&rsquo;une vue (<em>view<\/em>) et l&rsquo;allocation d&rsquo;une copie (<em>copy<\/em>) est au c\u0153ur de la gestion de la m\u00e9moire sous NumPy. De nombreux d\u00e9veloppeurs pr\u00e9sument \u00e0 tort que l&rsquo;assignation du r\u00e9sultat d&rsquo;un tri indirect permet d&rsquo;op\u00e9rer des modifications in-situ qui se r\u00e9percuteront automatiquement sur la matrice d&rsquo;origine.<\/p>\n<p>Comme nous l&rsquo;avons explicit\u00e9 dans la section consacr\u00e9e au Fancy Indexing, l&rsquo;application d&rsquo;un tableau d&rsquo;indices entiers \u00e0 une matrice g\u00e9n\u00e8re <strong>syst\u00e9matiquement et obligatoirement une copie physique int\u00e9grale<\/strong> des donn\u00e9es cibl\u00e9es. Consid\u00e9rons le cas d&rsquo;un script ex\u00e9cutant l&rsquo;instruction suivante : <strong>X_trie = X[X[:, 0].argsort()]<\/strong>, puis proc\u00e9dant \u00e0 la mise \u00e0 jour d&rsquo;un \u00e9l\u00e9ment particulier via <strong>X_trie[0, 0] = 999<\/strong>. L&rsquo;utilisateur qui s&rsquo;attendrait \u00e0 ce que la cellule originelle <strong>X[0, 0]<\/strong> soit modifi\u00e9e constatera que celle-ci conserve rigoureusement sa valeur initiale.<\/p>\n<p>Si la finalit\u00e9 du traitement est d&rsquo;actualiser la matrice de d\u00e9part de fa\u00e7on d\u00e9finitive pour qu&rsquo;elle contienne ses \u00e9l\u00e9ments dans l&rsquo;ordre tri\u00e9, il est indispensable de r\u00e9assigner explicitement l&rsquo;int\u00e9gralit\u00e9 de son bloc m\u00e9moire \u00e0 l&rsquo;aide de l&rsquo;indexation compl\u00e8te par tranche : <strong>X[:] = X[X[:, 0].argsort()]<\/strong>. Cette formulation r\u00e9\u00e9crit le contenu r\u00e9ordonn\u00e9 directement au sein du tampon m\u00e9moire initialement allou\u00e9, assurant la synchronisation des donn\u00e9es pour l&rsquo;ensemble des modules logiciels d\u00e9tenant une r\u00e9f\u00e9rence vers l&rsquo;objet X.<\/p>\n<h2>12. Applications pratiques et \u00e9tudes de cas appliqu\u00e9es<\/h2>\n<h3>12.1 Cas pratique 1 : Ordonnancement d&rsquo;une batterie de tests psychom\u00e9triques<\/h3>\n<p>Consid\u00e9rons une \u00e9tude clinique en psychologie cognitive impliquant une cohorte de sujets soumis \u00e0 une batterie d&rsquo;\u00e9valuations standardis\u00e9es. Les r\u00e9sultats exp\u00e9rimentaux sont consign\u00e9s au sein d&rsquo;une matrice bidimensionnelle de type flottant o\u00f9 chaque ligne correspond \u00e0 un participant unique, et dont les quatre colonnes h\u00e9bergent respectivement : l&rsquo;identifiant num\u00e9rique du sujet, son score d&rsquo;anxi\u00e9t\u00e9 situationnelle (\u00e9chelle continue de 0 \u00e0 100), son temps de latence cognitive (en millisecondes), et son indice d&rsquo;attention soutenue.<\/p>\n<p>L&rsquo;objectif analytique consiste \u00e0 r\u00e9organiser l&rsquo;ensemble de la matrice afin d&rsquo;ordonner les sujets selon leur niveau de vuln\u00e9rabilit\u00e9 anxieuse croissante (colonne d&rsquo;indice 1), dans le but de constituer des sous-groupes homog\u00e8nes par quartiles pour une analyse de variance subs\u00e9quente. La d\u00e9marche m\u00e9thodique s&rsquo;articule comme suit :<\/p>\n<ul>\n<li>Extraction du profil vectoriel d&rsquo;anxi\u00e9t\u00e9 le long du premier axe : <strong>scores_anxiete = matrice_sujets[:, 1]<\/strong>.<\/li>\n<li>D\u00e9termination de la permutation d&rsquo;indices au moyen de l&rsquo;algorithme de tri stable : <strong>indices_tri = scores_anxiete.argsort(kind=&rsquo;stable&rsquo;)<\/strong>.<\/li>\n<li>G\u00e9n\u00e9ration de la matrice ordonn\u00e9e par indexation avanc\u00e9e : <strong>matrice_ordonnee = matrice_sujets[indices_tri]<\/strong>.<\/li>\n<li>Calcul des percentiles statistiques directement sur la structure r\u00e9align\u00e9e afin d&rsquo;isoler pr\u00e9cis\u00e9ment les seuils de rupture clinique.<\/li>\n<\/ul>\n<p>Cette m\u00e9thodologie garantit que les temps de latence et les identifiants originels restent rigoureusement solidaires de la progression des scores d&rsquo;anxi\u00e9t\u00e9. L&rsquo;analyste peut ainsi extraire les premiers 25 % de lignes de la matrice ordonn\u00e9e pour caract\u00e9riser le groupe \u00e0 faible anxi\u00e9t\u00e9, tout en s&rsquo;assurant qu&rsquo;aucun sujet n&rsquo;a vu ses mesures cognitives dissoci\u00e9es de son profil clinique.<\/p>\n<h3>12.2 Cas pratique 2 : Alignement chronologique de signaux comportementaux<\/h3>\n<p>Dans les syst\u00e8mes d&rsquo;acquisition temps r\u00e9el et l&rsquo;Internet des objets (IoT), les signaux comportementaux sont fr\u00e9quemment collect\u00e9s par des passerelles de communication r\u00e9seau distribu\u00e9es. En raison de la gigue r\u00e9seau (<em>jitter<\/em>) et des asynchronismes de transmission, les paquets de donn\u00e9es num\u00e9riques parviennent au serveur central dans un ordre temporel d\u00e9synchronis\u00e9. La matrice de stockage brute pr\u00e9sente alors une colonne d&rsquo;horodatage en microsecondes (situ\u00e9e \u00e0 l&rsquo;indice 0) totalement d\u00e9sordonn\u00e9e, emp\u00eachant toute analyse causale imm\u00e9diate.<\/p>\n<p>Pour restaurer la continuit\u00e9 causale des s\u00e9ries temporelles, il est indispensable de r\u00e9aligner l&rsquo;int\u00e9gralit\u00e9 des tranches horizontales de la matrice de mesures en fonction de l&rsquo;ordre strictement croissant de l&rsquo;horodatage. La mise en \u0153uvre de cette synchronisation chronologique s&rsquo;effectue au moyen de l&rsquo;instruction vectoris\u00e9e : <strong>matrice_signal_synchro = matrice_brute[matrice_brute[:, 0].argsort()]<\/strong>.<\/p>\n<p>Apr\u00e8s application de cette transformation, chaque ligne se retrouve positionn\u00e9e en stricte conformit\u00e9 avec le flux physique des \u00e9v\u00e9nements. L&rsquo;analyste peut d\u00e9sormais appliquer des op\u00e9rateurs de d\u00e9rivation temporelle le long de l&rsquo;axe des lignes (par exemple via <strong>numpy.diff(matrice_signal_synchro, axis=0)<\/strong>) pour \u00e9valuer les d\u00e9riv\u00e9es premi\u00e8res des signaux capt\u00e9s en toute rigueur scientifique, l&rsquo;int\u00e9grit\u00e9 de la base de temps sous-jacente \u00e9tant parfaitement r\u00e9tablie.<\/p>\n<h3>12.3 Cas pratique 3 : R\u00e9organisation d&rsquo;une matrice de corr\u00e9lation par hi\u00e9rarchie de poids<\/h3>\n<p>En analyse statistique multivari\u00e9e et en bio-informatique, l&rsquo;examen de matrices de corr\u00e9lation carr\u00e9es (dimensions P par P) permet de caract\u00e9riser les couplages fonctionnels entre variables. Cependant, lorsque les variables sont dispos\u00e9es dans un ordre arbitraire, la matrice de corr\u00e9lation appara\u00eet visuellement et num\u00e9riquement sous la forme d&rsquo;un bruit diffus, dissimulant l&rsquo;existence \u00e9ventuelle de blocs fonctionnels ou de modules coop\u00e9ratifs.<\/p>\n<p>Une technique \u00e9prouv\u00e9e pour r\u00e9v\u00e9ler la structure latente d&rsquo;un r\u00e9seau consiste \u00e0 ordonner simultan\u00e9ment les lignes et les colonnes de la matrice de corr\u00e9lation selon le poids moyen de connectivit\u00e9 de chaque variable, mesur\u00e9 par exemple par la somme des corr\u00e9lations absolues de chaque entit\u00e9 avec l&rsquo;ensemble du r\u00e9seau. La proc\u00e9dure programmatique s&rsquo;\u00e9nonce en trois phases :<\/p>\n<ul>\n<li>Calcul du vecteur de connectivit\u00e9 globale pour chaque variable : <strong>force_connexion = np.sum(np.abs(matrice_corr), axis=1)<\/strong>.<\/li>\n<li>Extraction du tableau des indices de tri descendant afin de positionner les hubs les plus fortement connect\u00e9s en t\u00eate de structure : <strong>indices_hubs = force_connexion.argsort()[::-1]<\/strong>.<\/li>\n<li>Application de la permutation sym\u00e9trique sur les deux dimensions spatiales de la matrice carr\u00e9e : <strong>matrice_corr_reordonnee = matrice_corr[indices_hubs, :][:, indices_hubs]<\/strong>.<\/li>\n<\/ul>\n<p>L&rsquo;op\u00e9ration double d&rsquo;indexation avanc\u00e9e r\u00e9ordonne simultan\u00e9ment l&rsquo;axe vertical et l&rsquo;axe horizontal selon le m\u00eame vecteur de permutation d&rsquo;indices. La matrice de corr\u00e9lation r\u00e9sultante conserve sa sym\u00e9trie math\u00e9matique fondamentale tout en concentrant visuellement et alg\u00e9briquement les coefficients de couplage les plus intenses dans le quadrant sup\u00e9rieur gauche. Cette r\u00e9organisation m\u00e9thodique facilite l&rsquo;application ult\u00e9rieure d&rsquo;algorithmes de d\u00e9tection de communaut\u00e9s ou de partitionnement spectral.<\/p>\n<h2>R\u00e9f\u00e9rences<\/h2>\n<p>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., &hellip; 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><\/p>\n<p>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><\/p>\n<p>Knuth, D. E. (1998). <em>The Art of Computer Programming, Volume 3: Sorting and Searching<\/em> (2nd ed.). Addison-Wesley Professional.<\/p>\n<p>McKinney, W. (2022). <em>Python for Data Analysis: Data Wrangling with pandas, NumPy, and Jupyter<\/em> (3rd ed.). O&rsquo;Reilly Media.<\/p>\n<p>NumPy Developers. (2024). <em>NumPy Reference Documentation (Release 1.26)<\/em>. <a rel=\"noopener noreferrer\" href=\"https:\/\/numpy.org\/doc\/stable\/reference\/\">https:\/\/numpy.org\/doc\/stable\/reference\/<\/a><\/p>\n<p>Oliphant, T. E. (2006). <em>A guide to NumPy<\/em> (Vol. 1). Trelgol Publishing.<\/p>\n<p>van der Walt, S. J., Colbert, S. C., &amp; Varoquaux, G. (2011). The NumPy Array: A Structure for Efficient Numerical Computation. <em>Computing in Science &amp; Engineering<\/em>, 13(2), 22\u201330. <a rel=\"noopener noreferrer\" href=\"https:\/\/doi.org\/10.1109\/MCSE.2011.37\">https:\/\/doi.org\/10.1109\/MCSE.2011.37<\/a><\/p>\n<p>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., &hellip; 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><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Guide complet et rigoureux pour apprendre \u00e0 trier un tableau NumPy par colonne : m\u00e9thodes argsort, ordre croissant et d\u00e9croissant, et cas d&rsquo;usage pratiques.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","categories":[4882,2465],"tags":[20220,4153,2960,4874,20221],"class_list":["post-13405","psych_stat","type-psych_stat","status-publish","hentry","category-calcul-scientifique","category-programmation-python","tag-argsort","tag-matrices","tag-numpy","tag-python-scientifique","tag-tri-par-colonne"],"_links":{"self":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/13405","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=13405"}],"version-history":[{"count":1,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/13405\/revisions"}],"predecessor-version":[{"id":16876,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=\/wp\/v2\/psych_stat\/13405\/revisions\/16876"}],"wp:attachment":[{"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=13405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=13405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/french.arabpsychology.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=13405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}