Transposing a matrix using loops - python

Given the matrix
matrix = [[2, None],
[2, None]]
I need to compute the transpose of this. I did the following:
def transpose(matrix):
# Makes a copy of the matrix
result = matrix
# Computes tranpose
for i in range(2):
for j in range(2):
result[j][i] = matrix[i][j]
return result
But this gives me the false result:
[[2, None],
[None, None]]
while it should be
[[2, 2],
[None, None]]
Can someone tell me where I went wrong with my code?

You a referencing to the same matrix, try initializing a new one:
def transpose(matrix):
# Makes a copy of the matrix
result = [[None]* len(x) for x in matrix]
# Computes tranpose
for i in range(2):
for j in range(2):
result[i][j] = matrix[j][i]
return result
You can also do it for a generic matrix using list comprehesion
def transpose(matrix):
return [[matrix[i][j] for i in range(len(matrix[j]))] for j in range(len(matrix))]

The problem is that the variable result refers to matrix, that is, you do not make a copy, so in the for-loop you actually also change matrix. You can solve this by making a copy of matrix in result with list:
result = [list(x) for x in matrix]
See the question: How to clone or copy a list?
Note that an easier way is to use NumPy:
import numpy as np
matrix = np.matrix([[2, None],[2, None]])
then use matrix.T to get the transpose:
matrix([[2, 2],
[None, None]], dtype=object)

# We can use the below method also:
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
mat_trans = []
trans = []
trans1 = []
trans2 = []
trans3 = []
for row in matrix:
for i in range(4):
if i == 0:
trans.append(row[i])
if i == 1:
trans1.append(row[i])
if i == 2:
trans2.append(row[i])
if i == 3:
trans3.append(row[i])
mat_trans.append(trans)
mat_trans.append(trans1)
mat_trans.append(trans2)
mat_trans.append(trans3)
trans = []
print(mat_trans)

Assuming that the matrix is rectangular (i.e. same list size in all one-D arrays), one can simply write a transpose as the following.
def transpose(matrix):
num_rows = len(matrix)
num_cols = len(matrix[0])
result = []
for j in range(num_cols):
rowresult = []
for i in range(num_rows):
rowresult.append(matrix[i][j])
result.append(rowresult)
return result
Note: This is not the most efficient implementation.

Related

Finding Subsets Function to Work for a Multidimensional Array

So I have function below that checks to see if any element of list a is the subset of any other element in the same list, and it returns only those indexes that are subsets.
a = [[1,2,3,4],
[2,3],
[1,5,7,8],
[5],
[7,8],
[1,2,3],
[7,8,9]]
#we need to keep [0,2,6]
#we need to remove [1,3,4,5]
def indexes_to_remove(array):
def boolMatrix(array):
boole = []
d ={}
for i,m in enumerate(array):
d[i] = []
for j in array:
boole.append(set(m).issubset(j))
return np.array(boole).reshape(len(array),len(array)) #True equals "is subset"
b= boolMatrix(array)
print(b)
res = [] #indexes to remove
for i,m in enumerate(b):
if sum(m) > 1: #if the index IS a subset of any other index (excludes "True" identity of itself)
res.append(i)
return res
indexes_to_remove(a)
outputs >> [1,3,4,5]
My problem however, is that I need this function to work for a multidimensional array that is
[n X n X 2] whereas a is only [n X n X 1]. For example, I need it to work on something that looks like:
a = [array([[1,2],[1,5],[2,3],[5,7]]),
array([[2,3],[5,7]]),
array([[1,5],[4,5],[9,2]]),
array([[2,3],[4,5],[1,5]])]
which should return [1].
Please help! What change do I need to do to my function for it to work for a multidimensional array of this shape?

Two ways to create 2D array in python

What is the difference between the below two ways for creating 2d array in python?
def arrays(row, column):
myList = [[None]*column for i in range(row)]
def arrays(row, column):
myList = [[None]*column]*row
In the first case, separate pointers are used to store your sublists.
In the second instance, the same pointer is used. So changing the value of one will also change the others.
Here's an illustrative example:-
def arrays1(row, column):
return [[None]*column for i in range(row)]
def arrays2(row, column):
return [[None]*column]*row
x = arrays1(2, 2)
y = arrays2(2, 2)
x[0][0] = 1
y[0][0] = 1
print(x) # [[1, None], [None, None]]
print(y) # [[1, None], [1, None]]

Nested for loop to transpose matrix

