How to call the number in a matrix - python

here is my matrix setup:
for a in b:
size_x = len(a) + 1
size_y = len(b) + 1
matrix = np.zeros ((size_x, size_y))
for x in range(size_x):
matrix [x, 0] = x
for y in range(size_y):
matrix [0, y] = y
for x in range(1, size_x):
for y in range(1, size_y):
if a[x-1] == b[y-1]:
matrix [x,y] = min(
matrix[x-1, y] + 1,
matrix[x-1, y-1],
matrix[x, y-1] + 1
)
else:
matrix [x,y] = min(
matrix[x-1,y] + 1,
matrix[x-1,y-1] + 1,
matrix[x,y-1] + 1
)
print(matrix)
This would give outputs such as
t e s t
[[ 0. 1. 2. 3. 4.]
t [ 1. 0. 1. 2. 3.]
e [ 2. 1. 0. 1. 2.]
x [ 3. 2. 1. 1. 2.]
t [ 4. 3. 2. 1. 1.]]
In which the bottom right-hand corner is the final value. How do I take this out and add it to a list?

You can access the ith index of an array arr by using this expression: arr[i] .
In order to answer your question -> accessing the bottom-right value of a 2d matrix simply use,
matrix[matrix.length-1][matrix[matrix.length-1].length-1]
or better
lastRowIndex = matrix.length-1;
lastColIndex = matrix[lastRowIndex].length-1;
bottomRightValue = matrix[lastRowIndex][lastColIndex]

Related

I want to split data (positive/negative) and put them in empty numpy arrays. (LOGISTIC REGRESSION EXAMPLE)

So I am stuck in sorting out this problem and I have this data of email ID and there respective value as 0 & 1 (corresponding tag values used in Logistic Regression). The data is as follows:
input_x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
input_y = np.array([0,1,0,0,1,1,1,0,0,0,0,1,0,1,0])
Now I want to split this data into two sets where I have all 0's values and corresponding "input_x" values in one set and all 1's values and corresponding "input_x" values in other set. For that I have made this function:
def split_data(x,y):
shpx = x.shape[0]
shpy = y.shape[0]
neg_data = 0
pos_data = 0
for i in range(shpy):
if y[i] == 0:
neg_data = neg_data + 1
else:
pos_data = pos_data + 1
print(f"Number of negative (0) values = {neg_data}")
print(f"Number of positive (1) values = {pos_data}")
emp_neg_data_x = np.zeros(neg_data)
emp_neg_data_y = np.zeros(neg_data)
emp_pos_data_x = np.zeros(pos_data)
emp_pos_data_y = np.zeros(pos_data)
for j in range(neg_data):
for k in range(shpx):
if y[k] == 0:
emp_neg_data_x[j] = x[j]
emp_neg_data_y[j] = 0
else:
pass
for m in range(pos_data):
for n in range(shpx):
if y[n] == 0:
emp_pos_data_x[m] = x[m]
emp_pos_data_y[m] = 1
else:
pass
return emp_neg_data_x,emp_neg_data_y,emp_pos_data_x,emp_pos_data_y
Where args x & y are input arrays. Upon running this function I get this result as:
Number of negative (0) values = 9
Number of positive (1) values = 6
[1. 2. 3. 4. 5. 6. 7. 8. 9.]
[0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 2. 3. 4. 5. 6.]
[1. 1. 1. 1. 1. 1.]
The emp_neg_data_y and emp_pos_data_y give correct values but the other two arrays simply output the sequenced index value and not the value of email_idx/input_x corresponding to 0 and 1.
Can you help me out? (I guess there is a problem in loop but I am stuck...)
First make a dictionary of x and y:
input_x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])
input_y = np.array([0,1,0,0,1,1,1,0,0,0,0,1,0,1,0])
y_dict = {x: input_y[x-1] for x in input_x}
Create your lists and print:
emp_neg_data_x = [x for x, y in y_dict.items() if y == 0]
emp_neg_data_y = [y for x, y in y_dict.items() if y == 0]
emp_pos_data_x = [x for x, y in y_dict.items() if y == 1]
emp_pos_data_y = [y for x, y in y_dict.items() if y == 1]
print(emp_neg_data_x)
print(emp_neg_data_y)
print(emp_pos_data_x)
print(emp_pos_data_y)
Output:
[1, 3, 4, 8, 9, 10, 11, 13, 15]
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[2, 5, 6, 7, 12, 14]
[1, 1, 1, 1, 1, 1]

