Reshape/pad Numpy array - Python - python

I have a multiple numpy arrays like so:
[1, 5, 0, 0]
[2, 1, 3, 1]
[1, 3, 4, 1]
All my arrays have different values and shapes.
I want to write a function that will pad all my arrays to the same shape.
Currently, I am doing something like this (inside a for loop):
width = int(7000 - size[0])
height = int(7000 - size[1])
data = np.pad(data, (width, height), 'constant', constant_values=(0,0))
Where data is the array being edited, and 7000x7000 is my largest array.
This is giving me a MemoryError.

i tried my own code with this:
import numpy
def arrays(arr):
return numpy.array(arr[::-1], float)
arr = input().strip().split(' ')
result = arrays(arr)
print(result)

Related

Replacing array at i`th dimension

Let's say I have a two-dimensional array
import numpy as np
a = np.array([[1, 1, 1], [2,2,2], [3,3,3]])
and I would like to replace the third vector (in the second dimension) with zeros. I would do
a[:, 2] = np.array([0, 0, 0])
But what if I would like to be able to do that programmatically? I mean, let's say that variable x = 1 contained the dimension on which I wanted to do the replacing. How would the function replace(arr, dimension, value, arr_to_be_replaced) have to look if I wanted to call it as replace(a, x, 2, np.array([0, 0, 0])?
numpy has a similar function, insert. However, it doesn't replace at dimension i, it returns a copy with an additional vector.
All solutions are welcome, but I do prefer a solution that doesn't recreate the array as to save memory.
arr[:, 1]
is basically shorthand for
arr[(slice(None), 1)]
that is, a tuple with slice elements and integers.
Knowing that, you can construct a tuple of slice objects manually, adjust the values depending on an axis parameter and use that as your index. So for
import numpy as np
arr = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
axis = 1
idx = 2
arr[:, idx] = np.array([0, 0, 0])
# ^- axis position
you can use
slices = [slice(None)] * arr.ndim
slices[axis] = idx
arr[tuple(slices)] = np.array([0, 0, 0])

transform n-dimensional numpy array to a 2D-array based on a variable in Python

I am trying to find the minimum value in an N-dimensional array spanned by (N-Parameters of varying values) and take out a 2-dimensional array spanned by 2 of the (N-Parameters) around the minimum value to make a contour plot.
I can do this by hard coding the different cases, but it should preferably be done using a variable list of which axis should be extracted (contour_param).
Please see the code below for some clarification.
import numpy as np
np.random.seed(10) # seed random for reproducebility
#Example for a 3D input array (my_data)
param_sizes = [2, 3, 4]
#Generate a data_cube
my_data = np.random.normal(size=np.prod(param_sizes)).reshape(param_sizes)
#find minimum
min_pos = np.where(my_data == my_data.min())
#what I want:
#define a parameter with the indexs of the axis to be used for the contour plot: e.i. : contour_param = [0, 1]
#for contour_param = [0, 1] i would need the the 2D array:
result = my_data[:, :, min_pos[2][0]]
#for contour_param = [1, 2] i would need the the 2D array:
result = my_data[min_pos[0][0], :, :]
#What I have tried is to convert min_pos to a list and change the entries to arrays:
contour_param = [0, 1]
min_pos = list(np.where(my_data == my_data.min()))
min_pos[contour_param[0]] = np.arange(param_sizes[contour_param[0]])
min_pos[contour_param[1]] = np.arange(param_sizes[contour_param[1]])
result = my_data[min_pos] #This throws an error
#In an attempt to clarify - I have included a sample for a 4D array
#Example for a 4D array
param_sizes = [2, 3, 4, 3]
#Generate a data_cube
my_data = np.random.normal(size=np.prod(param_sizes)).reshape(param_sizes)
#find minimum
min_pos = np.where(my_data == my_data.min())
#for contour_param = [0, 1] i would need the the 2D array:
result = my_data[:, :, min_pos[2][0], min_pos[3][0]]
#for contour_param = [1, 2] i would need the the 2D array
result = my_data[min_pos[0][0], :, :, min_pos[3][0]]
Great Question...
You can make use of np.s_ for that, as you can build up your slicer with that.
For instance the function:
def build_slicer(contour_param,min_pos):
assert len(contur_param) + 1 == min_pos.shape[0]
output = [] # init a emtpy output list
for main_index in range(min_pos.shape[0]):
if main_index in contour_param:
output.append(np.s_[:])
else:
output.append(np.s_[min_pos[main_index][0]])
return tuple(output)
would return:
import numpy as np
np.random.seed(10)
param_sizes = [2, 3, 4]
my_data = np.random.normal(size=np.prod(param_sizes)).reshape(param_sizes)
min_pos = np.where(my_data == my_data.min())
contour_param = [0,2]
build_slicer(contour_param,min_pos)
>>> (slice(None, None, None), 2, slice(None, None, None))
you can then use this to just slice your array
slice = build_slicer(contour_param,min_pos)
my_data[slice]

Numpy reshape - automatic filling or removal

I would like to find a reshape function that is able to transform my arrays of different dimensions in arrays of the same dimension. Let me explain it:
import numpy as np
a = np.array([[[1,2,3,3],[1,2,3,3]],[[1,2,3,3],[1,2,3,3]]])
b = np.array([[[1,2,3,3],[1,2,3,3]],[[1,2,3,3],[1,2,3,3]],[[1,2,3,3],[1,2,3,4]]])
c = np.array([[[1,2,3,3],[1,2,3,3]]])
I would like to be able to make b,c shapes equal to a shape. However, np.reshape throws an error because as explained here (Numpy resize or Numpy reshape) the function is explicitly made to handle the same dimensions.
I would like some version of that function that adds zeros at the start of the first dimension if the shape is smaller or remove the start if the shape is bigger. My example will look like this:
b = np.array([[[1,2,3,3],[1,2,3,3]],[[1,2,3,3],[1,2,3,4]]])
c = np.array([[[0,0,0,0],[0,0,0,0]],[[1,2,3,3],[1,2,3,3]]])
Do I need to write my own function to do that?
This is similar to above solution but will also work also if lower dimensions don't match
def custom_reshape(a, b):
result = np.zeros_like(a).ravel()
result[-min(a.size, b.size):] = b.ravel()[-min(a.size, b.size):]
return result.reshape(a.shape)
custom_reshape(a,b)
I would write a function like this:
def align(a,b):
out = np.zeros_like(a)
x = min(a.shape[0], b.shape[0])
out[-x:] = b[-x:]
return out
Output:
align(a,b)
# array([[[1, 2, 3, 3],
# [1, 2, 3, 3]],
# [[1, 2, 3, 3],
# [1, 2, 3, 4]]])
align(a,c)
# array([[[0, 0, 0, 0],
# [0, 0, 0, 0]],
# [[1, 2, 3, 3],
# [1, 2, 3, 3]]])

Numpy indexing in $n$ dimensions [duplicate]

I have 2d numpy array (think greyscale image). I want to assign certain value to a list of coordinates to this array, such that:
img = np.zeros((5, 5))
coords = np.array([[0, 1], [1, 2], [2, 3], [3, 4]])
def bad_use_of_numpy(img, coords):
for i, coord in enumerate(coords):
img[coord[0], coord[1]] = 255
return img
bad_use_of_numpy(img, coords)
This works, but I feel like I can take advantage of numpy functionality to make it faster. I also might have a use case later to to something like following:
img = np.zeros((5, 5))
coords = np.array([[0, 1], [1, 2], [2, 3], [3, 4]])
vals = np.array([1, 2, 3, 4])
def bad_use_of_numpy(img, coords, vals):
for coord in coords:
img[coord[0], coord[1]] = vals[i]
return img
bad_use_of_numpy(img, coords, vals)
Is there a more vectorized way of doing that?
We can unpack each row of coords as row, col indices for indexing into img and then assign.
Now, since the question is tagged : Python 3.x, on it we can simply unpack with [*coords.T] and then assign -
img[[*coords.T]] = 255
Generically, we can use tuple to unpack -
img[tuple(coords.T)] = 255
We can also compute the linear indices and then assign with np.put -
np.put(img, np.ravel_multi_index(coords.T, img.shape), 255)

Creating 2d histogram from 2d numpy array

I have a numpy array like this:
[[[0,0,0], [1,0,0], ..., [1919,0,0]],
[[0,1,0], [1,1,0], ..., [1919,1,0]],
...,
[[0,1019,0], [1,1019,0], ..., [1919,1019,0]]]
To create I use function (thanks to #Divakar and #unutbu for helping in other question):
def indices_zero_grid(m,n):
I,J = np.ogrid[:m,:n]
out = np.zeros((m,n,3), dtype=int)
out[...,0] = I
out[...,1] = J
return out
I can access this array by command:
>>> out = indices_zero_grid(3,2)
>>> out
array([[[0, 0, 0],
[0, 1, 0]],
[[1, 0, 0],
[1, 1, 0]],
[[2, 0, 0],
[2, 1, 0]]])
>>> out[1,1]
array([1, 1, 0])
Now I wanted to plot 2d histogram where (x,y) (out[(x,y]) is the coordinates and the third value is number of occurrences. I've tried using normal matplotlib plot, but I have so many values for each coordinates (I need 1920x1080) that program needs too much memory.
If I understand correctly, you want an image of size 1920x1080 which colors the pixel at coordinate (x, y) according to the value of out[x, y].
In that case, you could use
import numpy as np
import matplotlib.pyplot as plt
def indices_zero_grid(m,n):
I,J = np.ogrid[:m,:n]
out = np.zeros((m,n,3), dtype=int)
out[...,0] = I
out[...,1] = J
return out
h, w = 1920, 1080
out = indices_zero_grid(h, w)
out[..., 2] = np.random.randint(256, size=(h, w))
plt.imshow(out[..., 2])
plt.show()
which yields
Notice that the other two "columns", out[..., 0] and out[..., 1] are not used. This suggests that indices_zero_grid is not really needed here.
plt.imshow can accept an array of shape (1920, 1080). This array has a scalar value at each location in the array. The structure of the array tells imshow where to color each cell. Unlike a scatter plot, you don't need to generate the coordinates yourself.

Categories