views:

191

answers:

3

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
Wow, nice. Great solution.
Xavier Ho
Very good. Interesting, how it works.
psihodelia
read more on this in python docs for zip(): http://docs.python.org/library/functions.html
unbeli
what is a purpose of the asterisk?
psihodelia
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
@psihodelia, @mr popo: `*` is the unpacking syntax. See: http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists
Xavier Ho
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
Perfect answer! Thank you.
psihodelia
+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
Consider using `izip()` for the second, it might be faster. :]
Xavier Ho
@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
@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
@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
+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
Shouldn't this be a comment instead of an answer, @Mike?
Xavier Ho
@Xaver, Not IMO.
Mike Graham
All right, was just making sure of your intention. I would use numpy, too. And it would be way faster as well.
Xavier Ho