How to keep a matrix unchanged

I am trying to calculate the inverse matrix using the Gauss-Jordan Method. For that, I need to find the solution X to A.X = I (A and X being N x N matrices, and I the identity matrix).
However, for every column vector of the solution matrix X I calculate in the first loop, I have to use the original matrix A, but I don't know why it keeps changing when I did a copy of it in the beginning.
def SolveGaussJordanInvMatrix(A):
N = len(A[:,0])
I = np.identity(N)
X = np.zeros([N,N], float)
A_orig = A.copy()
for m in range(N):
x = np.zeros(N, float)
v = I[:,m]
A = A_orig
for p in range(N): # Gauss-Jordan Elimination
A[p,:] /= A[p,p]
v[p] /= A[p,p]
for i in range(p): # Cancel elements above the diagonal element
v[i] -= v[p] * A[i,p]
A[i,p:] -= A[p,p:]*A[i,p]
for i in range(p+1, N): # Cancel elements below the diagonal element
v[i] -= v[p] * A[i,p]
A[i,p:] -= A[p,p:]*A[i,p]
X[:,m] = v # Add column vector to the solution matrix
return X
A = np.array([[2, 1, 4, 1 ],
[3, 4, -1, -1],
[1, -4, 7, 5],
[2, -2, 1, 3]], float)
SolveGaussJordanInvMatrix(A)
Does anyone know how turn A back to its original form after the Gauss-Elimination loop?
I'm getting
array([[ 228.1, 0. , 0. , 0. ],
[-219.9, 1. , 0. , 0. ],
[ -14.5, 0. , 1. , 0. ],
[-176.3, 0. , 0. , 1. ]])
and expect
[[ 1.36842105 -0.89473684 -1.05263158 1. ]
[-1.42105263 1.23684211 1.13157895 -1. ]
[ 0.42105263 -0.23684211 -0.13157895 -0. ]
[-2. 1.5 1.5 -1. ]]

PLU (LUP) decomposition failed with zeros on main diagonal

