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
Slicing 2D Numpy arrays
Python array slicing -- How can 2D array slicing be implemented? - Stack Overflow
python - Slice 2d array into smaller 2d arrays - Stack Overflow
python - Slice in 2 dimensional array - Stack Overflow
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]
If you want to know the rules of array slicing, the picture below might help:

For read access you need to override the __getitem__ method:
class ArrayLike(object):
def __init__(self):
pass
def __getitem__(self, arg):
(rows,cols) = arg # unpack, assumes that we always pass in 2-arguments
# TODO: parse/interpret the rows/cols parameters,
# for single indices, they will be integers, for slices, they'll be slice objects
# here's a dummy implementation as a placeholder
return numpy.eye(10)[rows, cols]
One of the tricky bits is that __getitem__ always only uses one argument (aside from self),
when you put multiple-comma-separated items inside the square brackets, you're actually providing a single tuple as the argument to the __getitem__ call; thus the need to
unpack this tuple (and optionally verify that the length of the tuple is suitable) inside
the function.
Now given a = ArrayLike(), you end up with
a[2,3]meansrows=2,cols=3a[:3,2]meansrows=slice(None, 3, None),cols=3
and so on; you'll have to look at the documentation on slice objects to decide how you want to use the slice information to pull out the data that you need from your class.
To make it more like a numpy array, you'd also want to override __setitem__ as well, to
allow for assigning to elements/slices.
There was another question a couple of months ago which clued me in to the idea of using reshape and swapaxes. The h//nrows makes sense since this keeps the first block's rows together. It also makes sense that you'll need nrows and ncols to be part of the shape. -1 tells reshape to fill in whatever number is necessary to make the reshape valid. Armed with the form of the solution, I just tried things until I found the formula that works.
You should be able to break your array into "blocks" using some combination of reshape and swapaxes:
def blockshaped(arr, nrows, ncols):
"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size
If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
h, w = arr.shape
assert h % nrows == 0, f"{h} rows is not evenly divisible by {nrows}"
assert w % ncols == 0, f"{w} cols is not evenly divisible by {ncols}"
return (arr.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1,2)
.reshape(-1, nrows, ncols))
turns c
np.random.seed(365)
c = np.arange(24).reshape((4, 6))
print(c)
[out]:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
into
print(blockshaped(c, 2, 3))
[out]:
[[[ 0 1 2]
[ 6 7 8]]
[[ 3 4 5]
[ 9 10 11]]
[[12 13 14]
[18 19 20]]
[[15 16 17]
[21 22 23]]]
I've posted an inverse function, unblockshaped, here, and an N-dimensional generalization here. The generalization gives a little more insight into the reasoning behind this algorithm.
Note that there is also superbatfish's
blockwise_view. It arranges the
blocks in a different format (using more axes) but it has the advantage of (1)
always returning a view and (2) being capable of handling arrays of any
dimension.
It seems to me that this is a task for numpy.split or some variant.
e.g.
a = np.arange(30).reshape([5,6]) #a.shape = (5,6)
a1 = np.split(a,3,axis=1)
#'a1' is a list of 3 arrays of shape (5,2)
a2 = np.split(a, [2,4])
#'a2' is a list of three arrays of shape (2,5), (2,5), (1,5)
If you have a NxN image you can create, e.g., a list of 2 NxN/2 subimages, and then divide them along the other axis.
numpy.hsplit and numpy.vsplit are also available.