Is there any fast method to make a transposition of a rectangular 2D matrix in Python (non-involving any library import).? Say, if I have an array X=[[1,2,3], [4,5,6]] I need an array Y which should be a transposed version of X, so Y=[[1,4],[2,5],[3,6]].
+8
A:
Simple: Y=zip(*X)
>>> X=[[1,2,3], [4,5,6]]
>>> Y=zip(*X)
>>> Y
[(1, 4), (2, 5), (3, 6)]
EDIT: to answer questions in the comments about what does zip(*X) mean, here is an example from python manual:
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]
So, when X
is [[1,2,3], [4,5,6]]
, zip(*X)
is zip([1,2,3], [4,5,6])
unbeli
2010-05-27 13:54:52
Wow, nice. Great solution.
Xavier Ho
2010-05-27 13:57:13
Very good. Interesting, how it works.
psihodelia
2010-05-27 13:58:05
read more on this in python docs for zip(): http://docs.python.org/library/functions.html
unbeli
2010-05-27 13:58:45
what is a purpose of the asterisk?
psihodelia
2010-05-27 14:05:47
why is it `zip(*X)` instead of `zip(X)`? sorry i'm new to python. i can see zip(X) doesn't work, but i don't understand why
mr popo
2010-05-27 14:06:07
@psihodelia, @mr popo: `*` is the unpacking syntax. See: http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists
Xavier Ho
2010-05-27 14:06:53
zip(*X) means run zip(), taking arguments from list X. zip(*[a,b]) === zip(a,b), zip(*X) for the X above === zip([1,2,3], [4,5,6])
unbeli
2010-05-27 14:07:25
Perfect answer! Thank you.
psihodelia
2010-05-27 14:25:30
+4
A:
>>> X = [1,2,3], [4,5,6]]
>>> zip(*X)
[(1,4), (2,5), (3,6)]
>>> [list(tup) for tup in zip(*X)]
[[1,4], [2,5], [3,6]]
If the inner pairs absolutely need to be lists, go with the second.
yarmiganosca
2010-05-27 13:55:52
@Xavier, Imagining something to be faster isn't how we optimize code. It turns out we guess wrong a lot more of the time than we think. In fact, I don't know for sure, but I suspect from experience the `zip` form will actually be faster for a lot of input, though more memoryhungry. In any event, playing with these two is not the way to improve the performance of this operation.
Mike Graham
2010-05-27 14:17:34
@Mike: Yes, you are correct. But my experience tells me that `range()` is usually slower than `xrange()` in large inputs, because *allocating memory takes time*. While I can't say for sure if the list comprehension has any sort of optimisation, the best follow-up comment I can give is to profile - the only way to find out.
Xavier Ho
2010-05-27 14:20:21
@Mike: In case you're interested, I just did a quick benchmark. `izip()` starts to win when the matrix is around 1000x1000 in size. So, if most of the matrix inputs are less than that in dimensions, `zip()` is wonderful. (Python 2.6.5)
Xavier Ho
2010-05-27 14:26:58
+2
A:
If you're working with matrices, you should almost certainly be using numpy. This will perform numerical operations easier and more efficiently than pure Python code.
>>> x = [[1,2,3], [4,5,6]]
>>> x = numpy.array(x)
>>> x
array([[1, 2, 3],
[4, 5, 6]])
>>> x.T
array([[1, 4],
[2, 5],
[3, 6]])
"non-involving any library import" is a silly, non-productive requirement.
Mike Graham
2010-05-27 14:11:25
All right, was just making sure of your intention. I would use numpy, too. And it would be way faster as well.
Xavier Ho
2010-05-27 14:13:40