Swapping the dimensions of a numpy array using Ellipsis?










1















This code is swapping first and the last channels of an RBG image which is loaded into a Numpy array:





img = imread('image1.jpg')

# Convert from RGB -> BGR
img = img[..., [2, 1, 0]]


While I understand the use of Ellipsis for slicing in Numpy arrays, I couldn't understand the use of Ellipsis here. Could anybody explain what is exactly happening here?










share|improve this question






















  • It's just a placeholder for all but the last diimension.

    – hpaulj
    Nov 13 '18 at 0:40











  • This is more of a reversal or flip of one dimension, not a swap of dimensions.

    – hpaulj
    Nov 13 '18 at 1:37















1















This code is swapping first and the last channels of an RBG image which is loaded into a Numpy array:





img = imread('image1.jpg')

# Convert from RGB -> BGR
img = img[..., [2, 1, 0]]


While I understand the use of Ellipsis for slicing in Numpy arrays, I couldn't understand the use of Ellipsis here. Could anybody explain what is exactly happening here?










share|improve this question






















  • It's just a placeholder for all but the last diimension.

    – hpaulj
    Nov 13 '18 at 0:40











  • This is more of a reversal or flip of one dimension, not a swap of dimensions.

    – hpaulj
    Nov 13 '18 at 1:37













1












1








1








This code is swapping first and the last channels of an RBG image which is loaded into a Numpy array:





img = imread('image1.jpg')

# Convert from RGB -> BGR
img = img[..., [2, 1, 0]]


While I understand the use of Ellipsis for slicing in Numpy arrays, I couldn't understand the use of Ellipsis here. Could anybody explain what is exactly happening here?










share|improve this question














This code is swapping first and the last channels of an RBG image which is loaded into a Numpy array:





img = imread('image1.jpg')

# Convert from RGB -> BGR
img = img[..., [2, 1, 0]]


While I understand the use of Ellipsis for slicing in Numpy arrays, I couldn't understand the use of Ellipsis here. Could anybody explain what is exactly happening here?







python numpy ellipsis






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 0:09









Ali SalehiAli Salehi

8817




8817












  • It's just a placeholder for all but the last diimension.

    – hpaulj
    Nov 13 '18 at 0:40











  • This is more of a reversal or flip of one dimension, not a swap of dimensions.

    – hpaulj
    Nov 13 '18 at 1:37

















  • It's just a placeholder for all but the last diimension.

    – hpaulj
    Nov 13 '18 at 0:40











  • This is more of a reversal or flip of one dimension, not a swap of dimensions.

    – hpaulj
    Nov 13 '18 at 1:37
















It's just a placeholder for all but the last diimension.

– hpaulj
Nov 13 '18 at 0:40





It's just a placeholder for all but the last diimension.

– hpaulj
Nov 13 '18 at 0:40













This is more of a reversal or flip of one dimension, not a swap of dimensions.

– hpaulj
Nov 13 '18 at 1:37





This is more of a reversal or flip of one dimension, not a swap of dimensions.

– hpaulj
Nov 13 '18 at 1:37












1 Answer
1






active

oldest

votes


















1














tl;dr



img[..., [2, 1, 0]] produces the same result as taking the slices img[:, :, i] for each i in the index array [2, 1, 0], and then stacking the results along the last dimension of img. In other words:



img[..., [2,1,0]]


will produce the same output as:



np.stack([img[:,:,2], img[:,:,1], img[:,:,0]], axis=2)


The ellipsis ... is a placeholder that tells numpy which axis to apply the index array to. Without the ... the index array will be applied to the first axis of img instead of the last. Thus, without ..., the index statement:



img[[2,1,0]]


will produce the same output as:



np.stack([img[2,:,:], img[1,:,:], img[0,:,:]], axis=0)


What the docs say



This is an example of what the docs call "Combining advanced and basic indexing":




When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element.




It goes on to describe that in this




case, the dimensions from the advanced indexing operations [in your example [2, 1, 0]] are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing).




The 2D case



The docs aren't the easiest to understand, but in this case it's not too hard to pick apart. Start with a simpler 2D case:



arr = np.arange(12).reshape(4,3)

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])


Using the same kind of advanced indexing with a single index value yields:



arr[:, [1]]

array([[ 1],
[ 4],
[ 7],
[10]])


which is the 1st column of arr. In other words, it's like you yielded all possible values from arr while holding the index of the last axis fixed. Like @hpaulj said in his comment, the ellipsis is there to act as a placeholder. It effectively tells numpy to iterate freely over all of the axes except for the last, to which the indexing array is applied.