I am trying to write PLU (LUP) decomposition using Gaussian elimination. I found this article with this algorithm:
def plu(A):
#Get the number of rows
n = A.shape[0]
#Allocate space for P, L, and U
U = A.copy()
L = np.eye(n, dtype=np.double)
P = np.eye(n, dtype=np.double)
#Loop over rows
for i in range(n):
#Permute rows if needed
for k in range(i, n):
if ~np.isclose(U[i, i], 0.0):
break
U[[k, k+1]] = U[[k+1, k]]
P[[k, k+1]] = P[[k+1, k]]
#Eliminate entries below i with row
#operations on U and #reverse the row
#operations to manipulate L
factor = U[i+1:, i] / U[i, i]
L[i+1:, i] = factor
U[i+1:] -= factor[:, np.newaxis] * U[i]
return P, L, U
With normal matrix it's running well but when on main diagonal appears 0 it breaks. For example with this matrix:
[[1, 0, 26, 10],
[60, 0, 75, 50],
[45, 90, 31, 100],
[30, 45, 10, 0]]
P
[[1. 0. 0. 0.]
[0. 0. 1. 0.]
[0. 1. 0. 0.]
[0. 0. 0. 1.]]
L
[[ 1. 0. 0. 0.]
[60. 1. 0. 0.]
[45. 0. 1. 0.]
[30. 0.5 0.13501684 1.]]
U
[[1. 0. 26. 10. ]
[0. 90. -1139. -350. ]
[0. 0. -1485. -550. ]
[0. 0. 0. -50.74074074]]
Multiplication of PLU will not give the original matrix.
So I tried to fix the algorithm: when rows swapping they are swapping only in P and U, so I add L[[k, k + 1]] = L[[k + 1, k]] in the inner loop to swap it in the L too. Also I changed the initialization of L: in the start I fill L with zeros L = np.zeros_like(A) and add identity matrix in the end L += np.eye(n, dtype=np.double).
But fixed version of algorithm give wrong result when top left element is 0. Any ideas what I'm doing wrong?
I think I fix it.
def get_plu_decomposition(A):
n = A.shape[0]
U = csr_matrix(A.copy())
L = csr_matrix(np.zeros_like(A))
P = csr_matrix(np.eye(n, dtype=np.double))
for i in range(n - 1):
index = np.argmax(abs(U[i:, i]))
if not U[i:, i][index] != 0:
continue
index += i
if index != i:
U[[index, i]] = U[[i, index]]
P[[index, i]] = P[[i, index]]
L[[index, i]] = L[[i, index]]
factor = U[i + 1:, i] / U[i, i]
L[i + 1:, i] = factor
U[i + 1:] -= factor * U[i]
L += csr_matrix(np.eye(n, dtype=np.double))
P = P.transpose()
assert (np.allclose(A, (P#L#U).toarray()))
return P, L, U
The problem was in swapping rows and transposing P matrix

Transpose `matrix[:,mask]` to `matrix[mask,:]` by using only number `0` and `1`?

I want to write only one function to calculate true mean (don't count the zero element when averaging numbers in row or column) of each row or column of matrix. I try to control whether it is by-row or by-column calculation using axis parameters as 1 or 0, respectively.
This is the function for by-column calculation
def true_mean(matrix, axis):
countnonzero = (matrix!=0).sum(axis)
mask = countnonzero!=0
output_mat = np.zeros(matrix.T.shape[axis])
output_mat[mask] = matrix[:,mask].sum(axis)/countnonzero[mask] # line4
return output_mat
Test the function
eachPSM = np.ones([5,4])
eachPSM[0] = 0
eachPSM[2,2:4] = 5
print each PSM
> [[ 0. 0. 0. 0.]
[ 1. 1. 1. 1.]
[ 1. 1. 5. 5.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
ans = true_mean(eachPSM,0)
print ans
> [ 1. 1. 2. 2.]
However, if I want to calculate by row (axis = 1), only line4 has to change to
output_mat[mask] = matrix[mask,:].sum(axis)/countnonzero[mask]
Is there a way to flip matrix[:,mask] to matrix[mask,:] by using only number 0 and 1? So I can have only one function for calculating true mean from row and column.
You can use the fact that the [] operator takes a tuple as input argument:
indexer = [slice(None), slice(None)]
indexer[axis] = mask
print(x[indexer])
slice(None) is equivalent to :, so we construct a tuple that takes the full matrix [:, :] and replace the entry of the desired axis with the mask.
Complete example:
import numpy as np
x = np.arange(9).reshape(3, 3)
mask = np.array([True, False, True])
for axis in [0, 1]:
indexer = [slice(None)] * x.ndim
indexer[axis] = mask
print(x[indexer])
prints
[[0 1 2]
[6 7 8]]
and
[[0 2]
[3 5]
[6 8]]

Elementwise division, disregarding zeros

It's a python question: let's say I have an m+1-dimensional numpy array a consisting of non-negative numbers, and I would like to obtain an array b of the same size where the last coordinates are normalized so that they sum up to 1, or zero in case all of them were zeros. For example, if m = 2, my code would be as follows
import numpy as np
a = np.array([[[ 0.34 , 0.66],
[ 0.75 , 0.25]],
[[ 0. , 0. ],
[ 1. , 0. ]]])
for i1 in range(len(a)):
for i2 in range(len(a)):
s = a[i1][i2].sum()
if s > 0:
a[i1][i2] = a[i1][i2]/s
however I find this method sloppy. Also, it works only for fixed m.
This can be done by broadcasting. There are several ways to take into account the zero-sum exception. Without taking it into account, you could write
import numpy as np
shape = (2, 3, 4)
X = np.random.randn(*shape) ** 2
sums = X.sum(-1)
Y = X / sums[..., np.newaxis]
Now, in order to take into account potential zero-sum-ness of some lines, we set one line of the data to 0:
X[0, 0, :] = 0
sums = X.sum(-1)
nnz = sums != 0
Y = np.zeros_like(X)
Y[nnz, :] = X[nnz, :] / sums[nnz, np.newaxis]
You will observe that Y.sum(axis=-1) has the entry 0 in coordinate (0,0) reflecting the zero-ness of the corresponding line.
EDIT: Application to the concrete example
X = np.array(array([[[ 0.34 , 0.66],
[ 0.75 , 0.25]],
[[ 0. , 0. ],
[ 1. , 0. ]]]))
sums = X.sum(-1)
nnz = sums != 0
Y = np.zeros_like(X)
Y[nnz, :] = X[nnz, :] / sums[nnz, np.newaxis]
yields Y == X (because along the last axis the sum is already one or zero.)

Categories

Resources