Confusion with Fancy indexing (for non-fancy people)
<p>Let's assume a multi-dimensional array</p>

<pre><code>import numpy as np
foo = np.random.rand(102,43,35,51)
</code></pre>

<p>I know that those last dimensions represent a 2D space (35,51) of which I would like to index <strong>a range of rows</strong> of a <strong>column</strong>
Let's say I want to have rows 8 to 30 of column 0
From my understanding of indexing I should call</p>

<pre><code>foo[0][0][8::30][0]
</code></pre>

<p>Knowing my data though (unlike the random data used here), this is not what I expected</p>

<p>I could try this that does work but looks ridiculous</p>

<pre><code>foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
</code></pre>

<p>Now from what I can find in <a href="https://docs.scipy.org/doc/numpy-dev/user/quickstart.html#head-864862d3f2bb4c32f04260fac61eb4ef34788c4c" rel="nofollow">this documentation </a> I can also use 
something like:</p>

<pre><code>foo[0][0][[8,30],0]
</code></pre>

<p>which only gives me the values of rows 8 and 30
while this:</p>

<pre><code>foo[0][0][[8::30],0]
</code></pre>

<p>gives an error</p>

<pre><code>File "&lt;ipython-input-568-cc49fe1424d1&gt;", line 1
foo[0][0][[8::30],0]
                ^
SyntaxError: invalid syntax
</code></pre>

<p>I don't understand why the :: argument cannot be passed here. What is then a way to indicate a range in your indexing syntax?</p>

<p>So I guess my overall question is what would be the proper pythonic equivalent of this syntax:</p>

<pre><code>foo[0][0][[8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],0]
</code></pre>

<p>Instead of </p>

<pre><code>foo[0][0][8::30][0]
</code></pre>

<p>try</p>

<pre><code>foo[0, 0, 8:30, 0]
</code></pre>

<p>The <code>foo[0][0]</code> part is the same as <code>foo[0, 0, :, :]</code>, selecting a 2d array (35 x 51).  But <code>foo[0][0][8::30]</code> selects a subset of those rows</p>

<p>Consider what happens when is use <code>0::30</code> on 2d array:</p>

<pre><code>In [490]: np.zeros((35,51))[0::30].shape
Out[490]: (2, 51)

In [491]: np.arange(35)[0::30]
Out[491]: array([ 0, 30])
</code></pre>

<p>The <code>30</code> is the <code>step</code>, not the <code>stop</code> value of the slice.</p>

<p>the last <code>[0]</code> then picks the first of those rows.  The end result is the same as <code>foo[0,0,0,:]</code>.</p>

<p>It is better, in most cases, to index multiple dimensions with the comma syntax.  And if you want the first 30 rows use <code>0:30</code>, not <code>0::30</code> (that's basic slicing notation, applicable to lists as well as arrays).</p>

<p>As for: </p>

<pre><code>foo[0][0][[8::30],0]
</code></pre>

<p>simplify it to <code>x[[8::30], 0]</code>.  The Python interpreter accepts <code>[1:2:3, 0]</code>, translating it to <code>tuple(slice(1,2,3), 0)</code> and passing it to a <code>__getitem__</code> method.  But the colon syntax is accepted in a very specific context.  The interpreter is treating that inner set of brackets as a list, and colons are not accepted there.</p>

<pre><code>foo[0,0,[1,2,3],0]
</code></pre>

<p>is ok, because the inner brackets are a list, and the numpy <code>getitem</code> can handle those.</p>

<p><code>numpy</code> has a tool for converting a slice notation into a list of numbers.  Play with that if it is still confusing:</p>

<pre><code>In [495]: np.r_[8:30]
Out[495]: 
array([ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
       25, 26, 27, 28, 29])
In [496]: np.r_[8::30]
Out[496]: array([0])
In [497]: np.r_[8:30:2]
Out[497]: array([ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28])
</code></pre>

python arrays numpy indexing scipy