def transpose_matrix(matrix):
n = len(matrix)
vertical_to_horizontal = [[0]*n]*n
for i in range(n):
for j in range(n):
vertical_to_horizontal[i][j] = matrix[j][i]
return vertical_to_horizontal
print(transpose_matrix([[1,2],[3,4]]))
The function is supposed to transpose a n*n matrix, but I get [[2, 4], [2, 4]] instead of the correct answer ([1,3],[2,4]).
I know that there are other ways to transpose a matrix, but my problem is to understand why the code above doesn't give the expected result.
Your algorithm is correct, the problem lies in the way you create your empty matrix at the beginning, with
vertical_to_horizontal = [[0]*n]*n
The inner [0]*n creates a list [0, 0]
Then, the outer * operator creates a list that references twice this inner list - the very same object.
n = 2
v_to_h = [[0]*n] * n
print(id(v_to_h[0]), id(v_to_h[1]))
#140243497120456 140243497120456
The two [0, 0] lists in your matrix are in fact the same object, as their identical ids shows. So, when we do
v_to_h[0][0] = 5
we update the 0th element of v_to_h[0], but v_to_h[0] and v_to_h[1] are the same object, so we get twice the same list in the matrix:
print(v_to_h)
#[[5, 0], [5, 0]]
If you want to prevent that, you have to create different inner lists, so don't use the * operator.
You can use a list comprehension, as in:
n = 2
v_to_h = [[0]*n for i in range(n)]
print(id(v_to_h[0]), id(v_to_h[1]))
#140243437130184 140243512804488
Here, our two lists are different objects.
So, your code could be:
def transpose_matrix(matrix):
n = len(matrix)
vertical_to_horizontal = [[0]*n for i in range(n)]
for i in range(n):
for j in range(n):
vertical_to_horizontal[i][j] = matrix[j][i]
return vertical_to_horizontal
print(transpose_matrix([[1,2],[3,4]]))
#[[1, 3], [2, 4]]
which does what you expect - though there are, of course, shorter and more efficient ways to transpose a matrix, as already indicated in the comments.
def transpose_matrix(matrix):
n = len(matrix)
vertical_to_horizontal = []
for i in range(n):
vertical_to_horizontal.append([i]*n)
for j in range(n):
vertical_to_horizontal[i][j] = matrix[j][i]
return vertical_to_horizontal
print(transpose_matrix([[1,2],[3,4]]))

Python code to find the transpose of a matrix

I have the following code to find the transpose of a matrix
n,m=map(int,raw_input().split())
a=[]
for i in range(n):
a.append(map(int,raw_input().split()))
for i in range(m):
for j in range(n):
a[i][j],a[j][i]=a[j][i],a[i][j]
for i in a: #printing transpose
print i
But when i print the resultant transpose matrix, source matrix elements is getting printed....Is there any problem with the code or logic??
Using numpy,
import numpy as np
a=np.array([[1,2,3],[4,5,6]])
a.transpose()
As an alternative answer i suggest use zip function for find transposition of a matrix :
>>> a=[[1,2,3],[0,7,8],[12,40,9]]
>>> map(list,zip(*a))
[[1, 0, 12], [2, 7, 40], [3, 8, 9]]
Your matrix transpose is reflexive i.e.
i , j = x, y and swap a[i] with a[j] then for i, j = y, x it will swap a[i] and a[j] and it would restore the values
So you need to enforce an ordering
def foo():
n,m=map(int,raw_input().split())
a=[]
for i in range(n):
a.append(map(int,raw_input().split()))
for i in range(m):
for j in range(i+1, n): # ensure j > i
a[i][j],a[j][i]=a[j][i],a[i][j]
for i in a: #printing transpose
print i
Note, Python libraries already has a function that performs transpose of a 2 dimensional lists called zip
def foo():
n,m=map(int,raw_input().split())
a=[]
for i in range(n):
a.append(map(int,raw_input().split()))
zip(*a)
for i in a: #printing transpose
print i

Matrix Addition in Python - list

I'm trying to write Matrix Addition function using Python.
Here is the code I've been trying, but it gives me a list index error and I cannot figure out why.
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A)):
result = A[i][column] + B[i][column]
Z[i][column] = (result)
return Z
using the following lists:
A = [[2,4], [7,0], [6,3]]
B = [[3,1], [-1,8], [-3, 3]]
So in theory, A[0][0] + B[0][0] would equal 5, and I would want to add that value to position Z[0][0].
However I keep receiving the error: IndexError: list index out of range
>>> A = [[2,4], [7,0], [6,3]]
>>> B = [[3,1], [-1,8], [-3, 3]]
>>> Z = [map(sum, zip(*t)) for t in zip(A, B)]
>>> Z
[[5, 5], [6, 8], [3, 6]]
As for how you could fix your current code:
Z = []
for i in range(len(A)):
row = []
for j in range(len(A[i])):
row.append(A[i][j] + B[i][j])
Z.append(row)
The important parts here being that you cannot just assign to Z[i][j] unless that row/column already exists, so you need to construct each inner list separately and append them to Z. Also the inner loop needs to end at the length of a row, so I changed range(len(A)) to range(len(A[i])).
len(A) = 3 but you matrix have dimension 3x2 so when you try to access A[2][2] (because column is between 0 and len(A)) you are out of bounds.
For column you are using range 0 to len(A) (which is 3). A[i][2] will be out of range, because A[i]'s length is only 2.
Try using column range to end a len(A[i]) instead of len(A):
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A[i])):
result = A[i][column] + B[i][column]
Z[i][j] = (result)
return Z

Categories

Resources