4

I have an array of dimension (3,120,100) and I want to convert it into an array of dimensions (120,100,3). The array I have is

arr1 = np.ones((120,100), dtype = int)
arr2 = arr1*2
arr3 = arr1*3
arr = np.stack((arr1,arr2,arr3))
arr

It contains three 120x100 arrays of 1's, 2's, and 3's. When I use reshape on it, I get 120x100 arrays of 1's, 2's, or 3's.

I want to get an array of 120x100 where each element is [1,2,3]

  • 1
    Did you try an axis parameter for `stack`? like `np.stack([arr1, arr2, arr3], axis=2)`? – hpaulj Oct 05 '18 at 17:24
  • Possible duplicate of [How to transpose a 3D matrix?](https://stackoverflow.com/questions/47470697/how-to-transpose-a-3d-matrix) besides `transpose` you could also use `swapaxes` or `moveaxis` (see link) – Cleb Oct 17 '18 at 17:26

3 Answers3

10

If you want a big array containing 1, 2 and 3 as you describe, user3483203's answer would be the recommendable option. If you have, in general, an array with shape (X, Y, Z) and you want to have it as (Y, Z, X), you would normally use np.transpose:

import numpy as np

arr = ... # Array with shape (3, 120, 100)
arr_reshaped = np.transpose(arr, (1, 2, 0))
print(arr_reshaped.shape)
# (120, 100, 3)

EDIT: The question title says you want to reshape an array from (X, Y, Z) to (Z, Y, X), but the text seems to suggest you want to reshape from (X, Y, Z) to (Y, Z, X). I followed the text, but for the one in the title it would simply be np.transpose(arr, (2, 1, 0)).

jdehesa
  • 58,456
  • 7
  • 77
  • 121
2

I'll answer this assuming it's part of a larger problem, and this is just example data to demonstrate what you want to do. Otherwise the broadcasting solution works just fine.

When you use reshape it doesn't change how numpy interprets the order of individual elements. It simply affects how numpy views the shape. So, if you have elements a, b, c, d in an array on disk that can be interpreted as an array of shape (4,), or shape (2, 2), or shape (1, 4) and so on.

What it seems you're looking for is transpose. This affects allows swapping how numpy interprets the axes. In your case

>>>arr.transpose(2,1,0)
array([[[1, 2, 3],
    [1, 2, 3],
    [1, 2, 3],
    ..., 
    [1, 2, 3],
    [1, 2, 3],
    [1, 2, 3]]])
user2699
  • 2,927
  • 14
  • 31
  • @LeonardShaw, if this answers your question please accept it, or the answer posted earlier by jdehesa. – user2699 Oct 05 '18 at 20:10
1

You don't need to create a very large array and reshape. Since you know what you want each element to be, and the final shape, you can just use numpy.broadcast_to. This requires a setup of just creating a shape (3,) array.

Setup

arr = np.array([1,2,3])

np.broadcast_to(arr, (120, 100, 3))

array([[[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        ...,
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3],
        ...,
        [1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]])

To get a non read-only version of this output, you can call copy():

out = np.broadcast_to(arr, (120, 100, 3)).copy()
user3483203
  • 50,081
  • 9
  • 65
  • 94
  • The result of `broadcast_to` is a view of the original array. Cells are not independently modifiable, because many cells are views of the same memory location; for example, writing to index `0, 0, 0` will affect index `1, 2, 0`, as well as any index of the form `i, j, 0`. – user2357112 Oct 05 '18 at 17:08
  • @user2357112 That is true but that does not seem to be a concern for the OP. – jdehesa Oct 05 '18 at 17:10
  • @user2357112 From their requirements, they don't specify needing to actually edit any of these values, but added a clarification using `copy()`. But when you say "cells are not independently modifiable", cells are not actually modifiable at all in the original result, it's a read only view, you can't write to any of the cells – user3483203 Oct 05 '18 at 17:12