Python: Appending dimensions to a bidimensional array - python

Suppose you have an array (m, m) and want to make it (n, n). For example, transforming a 2x2 matrix to a 6x6. So:
[[ 1. 2.]
[ 3. 4.]]
To:
[[ 1. 2. 0. 0. 0. 0.]
[ 3. 4. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
This is what I'm doing:
def array_append(old_array, new_shape):
old_shape = old_array.shape
dif = np.array(new_shape) - np.array(old_array.shape)
rows = []
for i in xrange(dif[0]):
rows.append(np.zeros((old_array.shape[0])).tolist())
new_array = np.append(old_array, rows, axis=0)
columns = []
for i in xrange(len(new_array)):
columns.append(np.zeros(dif[1]).tolist())
return np.append(new_array, columns, axis=1)
Example use:
test1 = np.ones((2,2))
test2 = np.zeros((6,6))
print array_append(test1, test2.shape)
Output:
[[ 1. 1. 0. 0. 0. 0.]
[ 1. 1. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
Based on this answer. But that's a lot of code for an (imho) simple operation. Is there a more concise/pythonic way to do it?

Why not use array = numpy.zeros((6,6)), see the numpy docs...
EDIT, woops, question has been edited... I guess you are trying to put ones in a section of an array filled with zeros? Then:
array = numpy.zeros((6,6))
array[0:2,0:2] = 1
If the small matrix does not all have the value of 1:
array[ystart:yend,xstart:xend] = smallermatrix

That would be then:
# test1= np.ones((2, 2))
test1= np.random.randn((2, 2))
test2= np.zeros((6, 6))
test2[0: 2, 0: 2]= test1

Related

Interpolation issues at the edges with inpaint from openCV

I tried interpolating not-a-number (nan) pixels in a scan with inpaint from opencv. This worked fine in the bulk of the image, but nan pixels at the edges of the image remained nan pixels.
Here is a minimal python example to reproduce the problem:
import numpy as np
import cv2 as cv
if __name__ == '__main__':
input = np.zeros((6,6))
input[1, 3] = np.nan
input = np.float32(input)
mask = np.uint8(input != 0)
inpaintRadius = 2
inpaintAlgorithm = cv.INPAINT_NS
output = cv.inpaint(input, mask, inpaintRadius, inpaintAlgorithm)
print(output)
This gives the output:
[[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. nan 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
As the nan pixel is interpolated with the Navier-Stokes equation, the correct solution is the equilibrium state. Therefore, I would expect and want for the output.
expected output:
[[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
If I relocate the nan from [1, 3] to [2, 3], then I obtain the expected output.
Does someone know, how inpaint from openCV handels the edges and what is the appropriate way to interpolate the edges?

In a 10 by 10 matrix, why does this array notation not work?

I would like to know why doesn't my following code output a 1. on the left and right side of the matrix:
import numpy as np
import matplotlib.pyplot as plt
N = 10
def dungeon(N):
dungeon = np.zeros((N, N))
# Top and bottom
dungeon[0] = 1
dungeon[-1] = 1
# Right side
#dungeon[1][0] = 1
#dungeon[2][0] = 1
# etc...
dungeon[0:3][0]
print(dungeon)
Why doesn't dungeon[0:3][0] output 1.'s on the left column? How can I fix this without individually writing dungeon[1][0], dungeon[2][0], etc...?
You are generating a 10x10 Matrix.
dungeon[0] = 1 sets all the elements in the 1st row to 1.
dungeon[-1] = 1 sets all the elements in the last row to 1.
You didn't set the right and left sides.
There are two ways to generate a 10x10 matrix which contains 0s in the center and 1s at the sides:
dungeon = np.ones((10, 10))
dungeon [1:-1, 1:-1] = 0
OR
dungeon = np.zeros((10, 10))
dungeon[0:N,0:1] = 1
dungeon[0:N,-1:N] = 1
dungeon[0:1,0:N] = 1
dungeon[-1:N,0:N] = 1
OUTPUT:
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]
Just take the transpose!
import numpy as np
N = 10
def dungeon(N):
dungeon = np.zeros((N, N))
# Top and bottom
dungeon[0] = 1
dungeon[-1] = 1
# Right and left side
dungeon = dungeon.T
dungeon[0] = 1
dungeon[-1] = 1
print(dungeon)

Randomizing Array Values

I have a 4x4 array.
Initially the values are all set to 0, however I want to change innermost 2x2 values to a random float.
a = np.zeros((4,4))
print(a)
a[1:3,1:3] = random.uniform(-1,1)
print(a)
Creates an output:
[[0. 0. 0. 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0.66529858 0.66529858 0. ]
[0. 0. 0. 0. ]]
When the desired outcome would be:
[[0. 0. 0. 0. ]
[0. 0.random0 0.random1 0. ]
[0. 0.random2 0.random3 0. ]
[0. 0. 0. 0. ]]
You need to use the size argument to generate a 2 by 2 random matrix:
a[1:3,1:3] = random.uniform(-1,1,size=(2,2))

How to scatter a smaller array in to a larger array using a list as index?

I need help to obtain the following type of result in Python (that I was used to in Matlab):
M = numpy.zeros((5,5))
m = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
indx = [0, 2, 3]
# in Matlab: M(indx,indx) = M(indx,indx) + m
so that the output is:
[[ 1. 0. 2. 3. 0.]
[ 0. 0. 0. 0. 0.]
[ 4. 0. 5. 6. 0.]
[ 7. 0. 8. 9. 0.]
[ 0. 0. 0. 0. 0.]]

Spliting an array into train and test sets with python

I tried a method to split data between train and test sets, but it seems that it fill the train with zeros and leave the data in test...
In theory, it works :
When I apply the following function which randomly selects some columns of the given array, it worked with the DataLens with numpy matrix but not with others.
def train_test_split(array):
test = np.zeros(array.shape)
train = array.copy()
for user in xrange(array.shape[0]):
test_ratings = np.random.choice(array[user, :].nonzero()[0],
size=10,
replace=False)
train[user, test_ratings] = 0.
test[user, test_ratings] = ratings[user, test_ratings]
# Test and training are truly disjoint
assert(np.all((train * test) == 0))
return train, test
train, test = train_test_split(ratings)
With simple data it doesn't work :
When using simple data :
ratings :
[[ 1. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 0.]
[ 0. 0. 1. 0. 0.]
[ 1. 0. 0. 0. 0.]
[ 0. 0. 0. 1. 1.]]
It fill the array with 0 one by one even if train was a copy of ratings at the very beginning :
train :
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]]

Categories