How to get matrix rows by indexes? - python

Assuming that we have a matrix X and a target column y as following:
import numpy as np
X = np.ones([10,2])
for i in range(0,X.shape[0]):
X[i][0] = i
y = [0,1,2,1,0,0,1,2,3,3]
I want to get rows of X depending on the value of y. From the small example above:
For y == 0, I want to get rows of X as:
[[0 1]
[4 1]
[5 1]]
For y == 3, I want to get rows of X as:
[[8 1]
[9 1]]
And so on.
How can I solve this problem?
I also tried
print(X[y == 0][:])
But it did not work.

You must convert ordinary python array to numpy.ndarray, as follow
Y=np.array(y)
print(X[Y == 0][:])
you will get:
[[ 0. 1.]
[ 4. 1.]
[ 5. 1.]]

Related

Reformatting a numpy array

I have come across some code (which may answer this question of mine). Here is the code (from Vivek Maskara's solution to my issue):
import cv2 as cv
import numpy as np
def read(image_path, label):
image = cv.imread(image_path)
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
image_h, image_w = image.shape[0:2]
image = cv.resize(image, (448, 448))
image = image / 255.
label_matrix = np.zeros([7, 7, 30])
for l in label:
l = l.split(',')
l = np.array(l, dtype=np.int)
xmin = l[0]
ymin = l[1]
xmax = l[2]
ymax = l[3]
cls = l[4]
x = (xmin + xmax) / 2 / image_w
y = (ymin + ymax) / 2 / image_h
w = (xmax - xmin) / image_w
h = (ymax - ymin) / image_h
loc = [7 * x, 7 * y]
loc_i = int(loc[1])
loc_j = int(loc[0])
y = loc[1] - loc_i
x = loc[0] - loc_j
if label_matrix[loc_i, loc_j, 24] == 0:
label_matrix[loc_i, loc_j, cls] = 1
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]
label_matrix[loc_i, loc_j, 24] = 1 # response
return image, label_matrix
Would it be possible for you to explain how this part of the code works and what it specifically does:
if label_matrix[loc_i, loc_j, 24] == 0:
label_matrix[loc_i, loc_j, cls] = 1
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]
label_matrix[loc_i, loc_j, 24] = 1 # response
I will first create and explain a simplified example, and then explain the part you pointed.
First, we create the ndarray named label_matrix:
import numpy as np
label_matrix = np.ones([2, 3, 4])
print(label_matrix)
This code means that you wil get an array containing 2 arrays, each of these 2 arrays will contain 3 arrays, and each of these 3 arrays will contain 4 elements.
And because we used np.ones, all these elements will have a value of 1.
So, printing label_matrix wil output this:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
Now, we will change the values of first 4 elements of the first array contained by the first array of label_matrix.
To acces the first array of label_matrix, we do: label_matrix[0]
To access the first array contained by the first array of label_matrix we do: label_matrix[0, 0]
To access the first element of the first array contained by the first array of label_matrix we do: label_matrix[0, 0, 0]
To access the second element of the first array contained by the first array of label_matrix we do: label_matrix[0, 0, 1]
etc.
So, now, we will change the values of first 4 elements of the first array contained by the first array of label_matrix:
label_matrix[0, 0, 0] = 100
label_matrix[0, 0, 1] = 200
label_matrix[0, 0, 2] = 300
label_matrix[0, 0, 2] = 400
Output of label_matrix:
[[[100. 200. 300. 400.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
[[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]]
But we could have written it like this, instead of wrting 4 lines of codes:
label_matrix[0, 0, 0:4] = [100,200,300,400]
Writing label_matrix[0, 0, 0:4] means:
in the first array contained by the first array of label_matrix, select the 4 first elements (from index 0 to 4 (4 being not included))
So now you know the meaning of each line.
I'll explain the part of code you pointed:
if label_matrix[loc_i, loc_j, 24] == 0::
Test if the element at index 24 (the 23th element) has value 0
if yes, then:
label_matrix[loc_i, loc_j, cls] = 1:
assign the value 1 to the element at index cls. (If the variable named cls has value 4, it will assigne the value 1 to the element at index 4 of the first array contained by the first array of label_matrix)
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]:
Say "x==100", "y==200", "w==300" and "h==400". So, in the first array contained by the first array of label_matrix, assign value 100 to the elemnt at index 20, value 200 to the elemnt at index 21, 300 at index 22 and 400 to index 23
label_matrix[loc_i, loc_j, 24] = 1:
in the first array contained by the first array of label_matrix, assign value 1 to the element at index 24

Numpy - Declare a specific nx1 array

I'm using numpy in python , in order to create a nx1 matrix . I want the 1st element of the matrix to be 3 , the 2nd -1 , then the n-1 element -1 again and at the end the n element 3. All the in between elements , i.e. from element 3 to element n-2 should be 0. I've made a drawing of the mentioned matrix , is like this :
I'm fairly new to python and using numpy but seems like a great tool for managing matrices. What I've tried so far is creating the nx1 array (giving n some value) and initializing it to 0 .
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
print("\Matrix is \n",matrix)
Any clues to how i proceed? Or what routine to use ?
Probably the simplest way is to just do the following:
import numpy as np
n = 10
a = np.zeros(n)
a[0] = 3
a[1] = -1
a[len(a)-1] = 3
a[len(a)-2] = -1
>>print(a)
output: [ 3. -1. 0. 0. 0. 0. 0. 0. -1. 3.]
Hope this helps ;)
In [97]: n=10
In [98]: arr = np.zeros(n,int)
In [99]: arr[[0,-1]]=3; arr[[1,-2]]=-1
In [100]: arr
Out[100]: array([ 3, -1, 0, 0, 0, 0, 0, 0, -1, 3])
Easily changed to (n,1):
In [101]: arr[:,None]
Out[101]:
array([[ 3],
[-1],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[-1],
[ 3]])
I guess something that works is :
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
matrix[0]=3
matrix[1]=-1
matrix[n-2]=-1
matrix[n-1]=3
print("\Matrix is \n",matrix)

using Fourier transforms to do convolution?

According to the Convolution theorem, we can convert the Fourier transform operator to convolution.
Using Python and Scipy, my code is below but not correct.
Can you help me and explain it?
import tensorflow as tf
import sys
from scipy import signal
from scipy import linalg
import numpy as np
x = [[1 , 2] , [7 , 8]]
y = [[4 , 5] , [3 , 4]]
print "conv:" , signal.convolve2d(x , y , 'full')
new_x = np.fft.fft2(x)
new_y = np.fft.fft2(y)
print "fft:" , np.fft.ifft2(np.dot(new_x , new_y))
The result of code:
conv: [[ 4 13 10]
[31 77 48]
[21 52 32]]
fft: [[ 20.+0.j 26.+0.j]
[ 104.+0.j 134.+0.j]]
I'm confused!
The problem may be in the discrepancy between the discrete and continuous convolutions. The convolution kernel (i.e. y) will extend beyond the boundaries of x, and these regions need accounting for in the convolution.
scipy.signal.convolve will by default pad the out of bounds regions with 0s, which will bias results:
https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.convolve2d.html
The Fourier multiplication will not do this by default - you could test this by making padded x, y arrays and comparing the results.
The discrepancy between such techniques should diminish as the kernel size becomes much less than the image dimensions.
As a further note - you should not use the dot product between new_x, new_y. Instead, just multiply the arrays with the * operator.
Hope this helps.
I answer my question.
The correct code.
import sys
from scipy import signal
from scipy import linalg
import numpy as np
x = [[1 , 0 , 0 , 0] , [0 , -1 , 0 , 0] , [0 , 0 , 3 , 0] , [0 , 0 , 0 , 1]]
x = np.array(x)
y = [[4 , 5] , [3 , 4]]
y = np.array(y)
print "conv:" , signal.convolve2d(x , y , 'full')
s1 = np.array(x.shape)
s2 = np.array(y.shape)
size = s1 + s2 - 1
fsize = 2 ** np.ceil(np.log2(size)).astype(int)
fslice = tuple([slice(0, int(sz)) for sz in size])
new_x = np.fft.fft2(x , fsize)
new_y = np.fft.fft2(y , fsize)
result = np.fft.ifft2(new_x*new_y)[fslice].copy()
print "fft for my method:" , np.array(result.real , np.int32)
print "fft:" , np.array(signal.fftconvolve(x ,y) , np.int32)

What is the Python numpy equivalent of the IDL # operator?

I am looking for the Python numpy equivalent of the IDL # operator.
Here is what the # operator does:
Computes array elements by multiplying the columns of the first array
by the rows of the second array. The second array must have the same
number of columns as the first array has rows. The resulting array has
the same number of columns as the first array and the same number of
rows as the second array.
Here are the numpy arrays I am dealing with:
A = [[ 0.9826128 0. 0.18566662]
[ 0. 1. 0. ]
[-0.18566662 0. 0.9826128 ]]
and
B = [[ 1. 0. 0. ]
[ 0.62692564 0.77418869 0.08715574]]
Also, numpy.dot(A,B) results in ValueError: matrices are not aligned.
Reading the notes on IDL's definition of matrix multiplication, it seems they use the opposite notation to everyone else:
IDL’s convention is to consider the first dimension to be the column
and the second dimension to be the row
So # can be achieved by the rather strange looking:
numpy.dot(A.T, B.T).T
from their example values:
import numpy as np
A = np.array([[0, 1, 2], [3, 4, 5]])
B = np.array([[0, 1], [2, 3], [4, 5]])
C = np.dot(A.T, B.T).T
print(C)
gives
[[ 3 4 5]
[ 9 14 19]
[15 24 33]]
If I'm correct you want matrix multiplication.

Python: Resize an existing array and fill with zeros

I think that my issue should be really simple, yet I can not find any help
on the Internet whatsoever. I am very new to Python, so it is possible that
I am missing something very obvious.
I have an array, S, like this [x x x] (one-dimensional). I now create a
diagonal matrix, sigma, with np.diag(S) - so far, so good. Now, I want to
resize this new diagonal array so that I can multiply it by another array that
I have.
import numpy as np
...
shape = np.shape((6, 6)) #This will be some pre-determined size
sigma = np.diag(S) #diagonalise the matrix - this works
my_sigma = sigma.resize(shape) #Resize the matrix and fill with zeros - returns "None" - why?
However, when I print the contents of my_sigma, I get "None". Can someone please
point me in the right direction, because I can not imagine that this should be
so complicated.
Thanks in advance for any help!
Casper
Graphical:
I have this:
[x x x]
I want this:
[x 0 0]
[0 x 0]
[0 0 x]
[0 0 0]
[0 0 0]
[0 0 0] - or some similar size, but the diagonal elements are important.
There is a new numpy function in version 1.7.0 numpy.pad that can do this in one-line. Like the other answers, you can construct the diagonal matrix with np.diag before the padding.
The tuple ((0,N),(0,0)) used in this answer indicates the "side" of the matrix which to pad.
import numpy as np
A = np.array([1, 2, 3])
N = A.size
B = np.pad(np.diag(A), ((0,N),(0,0)), mode='constant')
B is now equal to:
[[1 0 0]
[0 2 0]
[0 0 3]
[0 0 0]
[0 0 0]
[0 0 0]]
sigma.resize() returns None because it operates in-place. np.resize(sigma, shape), on the other hand, returns the result but instead of padding with zeros, it pads with repeats of the array.
Also, the shape() function returns the shape of the input. If you just want to predefine a shape, just use a tuple.
import numpy as np
...
shape = (6, 6) #This will be some pre-determined size
sigma = np.diag(S) #diagonalise the matrix - this works
sigma.resize(shape) #Resize the matrix and fill with zeros
However, this will first flatten out your original array, and then reconstruct it into the given shape, destroying the original ordering. If you just want to "pad" with zeros, instead of using resize() you can just directly index into a generated zero-matrix.
# This assumes that you have a 2-dimensional array
zeros = np.zeros(shape, dtype=np.int32)
zeros[:sigma.shape[0], :sigma.shape[1]] = sigma
I see the edit... you do have to create the zeros first and then move some numbers into it. np.diag_indices_from might be useful for you
bigger_sigma = np.zeros(shape, dtype=sigma.dtype)
diag_ij = np.diag_indices_from(sigma)
bigger_sigma[diag_ij] = sigma[diag_ij]
This solution works with resize function
Take a sample array
S= np.ones((3))
print (S)
# [ 1. 1. 1.]
d= np.diag(S)
print(d)
"""
[[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]]
"""
This dosent work, it just add a repeating values
np.resize(d,(6,3))
"""
adds a repeating value
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.],
[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
"""
This does work
d.resize((6,3),refcheck=False)
print(d)
"""
[[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]
[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
"""
Another pure python solution is
a = [1, 2, 3]
b = []
for i in range(6):
b.append((([0] * i) + a[i:i+1] + ([0] * (len(a) - 1 - i)))[:len(a)])
b is now
[[1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
it's a hideous solution, I'll admit that.
However, it illustrates some functions of the list type that can be used.

Categories