{"id":2470,"date":"2026-02-02T07:28:31","date_gmt":"2026-02-02T07:28:31","guid":{"rendered":"https:\/\/demo.materiamedica.net\/demo6\/?p=2470"},"modified":"2026-02-02T07:28:31","modified_gmt":"2026-02-02T07:28:31","slug":"chapter-6-numpy-array-indexing","status":"publish","type":"post","link":"https:\/\/demo.materiamedica.net\/demo6\/chapter-6-numpy-array-indexing\/","title":{"rendered":"Chapter 6: NumPy Array Indexing"},"content":{"rendered":"<p dir=\"auto\"><strong>NumPy Array Indexing<\/strong> written as if a patient teacher is sitting next to you, showing examples on the screen, explaining the logic, warning about common traps, and showing realistic patterns you will actually use.<\/p>\n<p dir=\"auto\">Let\u2019s go slowly and thoroughly \u2014 indexing is <strong>one of the most important skills<\/strong> in NumPy.<\/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. Basic Indexing \u2013 Like lists, but more powerful<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>arr = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])\r\n\r\nprint(arr[0])      # 10\r\nprint(arr[3])      # 40\r\nprint(arr[-1])     # 100  \u2190 last element\r\nprint(arr[-3])     # 80   \u2190 third from the end<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>2D array example<\/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>matrix = np.array([\r\n    [ 1,  2,  3,  4],\r\n    [ 5,  6,  7,  8],\r\n    [ 9, 10, 11, 12],\r\n    [13, 14, 15, 16]\r\n])\r\n\r\nprint(matrix[0, 0])    # 1\r\nprint(matrix[2, 3])    # 12\r\nprint(matrix[3, -1])   # 16\r\nprint(matrix[-1, 0])   # 13   \u2190 last row, first column<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Important rule to remember early:<\/strong><\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>text<\/div>\n<div>\n<pre tabindex=\"0\"><code>In 2D:  matrix[row, column]\r\nIn 3D:  array[depth, row, column]   or   [z, y, x]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">2. Slicing \u2013 The most frequently used operation<\/h3>\n<p dir=\"auto\">Slicing syntax: start:stop:step<\/p>\n<p dir=\"auto\">All three parts are <strong>optional<\/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>a = np.arange(20)   # [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]\r\n\r\nprint(a[3:8])       # [3 4 5 6 7]\r\nprint(a[10:])       # [10 11 12 13 14 15 16 17 18 19]   \u2190 from index 10 to end\r\nprint(a[:5])        # [0 1 2 3 4]                        \u2190 from beginning to 4\r\nprint(a[::2])       # [ 0  2  4  6  8 10 12 14 16 18]   \u2190 every second element\r\nprint(a[1::3])      # [ 1  4  7 10 13 16 19]\r\nprint(a[::-1])      # [19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0] \u2190 reverse<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>2D slicing examples<\/strong> (very common)<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>print(matrix)\r\n\r\n# [[ 1  2  3  4]\r\n#  [ 5  6  7  8]\r\n#  [ 9 10 11 12]\r\n#  [13 14 15 16]]\r\n\r\nprint(matrix[1:3, 2:])      # rows 1\u20132, columns 2 to end\r\n# [[ 7  8]\r\n#  [11 12]]\r\n\r\nprint(matrix[:, 1])         # all rows, second column\r\n# [ 2  6 10 14]\r\n\r\nprint(matrix[2, :])         # third row, all columns\r\n# [ 9 10 11 12]\r\n\r\nprint(matrix[::2, ::2])     # every other row and column\r\n# [[ 1  3]\r\n#  [ 9 11]]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">3. Boolean Indexing \u2013 Extremely powerful (you will use this daily)<\/h3>\n<p dir=\"auto\">Instead of numbers, you give a <strong>boolean mask<\/strong> of the same shape.<\/p>\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\npassed = scores &gt;= 70\r\nprint(passed)\r\n# [ True  True False  True  True  True  True False False  True]\r\n\r\nprint(scores[passed])\r\n# [78 92 88 71 95 82 91]\r\n\r\n# Even shorter &amp; very common:\r\nhigh_scores = scores[scores &gt;= 90]\r\nprint(high_scores)          # [92 95 91]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Realistic example \u2013 cleaning data<\/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>ages = np.array([23, 45, 12, 67, 34, 8, 29, 91, 55, 41])\r\n\r\n# Remove impossible ages\r\nvalid_ages = ages[(ages &gt;= 0) &amp; (ages &lt;= 120)]\r\nprint(valid_ages)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Replacing values conditionally<\/strong> (very frequent pattern)<\/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.randn(10)\r\nprint(data)\r\n\r\ndata[data &lt; 0] = 0          # set all negative values to zero\r\nprint(data)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">4. Fancy Indexing \u2013 Using arrays\/lists of indices<\/h3>\n<p dir=\"auto\">You can pass an array or list of indices \u2192 picks elements in that order.<\/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([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])\r\n\r\nidx = [1, 4, 7, 9]\r\nprint(values[idx])\r\n# [20 50 80 100]\r\n\r\n# Can also use numpy array of indices\r\nidx2 = np.array([0, 3, 6])\r\nprint(values[idx2])\r\n# [10 40 70]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>2D fancy indexing \u2013 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>print(matrix)\r\n\r\nrows = [0, 2, 3]\r\ncols = [1, 3, 2]\r\n\r\nprint(matrix[rows, cols])\r\n# [ 2 12 15 ]   \u2190 matrix[0,1], matrix[2,3], matrix[3,2]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">5. Combining styles \u2013 Very powerful &amp; common<\/h3>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code># Boolean + slicing\r\nlarge = matrix[matrix &gt; 8]          # gets all values &gt; 8 as 1D array\r\n\r\n# Fancy + slicing\r\nimportant_cols = [1, 3]\r\nsub = matrix[:, important_cols]     # all rows, only columns 1 and 3\r\n\r\n# Boolean mask on rows\r\ngood_rows = np.any(matrix &gt; 14, axis=1)   # rows that have at least one value &gt; 14\r\nprint(matrix[good_rows])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">6. Views vs Copies \u2013 The trap almost everyone falls into<\/h3>\n<p dir=\"auto\"><strong>Most indexing creates a view<\/strong> (not a copy) \u2192 changes affect original array!<\/p>\n<div dir=\"auto\">\n<div data-testid=\"code-block\">\n<div>\n<div>Python<\/div>\n<div>\n<pre tabindex=\"0\"><code>a = np.arange(12).reshape(3, 4)\r\n\r\nview = a[1:3, 1:3]     # \u2190 this is a VIEW\r\nview[0, 0] = 999\r\n\r\nprint(a)               # original array changed!<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>How to force a copy:<\/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>copy1 = a[1:3, 1:3].copy()\r\ncopy2 = np.copy(a[1:3, 1:3])<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Quick rule of thumb (very useful):<\/strong><\/p>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"lg\">Operation<\/th>\n<th data-col-size=\"xs\">Usually returns<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"lg\">Basic slicing a[2:5]<\/td>\n<td data-col-size=\"xs\">View<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Boolean indexing a[a&gt;0]<\/td>\n<td data-col-size=\"xs\"><strong>Copy<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">Fancy indexing a[[1,3,5]]<\/td>\n<td data-col-size=\"xs\"><strong>Copy<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">a[&#8230;] with lists\/arrays<\/td>\n<td data-col-size=\"xs\"><strong>Copy<\/strong><\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"lg\">.copy()<\/td>\n<td data-col-size=\"xs\">Copy<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">7. Realistic patterns you will write again and again<\/h3>\n<p dir=\"auto\"><strong>Pattern 1: Normalize only selected columns<\/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>X = np.random.randn(1000, 20)\r\nimportant = [0, 3, 7, 12, 19]\r\nX[:, important] = (X[:, important] - X[:, important].mean(axis=0)) \/ X[:, important].std(axis=0)<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 2: Remove rows with outliers<\/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.normal(100, 15, (500, 10))\r\noutliers = np.any(np.abs(data - 100) &gt; 45, axis=1)\r\nclean = data[~outliers]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\"><strong>Pattern 3: Get top-k scores<\/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>scores = np.random.randint(40, 101, 200)\r\ntop_indices = np.argsort(scores)[-10:]     # indices of top 10\r\ntop_scores = scores[top_indices]<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h3 dir=\"auto\">Summary Table \u2013 Quick Reference<\/h3>\n<div>\n<div dir=\"auto\">\n<table dir=\"auto\">\n<thead>\n<tr>\n<th data-col-size=\"sm\">You want&#8230;<\/th>\n<th data-col-size=\"lg\">Syntax example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td data-col-size=\"sm\">Single element<\/td>\n<td data-col-size=\"lg\">arr[3], mat[2,1]<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Row \/ column<\/td>\n<td data-col-size=\"lg\">mat[1], mat[:,3]<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Slice<\/td>\n<td data-col-size=\"lg\">arr[2:7], mat[1:4, 2:]<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Every nth element<\/td>\n<td data-col-size=\"lg\">arr[::3], arr[::-1] (reverse)<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Boolean filter<\/td>\n<td data-col-size=\"lg\">arr[arr &gt; 50], arr[arr % 2 == 0]<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Replace conditionally<\/td>\n<td data-col-size=\"lg\">arr[arr &lt; 0] = 0<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Fancy indexing (pick specific indices)<\/td>\n<td data-col-size=\"lg\">arr[[1,4,7]], mat[[0,2], [1,3]]<\/td>\n<\/tr>\n<tr>\n<td data-col-size=\"sm\">Get copy (not view)<\/td>\n<td data-col-size=\"lg\">arr[slice].copy()<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div><\/div>\n<\/div>\n<\/div>\n<p dir=\"auto\">Where would you like to go next?<\/p>\n<ul dir=\"auto\">\n<li>Advanced indexing tricks (np.ix_, masking in multiple dimensions)<\/li>\n<li>Differences between view vs copy in depth (with memory examples)<\/li>\n<li>Indexing in 3D arrays \/ images<\/li>\n<li>Boolean indexing + assignment patterns<\/li>\n<li>Common bugs people make with indexing<\/li>\n<li>Mini-project using indexing (data filtering &amp; cleaning)<\/li>\n<\/ul>\n<p dir=\"auto\">Just tell me what feels most useful right now! \ud83d\ude0a<\/p>\n","protected":false},"excerpt":{"rendered":"<p>NumPy Array Indexing written as if a patient teacher is sitting next to you, showing examples on the screen, explaining the logic, warning about common traps, and showing realistic patterns you will actually use.&#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-2470","post","type-post","status-publish","format-standard","hentry","category-numpy"],"_links":{"self":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2470","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=2470"}],"version-history":[{"count":1,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2470\/revisions"}],"predecessor-version":[{"id":2471,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/posts\/2470\/revisions\/2471"}],"wp:attachment":[{"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/media?parent=2470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/categories?post=2470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demo.materiamedica.net\/demo6\/wp-json\/wp\/v2\/tags?post=2470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}