Zip list of list in python [duplicate] - python

This question already has answers here:
Transpose list of lists
(14 answers)
Closed 4 years ago.
I'm trying to create a matrix transpose function in Python. A matrix is a two dimensional array, represented as a list of lists of integers. For example, the following is a 2X3 matrix (meaning the height of the matrix is 2 and the width is 3):
A=[[1, 2, 3],
[4, 5, 6]]
To be transposed the jth item in the ith index should become the ith item in the jth index. Here's how the above sample would look transposed:
>>> transpose([[1, 2, 3],
[4, 5, 6]])
[[1, 4],
[2, 5],
[3, 6]]
>>> transpose([[1, 2],
[3, 4]])
[[1, 3],
[2, 4]]
How can I do this?

You can use zip with * to get transpose of a matrix:
>>> A = [[ 1, 2, 3],[ 4, 5, 6]]
>>> zip(*A)
[(1, 4), (2, 5), (3, 6)]
>>> lis = [[1,2,3],
... [4,5,6],
... [7,8,9]]
>>> zip(*lis)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
If you want the returned list to be a list of lists:
>>> [list(x) for x in zip(*lis)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
#or
>>> map(list, zip(*lis))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Is there a prize for being lazy and using the transpose function of NumPy arrays? ;)
import numpy as np
a = np.array([(1,2,3), (4,5,6)])
b = a.transpose()

If we wanted to return the same matrix we would write:
return [[ m[row][col] for col in range(0,width) ] for row in range(0,height) ]
What this does is it iterates over a matrix m by going through each row and returning each element in each column.
So the order would be like:
[[1,2,3],
[4,5,6],
[7,8,9]]
Now for question 3, we instead want to go column by column, returning each element in each row.
So the order would be like:
[[1,4,7],
[2,5,8],
[3,6,9]]
Therefore just switch the order in which we iterate:
return [[ m[row][col] for row in range(0,height) ] for col in range(0,width) ]

Related

Create a 2-D numpy array with list comprehension

I need to create a 2-D numpy array using only list comprehension, but it has to follow the following format:
[[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]]]
So far, all I've managed to figure out is:
two_d_array = np.array([[x+1 for x in range(3)] for y in range(5)])
Giving:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
Just not very sure how to change the incrementation. Any help would be appreciated, thanks!
EDIT: Accidentally left out [3, 4, 5] in example. Included it now.
Here's a quick one-liner that will do the job:
np.array([np.arange(i, i+3) for i in range(1, 6)])
Where 3 is the number of columns, or elements in each array, and 6 is the number of iterations to perform - or in this case, the number of arrays to create; which is why there are 5 arrays in the output.
Output:
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
Change the code, something like this can work:
two_d_array = np.array([[(y*3)+x+1 for x in range(3)] for y in range(5)])
>>> [[1,2,3],[4,5,6],...]
two_d_array = np.array([[y+x+1 for x in range(3)] for y in range(5)])
>>> [[1,2,3],[2,3,4],...]
You've got a couple of good comprehension answers, so here are a couple of numpy solutions.
Simple addition:
np.arange(1, 6)[:, None] + np.arange(3)
Crazy stride tricks:
base = np.arange(1, 8)
np.lib.stride_tricks.as_strided(base, shape=(5, 3), strides=base.strides * 2).copy()
Reshaped cumulative sum:
base = np.ones(15)
base[3::3] = -1
np.cumsum(base).reshape(5, 3)

pythonic way to flip a list/tuple [duplicate]

This question already has answers here:
Transpose list of lists
(14 answers)
Closed 5 years ago.
What is the most python way to "flip" a list/tuple.
What I mean by flip is: If a you have a tuple of tuples that you can use with syntax like tuple[a][b], "flip" it so that you can do tuple[b][a] to get the same item.
An Example:
t = [
[1, 2, 3]
[4, 5, 6]
]
flipped(t) = [
[1, 4]
[2, 5]
[3, 6]
]
zip would be it; With zip, you take elements column by column(if you have a matrix) which will flip/transpose it:
list(zip(*t))
# [(1, 4), (2, 5), (3, 6)]
It is called transpose.
>>> t = [
... [1, 2, 3],
... [4, 5, 6]
... ]
>>> zip(*t)
[(1, 4), (2, 5), (3, 6)]
>>> map(list, zip(*t))
[[1, 4], [2, 5], [3, 6]]
If t were instead a NumPy array, they have a property T that returns the transpose:
>>> import numpy as np
>>> np.array(t)
array([[1, 2, 3],
[4, 5, 6]])
>>> np.array(t).T
array([[1, 4],
[2, 5],
[3, 6]])

Access matrix by list of matrix indices in Numpy

I have a list of matrix indices and want to access a matrix by these indices.
Example:
indices = [(2, 0), (2, 1), (2, 2)]
mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
mat[indices] = 0
This should result in [[1, 2, 3], [4, 5, 6], [0, 0, 0]], but unfortunately I always get "list indices must be integers, not list".
EDIT
As user2357112 suggests in his comment I tried the following now:
mat = numpy.array(mat)
indices = numpy.array(indices)
mat[indices] = 0
But unfortunately the whole matrix is filled with 0 now.
indices is a regular list of tuples and can't be used to get an element of your regular mat. What you can do is iterate over your list to get your indices:
for x, y in indices:
mat[x][y] = 0
If you want to use numpy methods, you need to create a numpy array. Indeed, np.array structure allows to use tuple to access to an element:
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
for item in indices:
mat[item] = 0
You can use zip(*indices) to access a numpy array by
an indices list:
import numpy as np
indices = [(2, 0), (2, 1), (2, 2)]
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>> mat[zip(*indices)]
array([7, 8, 9])
>> mat[zip(*indices)] = 0
>> mat
array([[1, 2, 3],
[4, 5, 6],
[0, 0, 0]])