You can use also this indexing syntax to shuffle the columns of arr around however you'd like:



arr[..., [1,0,2]]

array([[ 1, 0, 2],
[ 4, 3, 5],
[ 7, 6, 8],
[10, 9, 11]])


This is essentially the same operation as in your example, but on a 2D array instead of a 3D one.



You can explain what's going on with arr[..., [1,0,2]] by breaking it down to simpler indexing ops. It's kind of like you first take the return value of arr[..., [1]]:



array([[ 1],
[ 4],
[ 7],
[10]])


then the return value of arr[..., [0]]:



array([[0],
[3],
[6],
[9]])


then the return value of arr[..., [1]]:



array([[ 2],
[ 5],
[ 8],
[11]])


and then finally concatenated all of those results into a single array of shape (*arr.shape[:-1], len(ix)), where ix = [2, 0, 1] is the index array. The data along the last axis are ordered according to their order in ix.



One good way to understand exactly the ellipsis is doing is to perform the same op without it:



arr[[1,0,2]]

array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])


In this case, the index array is applied to the first axis of arr, so the output is an array containing the [1,0,2] rows of arr. Adding an ... before the index array tells numpy to apply the index array to the last axis of arr instead.



Your 3D case



The case you asked about is the 3D equivalent of the 2D arr[..., [1,0,2]] example above. Say that img.shape is (480, 640, 3). You can think about img[..., [2, 1, 0]] as looping over each value i in ix=[2, 1, 0]. For every i, the indexing operation will gather the slab of shape (480, 640, 1) that lies along the ith index of the last axis of img. Once all three slabs are collected, the final result will be the equivalent of concatenating along their last axis (and in the order they were found).



notes



  • The only difference between arr[..., [1]] and arr[:,1] is that arr[..., [1]] preserves the shape of the data from the original array.


  • For a 2D array, arr[:, [1]] is equivalent to arr[..., [1]]. : acts as a placeholder just like ..., but only for a single dimension.






share|improve this answer

























  • @hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

    – tel
    Nov 13 '18 at 2:15











  • @hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

    – tel
    Nov 13 '18 at 2:19










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271919%2fswapping-the-dimensions-of-a-numpy-array-using-ellipsis%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














tl;dr



img[..., [2, 1, 0]] produces the same result as taking the slices img[:, :, i] for each i in the index array [2, 1, 0], and then stacking the results along the last dimension of img. In other words:



img[..., [2,1,0]]


will produce the same output as:



np.stack([img[:,:,2], img[:,:,1], img[:,:,0]], axis=2)


The ellipsis ... is a placeholder that tells numpy which axis to apply the index array to. Without the ... the index array will be applied to the first axis of img instead of the last. Thus, without ..., the index statement:



img[[2,1,0]]


will produce the same output as:



np.stack([img[2,:,:], img[1,:,:], img[0,:,:]], axis=0)


What the docs say



This is an example of what the docs call "Combining advanced and basic indexing":




When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element.




It goes on to describe that in this




case, the dimensions from the advanced indexing operations [in your example [2, 1, 0]] are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing).




The 2D case



The docs aren't the easiest to understand, but in this case it's not too hard to pick apart. Start with a simpler 2D case:



arr = np.arange(12).reshape(4,3)

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])


Using the same kind of advanced indexing with a single index value yields:



arr[:, [1]]

array([[ 1],
[ 4],
[ 7],
[10]])


which is the 1st column of arr. In other words, it's like you yielded all possible values from arr while holding the index of the last axis fixed. Like @hpaulj said in his comment, the ellipsis is there to act as a placeholder. It effectively tells numpy to iterate freely over all of the axes except for the last, to which the indexing array is applied.



You can use also this indexing syntax to shuffle the columns of arr around however you'd like:



arr[..., [1,0,2]]

array([[ 1, 0, 2],
[ 4, 3, 5],
[ 7, 6, 8],
[10, 9, 11]])


This is essentially the same operation as in your example, but on a 2D array instead of a 3D one.



You can explain what's going on with arr[..., [1,0,2]] by breaking it down to simpler indexing ops. It's kind of like you first take the return value of arr[..., [1]]:



array([[ 1],
[ 4],
[ 7],
[10]])


then the return value of arr[..., [0]]:



array([[0],
[3],
[6],
[9]])


then the return value of arr[..., [1]]:



