## Monday, August 4, 2008

### Matrix Transposition

As part of my heat map project, I needed to transpose a matrix. I know I could use SciPy or hand-code a method, but I remembered an IAQ (infrequently asked question) from Peter Norvig where he gives this example:

 `m = [(1,2,3), (4,5,6)]zip(*m)# [(1, 4), (2, 5), (3, 6)]`

How does this work? Well, Norvig says that "f(*m) is like apply(f,m)," and I know that apply(f,m) feeds the elements of m to the function f, where in this case f is zip. If we do zip on two lists:

 `L = list('abcde')R = range(len(L))zip(L,R)# [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4)]`

However, feeding the nested list directly to zip does not do what we want:

 `nestedL = [L,R]zip(nestedL)# [(['a', 'b', 'c', 'd', 'e'],), ([0, 1, 2, 3, 4],)]`

But this does:

 `apply(zip, nestedL)# [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4)]`

So the next question is, how does f(*args) turn into apply(f,args)?
 `def f(*T): print type(T),Tf(nestedL)# < type 'tuple'> ([['a', 'b', 'c', 'd', 'e'], [0, 1, 2, 3, 4]],)`

T is a tuple containing nestedL as its first element. Here is where I lose the trail. It makes my head spin. But zip(*m) really is a neat trick to remember.

#### 1 comment:

diffusing thoughts said...

hope this helps you further:

this function accepts any number of arguments:
def rint(*args):
print args

>> rint((1,2,3))
((1, 2, 3),)
it got one argument a tuple (1,2,3)

>> rint(*(1,2,3))
(1, 2, 3)
it got three arguments 1, 2, and 3 the tuple has been unpacked before feeding into rint. An astericks means "unpack".