Transpose this matrix(python3) [duplicate]

This question already has answers here:
Matrix Transpose in Python [duplicate]
(19 answers)
Closed 8 years ago.
I am trying to find a way to transpose a matrix, for example for:
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
it would change the matrix to:
[[1, 4, 7],
[2, 5, 8],
[3, 6, 9]]
So far, I tried several things but it never worked. I tried:
def transpose_matrix(matrix): # this one doesn't change the matrix at all
zip(*matrix)
return matrix
or
def transpose_matrix(matrix):
map(list, zip(*matrix))
return matrix
or
def transpose_matrix(matrix): # this one returns an empty list []
print(list(zip(*matrix)))
I want to code it without using external library such as numpy.
After that, it returns the result to this menu and use the transposed matrix for upcoming option (not shown):
def menu(matrix):
print('choose option')
loop = True
while loop:
print('''
1-display matrix
7-transpose it
8-other option
0-back
''')
choi = input('cchoice:')
if choi =='1':
print('\n'.join([' '.join(map(str, row)) for row in matrix]))
elif choix == '7':
matrix = transpose_matrix(matrix)
else:
print('invalid choice')
You aren't actually assigning the result of your manipulations, and therefore return the original matrix unchanged. For example:
def transpose_matrix(matrix):
zip(*matrix) # ignore result of computation
return matrix # return argument unchanged
Instead, try:
def transpose_matrix(matrix):
matrix = list(map(list, zip(*matrix))) # assign result
return matrix # return transposed matrix
or simply:
def transpose_matrix(matrix):
return list(map(list, zip(*matrix)))
Bear in mind that you will need to assign the return from the function in the calling function, too:
matrix = transpose_matrix(matrix)
In-place modification
Alternatively, you could transpose in-place and implicitly return None:
def transpose_matrix(matrix):
matrix[:] = list(map(list, zip(*matrix)))
This way you don't have to assign back to matrix when you call the function.
Examples
Examples of the functions in action:
>>> def transpose_matrix(matrix):
return list(map(list, zip(*matrix)))
>>> transpose_matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> def in_place_transpose(matrix):
matrix[:] = list(map(list, zip(*matrix)))
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> in_place_transpose(m)
>>> m
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
zip behaviour
It is important to note that zip will truncate its output to the shortest argument iterable, e.g.:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8]
>>> d = [9]
>>> e = []
>>> for l in (b, c, d, e):
print(list(zip(a, l)))
[(1, 4), (2, 5), (3, 6)]
[(1, 7), (2, 8)]
[(1, 9)]
[]
Therefore if any of the rows of your matrix are empty lists, your output will be an empty list. You can use zip_longest from itertools to insert dummy fillvalues (None by default) instead:
>>> from itertools import zip_longest
>>> list(zip_longest([1, 2, 3], [4, 5]))
[(1, 4), (2, 5), (3, None)]
>>> m = [[1, 2, 3], [4, 5, 6], []]
>>> list(zip_longest(*m, fillvalue=0))
[(1, 4, 0), (2, 5, 0), (3, 6, 0)]
You could implement this as:
def transpose_matrix(matrix):
return list(map(list, zip_longest(*matrix, fillvalue=0)))
with from itertools import zip_longest at the top of your script.
There are some problems with the solutions you tried:
def transpose_matrix(matrix):
zip(*matrix)
return matrix
The result from zip(…) is thrown away, and you return the original matrix instead. Write return zip(*matrix).
def transpose_matrix(matrix):
map(list, zip(*matrix))
return matrix
Same as above, the result from map(…) is thrown away. Write return map(list, zip(*matrix)) instead.
def transpose_matrix(matrix):
print(list(zip(*m)))
The argument is named matrix, but you are working on m. So either rename the parameter m, or change the zipped value to *matrix.
Examples:
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*m))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> list(map(list, zip(*m)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

How to transpose a matrix in python without zip [duplicate]

This question already has answers here:
Matrix Transpose in Python [duplicate]
(19 answers)
Closed 9 years ago.
I was wondering how you could change the user input in python into a list, or better yet, a matrix, just as you would convert it to an integer by using int(input).
>>> L = [[1,2,3], [4,5,6], [7,8,9]]
>>> [[x[i] for x in L] for i in range(len(L[0]))]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
or
>>> zip(*L)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
or
>>> import numpy as np
>>> L = np.arange(1, 10).reshape((3, 3))
>>> L
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> L.transpose()
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
array([[1,2,3], [4,5,6], [7,8,9]]).T will do what you want, if you're using numpy.
list comprehensions should fit the bill quite nicely. Here's the general function:
def transpose(the_array):
return [[the_array[j][i] for j in range(0, len(the_array[i]))] for i in range(0, len(the_array))]

Categories