array([[ 2],
[ 5],
[ 8],
[11]])


and then finally concatenated all of those results into a single array of shape (*arr.shape[:-1], len(ix)), where ix = [2, 0, 1] is the index array. The data along the last axis are ordered according to their order in ix.



One good way to understand exactly the ellipsis is doing is to perform the same op without it:



arr[[1,0,2]]

array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])


In this case, the index array is applied to the first axis of arr, so the output is an array containing the [1,0,2] rows of arr. Adding an ... before the index array tells numpy to apply the index array to the last axis of arr instead.



Your 3D case



The case you asked about is the 3D equivalent of the 2D arr[..., [1,0,2]] example above. Say that img.shape is (480, 640, 3). You can think about img[..., [2, 1, 0]] as looping over each value i in ix=[2, 1, 0]. For every i, the indexing operation will gather the slab of shape (480, 640, 1) that lies along the ith index of the last axis of img. Once all three slabs are collected, the final result will be the equivalent of concatenating along their last axis (and in the order they were found).



notes



  • The only difference between arr[..., [1]] and arr[:,1] is that arr[..., [1]] preserves the shape of the data from the original array.


  • For a 2D array, arr[:, [1]] is equivalent to arr[..., [1]]. : acts as a placeholder just like ..., but only for a single dimension.






share|improve this answer

























  • @hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

    – tel
    Nov 13 '18 at 2:15











  • @hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

    – tel
    Nov 13 '18 at 2:19















1














tl;dr



img[..., [2, 1, 0]] produces the same result as taking the slices img[:, :, i] for each i in the index array [2, 1, 0], and then stacking the results along the last dimension of img. In other words:



img[..., [2,1,0]]


will produce the same output as:



np.stack([img[:,:,2], img[:,:,1], img[:,:,0]], axis=2)


The ellipsis ... is a placeholder that tells numpy which axis to apply the index array to. Without the ... the index array will be applied to the first axis of img instead of the last. Thus, without ..., the index statement:



img[[2,1,0]]


will produce the same output as:



np.stack([img[2,:,:], img[1,:,:], img[0,:,:]], axis=0)


What the docs say



This is an example of what the docs call "Combining advanced and basic indexing":




When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element.




It goes on to describe that in this




case, the dimensions from the advanced indexing operations [in your example [2, 1, 0]] are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing).




The 2D case



The docs aren't the easiest to understand, but in this case it's not too hard to pick apart. Start with a simpler 2D case:



arr = np.arange(12).reshape(4,3)

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])


Using the same kind of advanced indexing with a single index value yields:



arr[:, [1]]

array([[ 1],
[ 4],
[ 7],
[10]])


which is the 1st column of arr. In other words, it's like you yielded all possible values from arr while holding the index of the last axis fixed. Like @hpaulj said in his comment, the ellipsis is there to act as a placeholder. It effectively tells numpy to iterate freely over all of the axes except for the last, to which the indexing array is applied.



You can use also this indexing syntax to shuffle the columns of arr around however you'd like:



arr[..., [1,0,2]]

array([[ 1, 0, 2],
[ 4, 3, 5],
[ 7, 6, 8],
[10, 9, 11]])


This is essentially the same operation as in your example, but on a 2D array instead of a 3D one.



You can explain what's going on with arr[..., [1,0,2]] by breaking it down to simpler indexing ops. It's kind of like you first take the return value of arr[..., [1]]:



array([[ 1],
[ 4],
[ 7],
[10]])


then the return value of arr[..., [0]]:



array([[0],
[3],
[6],
[9]])


then the return value of arr[..., [1]]:



array([[ 2],
[ 5],
[ 8],
[11]])


and then finally concatenated all of those results into a single array of shape (*arr.shape[:-1], len(ix)), where ix = [2, 0, 1] is the index array. The data along the last axis are ordered according to their order in ix.



One good way to understand exactly the ellipsis is doing is to perform the same op without it:



arr[[1,0,2]]

array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])


In this case, the index array is applied to the first axis of arr, so the output is an array containing the [1,0,2] rows of arr. Adding an ... before the index array tells numpy to apply the index array to the last axis of arr instead.



Your 3D case



The case you asked about is the 3D equivalent of the 2D arr[..., [1,0,2]] example above. Say that img.shape is (480, 640, 3). You can think about img[..., [2, 1, 0]] as looping over each value i in ix=[2, 1, 0]. For every i, the indexing operation will gather the slab of shape (480, 640, 1) that lies along the ith index of the last axis of img. Once all three slabs are collected, the final result will be the equivalent of concatenating along their last axis (and in the order they were found).



