If you use numpy, this is easy:
slice = arr[:2,:2]
or if you want the 0's,
slice = arr[0:2,0:2]
You'll get the same result.
*note that slice is actually the name of a builtin-type. Generally, I would advise giving your object a different "name".
Another way, if you're working with lists of lists*:
slice = [arr[i][0:2] for i in range(0,2)]
(Note that the 0's here are unnecessary: [arr[i][:2] for i in range(2)] would also work.).
What I did here is that I take each desired row 1 at a time (arr[i]). I then slice the columns I want out of that row and add it to the list that I'm building.
If you naively try: arr[0:2] You get the first 2 rows which if you then slice again arr[0:2][0:2], you're just slicing the first two rows over again.
*This actually works for numpy arrays too, but it will be slow compared to the "native" solution I posted above.
Answer from mgilson on Stack OverflowIf you use numpy, this is easy:
slice = arr[:2,:2]
or if you want the 0's,
slice = arr[0:2,0:2]
You'll get the same result.
*note that slice is actually the name of a builtin-type. Generally, I would advise giving your object a different "name".
Another way, if you're working with lists of lists*:
slice = [arr[i][0:2] for i in range(0,2)]
(Note that the 0's here are unnecessary: [arr[i][:2] for i in range(2)] would also work.).
What I did here is that I take each desired row 1 at a time (arr[i]). I then slice the columns I want out of that row and add it to the list that I'm building.
If you naively try: arr[0:2] You get the first 2 rows which if you then slice again arr[0:2][0:2], you're just slicing the first two rows over again.
*This actually works for numpy arrays too, but it will be slow compared to the "native" solution I posted above.
To slice a multi-dimensional array, the dimension (i.e. axis) must be specified. As OP noted, arr[i:j][i:j] is exactly the same as arr[i:j] because arr[i:j] sliced along the first axis (rows) and has the same number of dimensions as arr (you can confirm by arr[i:j].ndim == arr.ndim); so the second slice is still slicing along the first dimension (which was already done by the first slice). To slice along the second dimension, it must be explicitly specified, e.g.:
arr[:2][:, :2] # its output is the same as `arr[:2, :2]`
A bare : means slice everything in that axis, so there's an implicit : for the second axis in the above code (i.e. arr[:2, :][:, :2]). What the above code is doing is slicing the first two rows (or first two arrays along the first axis) and then slice the first two columns (or the first two arrays along the second axis) from the resulting array.
An ... can be used instead of multiple colons (:), so for a general n-dimensional array, the following produce the same output:
w = arr[i:j, m:n]
x = arr[i:j, m:n, ...]
y = arr[i:j][:, m:n]
z = arr[i:j, ...][:, m:n, ...]
That said, arr[:2, :2] is the canonical way because in the case of arr[i:j][:, i:j], arr[i:j] creates a temporary array which is indexed by [:, i:j], so it's comparatively inefficient.
However, there are cases where chained indexing makes sense (or readable), e.g., if you want to index a multi-dimensional array using a list of indices. For example, if you want to slice the top-left quarter of a 4x4 array using a list of indices, then chained indexing gives the correct result whereas a single indexing gives a different result (it's because of numpy advanced indexing) where the values correspond to the index pair for each position in the index lists.
arr = np.arange(1,17).reshape(4,4)
rows = cols = [0,1]
arr[rows][:, cols] # <--- correct output
arr[rows, cols] # <--- wrong output
arr[[[e] for e in rows], cols] # <--- correct output
arr[np.ix_(rows, cols)] # <--- correct output
So,here I come again 🤣
I don't get slicing in 2D..
In my lesson,I was taught that using this
d[1:2,1]
means the 2nd element from the last two rows,and 2nd element from 1st column should be sliced..but when I use it I get only one element.Did I do something wrong?Can some of you awesome people hook me up with an explanation?
Here's some code for your palates:
a=[[1,2,3],[4,5,6],[7,8,9]] import numpy as np d=np.array(a) d[1:2,1]
Hi, I'm trying to create a simple game of life and I have problems putting zeros on the edge of my grid. When i try the following code i get an error and I don't understand why.
the variable grid represent a 2D array.
the code:
grid[0,:] = np.zeros_like(grid[0,:])#top_row
grid[-1,:] = np.zeros_like(grid[-1,:])#bottom_row
grid[:,0] = np.zeros_like(grid[:,0])#left
grid[:,-1] = np.zeros_like(grid[:,-1])#right
the error:
TypeError: list indices must be integers or slices, not tuple
To answer this question, we have to look at how indexing a multidimensional array works in Numpy. Let's first say you have the array x from your question. The buffer assigned to x will contain 16 ascending integers from 0 to 15. If you access one element, say x[i,j], NumPy has to figure out the memory location of this element relative to the beginning of the buffer. This is done by calculating in effect i*x.shape[1]+j (and multiplying with the size of an int to get an actual memory offset).
If you extract a subarray by basic slicing like y = x[0:2,0:2], the resulting object will share the underlying buffer with x. But what happens if you acces y[i,j]? NumPy can't use i*y.shape[1]+j to calculate the offset into the array, because the data belonging to y is not consecutive in memory.
NumPy solves this problem by introducing strides. When calculating the memory offset for accessing x[i,j], what is actually calculated is i*x.strides[0]+j*x.strides[1] (and this already includes the factor for the size of an int):
x.strides
(16, 4)
When y is extracted like above, NumPy does not create a new buffer, but it does create a new array object referencing the same buffer (otherwise y would just be equal to x.) The new array object will have a different shape then x and maybe a different starting offset into the buffer, but will share the strides with x (in this case at least):
y.shape
(2,2)
y.strides
(16, 4)
This way, computing the memory offset for y[i,j] will yield the correct result.
But what should NumPy do for something like z=x[[1,3]]? The strides mechanism won't allow correct indexing if the original buffer is used for z. NumPy theoretically could add some more sophisticated mechanism than the strides, but this would make element access relatively expensive, somehow defying the whole idea of an array. In addition, a view wouldn't be a really lightweight object anymore.
This is covered in depth in the NumPy documentation on indexing.
Oh, and nearly forgot about your actual question: Here is how to make the indexing with multiple lists work as expected:
x[[[1],[3]],[1,3]]
This is because the index arrays are broadcasted to a common shape. Of course, for this particular example, you can also make do with basic slicing:
x[1::2, 1::2]
As Sven mentioned, x[[[0],[2]],[1,3]] will give back the 0 and 2 rows that match with the 1 and 3 columns while x[[0,2],[1,3]] will return the values x[0,1] and x[2,3] in an array.
There is a helpful function for doing the first example I gave, numpy.ix_. You can do the same thing as my first example with x[numpy.ix_([0,2],[1,3])]. This can save you from having to enter in all of those extra brackets.