{"id":2491,"date":"2026-02-02T08:23:18","date_gmt":"2026-02-02T08:23:18","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2491"},"modified":"2026-02-02T08:23:18","modified_gmt":"2026-02-02T08:23:18","slug":"chapter-16-numpy-sorting-arrays","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-16-numpy-sorting-arrays\/","title":{"rendered":"Chapter 16: NumPy Sorting Arrays"},"content":{"rendered":"<p dir=\"auto\"><strong>NumPy Sorting Arrays<\/strong> \u2014 written as if I\u2019m your patient teacher sitting next to you, going through every important detail step by step, showing realistic examples, explaining trade-offs, warning about common mistakes, and showing patterns you will actually use in real data work.<\/p>\n<p dir=\"auto\">Let\u2019s open a notebook together and learn this properly.<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>import numpy as np<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">1. The two main ways to sort in NumPy<\/h3>\n<p dir=\"auto\">NumPy gives you <strong>two very different philosophies<\/strong> for sorting:<\/p>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"md\">Method<\/th>\n<th data-col-size=\"lg\">What it returns<\/th>\n<th data-col-size=\"sm\">Modifies original?<\/th>\n<th data-col-size=\"xl\">Most common use case<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"md\">np.sort()<\/td>\n<td data-col-size=\"lg\"><strong>new sorted array<\/strong> (copy)<\/td>\n<td data-col-size=\"sm\">No<\/td>\n<td data-col-size=\"xl\">When you want to keep original<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">array.sort()<\/td>\n<td data-col-size=\"lg\"><strong>None<\/strong> \u2014 sorts <strong>in place<\/strong><\/td>\n<td data-col-size=\"sm\"><strong>Yes<\/strong><\/td>\n<td data-col-size=\"xl\">When memory is tight or you don\u2019t need original<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"md\">np.argsort()<\/td>\n<td data-col-size=\"lg\"><strong>indices<\/strong> that would sort the array<\/td>\n<td data-col-size=\"sm\">No<\/td>\n<td data-col-size=\"xl\">Ranking, top-k, indirect sorting<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">2. np.sort() \u2014 the safe &amp; most commonly used method<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>scores = np.array([78, 92, 65, 88, 71, 95, 82, 59, 67, 91])\r\n\r\nsorted_scores = np.sort(scores)\r\nprint(sorted_scores)\r\n# [59 65 67 71 78 82 88 91 92 95]\r\n\r\nprint(scores)\r\n# [78 92 65 88 71 95 82 59 67 91]   \u2190 original unchanged!<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>2D array \u2014 important behavior<\/strong><\/p>\n<p dir=\"auto\">By default, np.sort() sorts <strong>along the last axis<\/strong> (columns in 2D).<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>mat = np.array([\r\n    [45, 12, 78, 33],\r\n    [19, 88,  5, 62],\r\n    [91, 27, 54,  3],\r\n    [ 8, 66, 41, 75]\r\n])\r\n\r\nprint(np.sort(mat))\r\n# Each **row** is sorted independently\r\n# [[12 33 45 78]\r\n#  [ 5 19 62 88]\r\n#  [ 3 27 54 91]\r\n#  [ 8 41 66 75]]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Control the axis<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Sort each column (vertical sort)\r\nprint(np.sort(mat, axis=0))\r\n# [[ 8 12  5  3]\r\n#  [19 27 41 33]\r\n#  [45 66 54 62]\r\n#  [91 88 78 75]]\r\n\r\n# Sort the whole array as if flattened\r\nprint(np.sort(mat, axis=None))\r\n# [ 3  5  8 12 19 27 33 41 45 54 62 66 75 78 88 91]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">3. In-place sorting: array.sort()<\/h3>\n<p dir=\"auto\"><strong>Modifies the array itself \u2014 returns None<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>data = np.random.randint(0, 100, 12)\r\nprint(\"Before:\", data)\r\n\r\ndata.sort()               # \u2190 in-place\r\nprint(\"After:\", data)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Very important warning<\/strong> \u2014 people often forget it returns None:<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>wrong = data.sort()       # \u2190 wrong!\r\nprint(wrong)              # None\r\n\r\ncorrect = data.copy()\r\ncorrect.sort()            # now correct is sorted<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>When to use array.sort()<\/strong><\/p>\n<ul dir=\"auto\">\n<li>You are sure you <strong>don\u2019t need<\/strong> the original anymore<\/li>\n<li>You want to save memory (no copy created)<\/li>\n<li>You are sorting very large arrays<\/li>\n<\/ul>\n<h3 dir=\"auto\">4. The most powerful &amp; most used tool: np.argsort()<\/h3>\n<p dir=\"auto\">Returns <strong>indices<\/strong> that would sort the array \u2014 not the values themselves.<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>values = np.array([45, 92, 18, 76, 33, 89, 61, 12, 55])\r\n\r\nidx = np.argsort(values)\r\nprint(idx)\r\n# [7 2 4 0 8 6 3 5 1]\r\n\r\nprint(values[idx])          # sorted order\r\n# [12 18 33 45 55 61 76 89 92]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Top 5 highest values (very common pattern)<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>top5_indices = np.argsort(values)[-5:]      # last 5 indices = highest\r\nprint(\"Top 5 values:\", values[top5_indices])\r\nprint(\"Their positions:\", top5_indices)\r\n\r\n# Highest first:\r\ntop5_desc = np.argsort(values)[-5:][::-1]\r\nprint(values[top5_desc])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>2D argsort \u2014 per row \/ per column<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>mat = np.random.randint(0, 100, (5, 6))\r\n\r\n# Index of best score per row (student with highest mark per subject)\r\nbest_per_subject = np.argmax(mat, axis=0)   # or np.argsort(mat, axis=0)[-1]\r\n\r\n# Sort each row and get the order\r\nrow_order = np.argsort(mat, axis=1)\r\nprint(row_order)   # shape (5,6) \u2014 each row contains 0..5 in sorted order<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Sorting with kind= parameter \u2014 when performance or stability matters<\/h3>\n<p dir=\"auto\">NumPy offers different sorting algorithms:<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>text<\/div>\n<div>\n<pre tabindex=\"0\"><code>kind         | Speed       | Stable? | Use case\r\n-------------|-------------|---------|----------------------------------\r\n'quicksort'  | fastest     | no      | default \u2014 good for most cases\r\n'mergesort'  | medium      | **yes** | when you need stable sort\r\n'heapsort'   | slower      | no      | rarely used\r\n'timsort'    | good        | **yes** | stable &amp; fast (used in pandas)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Stable sort example<\/strong> \u2014 very important when you have ties<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>names = np.array(['Anna', 'Bob', 'Clara', 'David', 'Emma'])\r\nscores = np.array([85, 92, 85, 78, 92])\r\n\r\n# We want to sort by score, but keep original order when scores are equal\r\n\r\nidx = np.argsort(scores, kind='mergesort')   # stable\r\nprint(names[idx])\r\n# ['David' 'Anna' 'Clara' 'Bob' 'Emma']   \u2190 Anna before Clara (original order)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\">With quicksort (not stable) \u2192 order of equal elements is random.<\/p>\n<h3 dir=\"auto\">6. Realistic patterns you will write 100\u00d7 times<\/h3>\n<p dir=\"auto\"><strong>Pattern 1: Get top-k scores with their original indices<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>sales = np.random.randint(1000, 100000, 500)\r\ntop10_idx = np.argsort(sales)[-10:][::-1]\r\ntop10_sales = sales[top10_idx]\r\ntop10_positions = top10_idx<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 2: Rank items<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>times = np.array([12.4, 11.9, 13.1, 11.8, 12.7])\r\nranks = np.argsort(np.argsort(times)) + 1   # 1-based rank\r\nprint(ranks)\r\n# [3 2 5 1 4]   \u2190 fastest gets rank 1<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 3: Sort rows of a matrix by one column<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>data = np.random.randint(0, 100, (100, 5))\r\n# sort by the 3rd column\r\nsorted_data = data[np.argsort(data[:, 2])]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 4: Sort strings \/ categories<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>products = np.array(['mouse', 'keyboard', 'monitor', 'usb', 'laptop'])\r\nsorted_idx = np.argsort(products)\r\nprint(products[sorted_idx])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Summary \u2013 Quick Decision Table<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">You want to&#8230;<\/th>\n<th data-col-size=\"md\">Best choice<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Sort values, keep original unchanged<\/td>\n<td data-col-size=\"md\">np.sort(arr)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Sort in place (save memory)<\/td>\n<td data-col-size=\"md\">arr.sort()<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Get sorted values <strong>and<\/strong> their original positions<\/td>\n<td data-col-size=\"md\">np.argsort()<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Find position of max \/ min<\/td>\n<td data-col-size=\"md\">np.argmax() \/ np.argmin()<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Need stable sorting (important for ties)<\/td>\n<td data-col-size=\"md\">kind=&#8217;mergesort&#8217; or &#8216;stable&#8217;<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Sort each row \/ each column independently<\/td>\n<td data-col-size=\"md\">np.sort(&#8230;, axis=0) or axis=1<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Get top 10 \/ bottom 10 with indices<\/td>\n<td data-col-size=\"md\">np.argsort(&#8230;)[-10:] or [::-1]<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Common Mistakes to Avoid<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Mistake 1: Forgetting that sort() returns None\r\nwrong = arr.sort()         # wrong \u2014 wrong is None\r\n\r\n# Mistake 2: Thinking argsort sorts strings case-insensitively\r\n# \u2192 it does NOT \u2014 uppercase comes before lowercase\r\n\r\n# Mistake 3: Using sort on very large arrays without thinking about memory\r\n# \u2192 prefer argsort + indexing when you only need order<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\">Would you like to go deeper into any of these topics next?<\/p>\n<ul dir=\"auto\">\n<li>Stable vs unstable sorting with real examples<\/li>\n<li>Sorting structured arrays \/ record arrays<\/li>\n<li>Sorting along multiple keys (like SQL ORDER BY col1, col2)<\/li>\n<li>Performance: sort vs argsort vs pandas sort<\/li>\n<li>Mini-exercise: rank students, find top products, clean sorted time series<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me what you want to focus on now! \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>NumPy Sorting Arrays \u2014 written as if I\u2019m your patient teacher sitting next to you, going through every important detail step by step, showing realistic examples, explaining trade-offs, warning about common mistakes, and showing&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[75],"tags":[],"class_list":["post-2491","post","type-post","status-publish","format-standard","hentry","category-numpy"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2491","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/comments?post=2491"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2491\/revisions"}],"predecessor-version":[{"id":2492,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2491\/revisions\/2492"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}