notes



  • The only difference between arr[..., [1]] and arr[:,1] is that arr[..., [1]] preserves the shape of the data from the original array.


  • For a 2D array, arr[:, [1]] is equivalent to arr[..., [1]]. : acts as a placeholder just like ..., but only for a single dimension.






share|improve this answer

























  • @hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

    – tel
    Nov 13 '18 at 2:15











  • @hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

    – tel
    Nov 13 '18 at 2:19













1












1








1







tl;dr



img[..., [2, 1, 0]] produces the same result as taking the slices img[:, :, i] for each i in the index array [2, 1, 0], and then stacking the results along the last dimension of img. In other words:



img[..., [2,1,0]]


will produce the same output as:



np.stack([img[:,:,2], img[:,:,1], img[:,:,0]], axis=2)


The ellipsis ... is a placeholder that tells numpy which axis to apply the index array to. Without the ... the index array will be applied to the first axis of img instead of the last. Thus, without ..., the index statement:



img[[2,1,0]]


will produce the same output as:



np.stack([img[2,:,:], img[1,:,:], img[0,:,:]], axis=0)


What the docs say



This is an example of what the docs call "Combining advanced and basic indexing":




When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element.




It goes on to describe that in this




case, the dimensions from the advanced indexing operations [in your example [2, 1, 0]] are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing).




The 2D case



The docs aren't the easiest to understand, but in this case it's not too hard to pick apart. Start with a simpler 2D case:



arr = np.arange(12).reshape(4,3)

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])


Using the same kind of advanced indexing with a single index value yields:



arr[:, [1]]

array([[ 1],
[ 4],
[ 7],
[10]])


which is the 1st column of arr. In other words, it's like you yielded all possible values from arr while holding the index of the last axis fixed. Like @hpaulj said in his comment, the ellipsis is there to act as a placeholder. It effectively tells numpy to iterate freely over all of the axes except for the last, to which the indexing array is applied.



You can use also this indexing syntax to shuffle the columns of arr around however you'd like:



arr[..., [1,0,2]]

array([[ 1, 0, 2],
[ 4, 3, 5],
[ 7, 6, 8],
[10, 9, 11]])


This is essentially the same operation as in your example, but on a 2D array instead of a 3D one.



You can explain what's going on with arr[..., [1,0,2]] by breaking it down to simpler indexing ops. It's kind of like you first take the return value of arr[..., [1]]:



array([[ 1],
[ 4],
[ 7],
[10]])


then the return value of arr[..., [0]]:



array([[0],
[3],
[6],
[9]])


then the return value of arr[..., [1]]:



array([[ 2],
[ 5],
[ 8],
[11]])


and then finally concatenated all of those results into a single array of shape (*arr.shape[:-1], len(ix)), where ix = [2, 0, 1] is the index array. The data along the last axis are ordered according to their order in ix.



One good way to understand exactly the ellipsis is doing is to perform the same op without it:



arr[[1,0,2]]

array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])


In this case, the index array is applied to the first axis of arr, so the output is an array containing the [1,0,2] rows of arr. Adding an ... before the index array tells numpy to apply the index array to the last axis of arr instead.



Your 3D case



The case you asked about is the 3D equivalent of the 2D arr[..., [1,0,2]] example above. Say that img.shape is (480, 640, 3). You can think about img[..., [2, 1, 0]] as looping over each value i in ix=[2, 1, 0]. For every i, the indexing operation will gather the slab of shape (480, 640, 1) that lies along the ith index of the last axis of img. Once all three slabs are collected, the final result will be the equivalent of concatenating along their last axis (and in the order they were found).



notes



  • The only difference between arr[..., [1]] and arr[:,1] is that arr[..., [1]] preserves the shape of the data from the original array.


  • For a 2D array, arr[:, [1]] is equivalent to arr[..., [1]]. : acts as a placeholder just like ..., but only for a single dimension.






share|improve this answer















tl;dr



img[..., [2, 1, 0]] produces the same result as taking the slices img[:, :, i] for each i in the index array [2, 1, 0], and then stacking the results along the last dimension of img. In other words:



img[..., [2,1,0]]


will produce the same output as:



np.stack([img[:,:,2], img[:,:,1], img[:,:,0]], axis=2)


The ellipsis ... is a placeholder that tells numpy which axis to apply the index array to. Without the ... the index array will be applied to the first axis of img instead of the last. Thus, without ..., the index statement:



img[[2,1,0]]


will produce the same output as:



np.stack([img[2,:,:], img[1,:,:], img[0,:,:]], axis=0)


What the docs say



This is an example of what the docs call "Combining advanced and basic indexing":




When there is at least one slice (:), ellipsis (...) or np.newaxis in the index (or the array has more dimensions than there are advanced indexes), then the behaviour can be more complicated. It is like concatenating the indexing result for each advanced index element.




It goes on to describe that in this




case, the dimensions from the advanced indexing operations [in your example [2, 1, 0]] are inserted into the result array at the same spot as they were in the initial array (the latter logic is what makes simple advanced indexing behave just like slicing).




The 2D case



The docs aren't the easiest to understand, but in this case it's not too hard to pick apart. Start with a simpler 2D case:



arr = np.arange(12).reshape(4,3)

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])


Using the same kind of advanced indexing with a single index value yields:



arr[:, [1]]

array([[ 1],
[ 4],
[ 7],
[10]])


which is the 1st column of arr. In other words, it's like you yielded all possible values from arr while holding the index of the last axis fixed. Like @hpaulj said in his comment, the ellipsis is there to act as a placeholder. It effectively tells numpy to iterate freely over all of the axes except for the last, to which the indexing array is applied.



You can use also this indexing syntax to shuffle the columns of arr around however you'd like:



arr[..., [1,0,2]]

array([[ 1, 0, 2],
[ 4, 3, 5],
[ 7, 6, 8],
[10, 9, 11]])


This is essentially the same operation as in your example, but on a 2D array instead of a 3D one.



You can explain what's going on with arr[..., [1,0,2]] by breaking it down to simpler indexing ops. It's kind of like you first take the return value of arr[..., [1]]:



array([[ 1],
[ 4],
[ 7],
[10]])


then the return value of arr[..., [0]]:



array([[0],
[3],
[6],
[9]])


then the return value of arr[..., [1]]:



array([[ 2],
[ 5],
[ 8],
[11]])


and then finally concatenated all of those results into a single array of shape (*arr.shape[:-1], len(ix)), where ix = [2, 0, 1] is the index array. The data along the last axis are ordered according to their order in ix.



One good way to understand exactly the ellipsis is doing is to perform the same op without it:



arr[[1,0,2]]

array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])


In this case, the index array is applied to the first axis of arr, so the output is an array containing the [1,0,2] rows of arr. Adding an ... before the index array tells numpy to apply the index array to the last axis of arr instead.



Your 3D case



The case you asked about is the 3D equivalent of the 2D arr[..., [1,0,2]] example above. Say that img.shape is (480, 640, 3). You can think about img[..., [2, 1, 0]] as looping over each value i in ix=[2, 1, 0]. For every i, the indexing operation will gather the slab of shape (480, 640, 1) that lies along the ith index of the last axis of img. Once all three slabs are collected, the final result will be the equivalent of concatenating along their last axis (and in the order they were found).



notes



  • The only difference between arr[..., [1]] and arr[:,1] is that arr[..., [1]] preserves the shape of the data from the original array.


  • For a 2D array, arr[:, [1]] is equivalent to arr[..., [1]]. : acts as a placeholder just like ..., but only for a single dimension.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 2:50

























answered Nov 13 '18 at 0:27









teltel

7,42621431




7,42621431












  • @hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

    – tel
    Nov 13 '18 at 2:15











  • @hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

    – tel
    Nov 13 '18 at 2:19

















  • @hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

    – tel
    Nov 13 '18 at 2:15











  • @hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

    – tel
    Nov 13 '18 at 2:19
















@hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

– tel
Nov 13 '18 at 2:15





@hpaulj I think I covered most of the basics (at least in terms of how the output value is generated), but are there any interesting details that I'm missing?]

– tel
Nov 13 '18 at 2:15













@hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

– tel
Nov 13 '18 at 2:19





@hpaulj Also, do you know of any good docs/tutorials that cover the full capabilities of the advanced indexing syntax? I've read the advanced indexing section in the official docs, but it doesn't seem to cover most of the possibilities. For example, I saw this amazing answer the other day that uses indexing with np.ogrid to resample a 4D array in a structured fashion. Sadly, I still have only the barest inkling of how it actually works.

– tel
Nov 13 '18 at 2:19



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271919%2fswapping-the-dimensions-of-a-numpy-array-using-ellipsis%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)