Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #83361 > unrolled thread

Can numpy do better than this?

Started byRustom Mody <rustompmody@gmail.com>
First post2015-01-08 09:56 -0800
Last post2015-01-11 04:12 +0000
Articles 7 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Can numpy do better than this? Rustom Mody <rustompmody@gmail.com> - 2015-01-08 09:56 -0800
    Re: Can numpy do better than this? Ian Kelly <ian.g.kelly@gmail.com> - 2015-01-08 12:27 -0700
      Re: Can numpy do better than this? Rustom Mody <rustompmody@gmail.com> - 2015-01-08 17:13 -0800
        Re: Can numpy do better than this? Rustom Mody <rustompmody@gmail.com> - 2015-01-08 17:19 -0800
        Re: Can numpy do better than this? Ian Kelly <ian.g.kelly@gmail.com> - 2015-01-08 18:36 -0700
          Re: Can numpy do better than this? Rustom Mody <rustompmody@gmail.com> - 2015-01-08 17:45 -0800
    Re: Can numpy do better than this? Nobody <nobody@nowhere.invalid> - 2015-01-11 04:12 +0000

#83361 — Can numpy do better than this?

FromRustom Mody <rustompmody@gmail.com>
Date2015-01-08 09:56 -0800
SubjectCan numpy do better than this?
Message-ID<71ecb9ec-5d8c-4503-a75b-1d4aeca79b08@googlegroups.com>
Given a matrix I want to shift the 1st column 0 (ie leave as is)
2nd by one place, 3rd by 2 places etc.

This code works.
But I wonder if numpy can do it shorter and simpler.

---------------------
def transpose(mat):
     return([[l[i] for l in mat]for i in range(0,len(mat[0]))])
def rotate(mat):
     return([mat[i][i:]+mat[i][:i] for i in range(0, len(mat))])
def shiftcols(mat):
    return ( transpose(rotate(transpose(mat))))

>>> mat = [[1,2,3,4,5,6],
        [7,8,9,10,11,12],
        [13,14,15,16,17,18],
        [19,20,21,22,23,24],
        [25,26,27,28,29,30],
        [31,32,33,34,35,36],
        [37,38,39,40,41,42]]

>>> shiftcols(mat)

[[1, 8, 15, 22, 29, 36],
[7, 14, 21, 28, 35, 42], 
[13, 20, 27, 34, 41, 6], 
[19, 26, 33, 40, 5, 12], 
[25, 32, 39, 4, 11, 18], 
[31, 38, 3, 10, 17, 24], 
[37, 2, 9, 16, 23, 30]]


I was hoping for something like the following APL operator

>>>   mat
 1  2  3  4  5  6
 7  8  9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
>>>   0 1 2 3 4 5 ⊖ mat
 1  8 15 22 29 36
 7 14 21 28 35  6
13 20 27 34  5 12
19 26 33  4 11 18
25 32  3 10 17 24
31  2  9 16 23 30

[toc] | [next] | [standalone]


#83365

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-01-08 12:27 -0700
Message-ID<mailman.17484.1420745315.18130.python-list@python.org>
In reply to#83361
On Thu, Jan 8, 2015 at 10:56 AM, Rustom Mody <rustompmody@gmail.com> wrote:
> Given a matrix I want to shift the 1st column 0 (ie leave as is)
> 2nd by one place, 3rd by 2 places etc.
>
> This code works.
> But I wonder if numpy can do it shorter and simpler.
>
> ---------------------
> def transpose(mat):
>      return([[l[i] for l in mat]for i in range(0,len(mat[0]))])
> def rotate(mat):
>      return([mat[i][i:]+mat[i][:i] for i in range(0, len(mat))])
> def shiftcols(mat):
>     return ( transpose(rotate(transpose(mat))))

Without using numpy, your transpose function could be:

def transpose(mat):
    return list(zip(*mat))

numpy provides the roll function, but it doesn't allow for a varying
shift per index. I don't see a way to do it other than to roll each
column separately:

>>> mat = np.array([[1,2,3,4,5,6],
...         [7,8,9,10,11,12],
...         [13,14,15,16,17,18],
...         [19,20,21,22,23,24],
...         [25,26,27,28,29,30],
...         [31,32,33,34,35,36],
...         [37,38,39,40,41,42]])
>>> res = np.empty_like(mat)
>>> for i in range(mat.shape[1]):
...     res[:,i] = np.roll(mat[:,i], -i, 0)
...
>>> res
array([[ 1,  8, 15, 22, 29, 36],
       [ 7, 14, 21, 28, 35, 42],
       [13, 20, 27, 34, 41,  6],
       [19, 26, 33, 40,  5, 12],
       [25, 32, 39,  4, 11, 18],
       [31, 38,  3, 10, 17, 24],
       [37,  2,  9, 16, 23, 30]])

[toc] | [prev] | [next] | [standalone]


#83380

FromRustom Mody <rustompmody@gmail.com>
Date2015-01-08 17:13 -0800
Message-ID<719d2a22-6c41-467c-a046-0a53704953c6@googlegroups.com>
In reply to#83365
On Friday, January 9, 2015 at 12:58:52 AM UTC+5:30, Ian wrote:
> On Thu, Jan 8, 2015 at 10:56 AM, Rustom Mody wrote:
> > Given a matrix I want to shift the 1st column 0 (ie leave as is)
> > 2nd by one place, 3rd by 2 places etc.
> >
> > This code works.
> > But I wonder if numpy can do it shorter and simpler.
> >
> > ---------------------
> > def transpose(mat):
> >      return([[l[i] for l in mat]for i in range(0,len(mat[0]))])
> > def rotate(mat):
> >      return([mat[i][i:]+mat[i][:i] for i in range(0, len(mat))])
> > def shiftcols(mat):
> >     return ( transpose(rotate(transpose(mat))))
> 
> Without using numpy, your transpose function could be:
> 
> def transpose(mat):
>     return list(zip(*mat))
> 
> numpy provides the roll function, but it doesn't allow for a varying
> shift per index. I don't see a way to do it other than to roll each
> column separately:
> 
> >>> mat = np.array([[1,2,3,4,5,6],
> ...         [7,8,9,10,11,12],
> ...         [13,14,15,16,17,18],
> ...         [19,20,21,22,23,24],
> ...         [25,26,27,28,29,30],
> ...         [31,32,33,34,35,36],
> ...         [37,38,39,40,41,42]])
> >>> res = np.empty_like(mat)
> >>> for i in range(mat.shape[1]):
> ...     res[:,i] = np.roll(mat[:,i], -i, 0)
> ...
> >>> res
> array([[ 1,  8, 15, 22, 29, 36],
>        [ 7, 14, 21, 28, 35, 42],
>        [13, 20, 27, 34, 41,  6],
>        [19, 26, 33, 40,  5, 12],
>        [25, 32, 39,  4, 11, 18],
>        [31, 38,  3, 10, 17, 24],
>        [37,  2,  9, 16, 23, 30]])

Thanks Ian!
With that I came up with the expression

transpose(array([list(roll(mat[:,i],i,0)) for i in range(mat.shape[1])]))

Not exactly pretty.
My hunch is it can be improved??...

[toc] | [prev] | [next] | [standalone]


#83381

FromRustom Mody <rustompmody@gmail.com>
Date2015-01-08 17:19 -0800
Message-ID<2dc64d02-e25b-444e-9406-732884f4d93d@googlegroups.com>
In reply to#83380
On Friday, January 9, 2015 at 6:43:45 AM UTC+5:30, Rustom Mody wrote:
> On Friday, January 9, 2015 at 12:58:52 AM UTC+5:30, Ian wrote:
> > On Thu, Jan 8, 2015 at 10:56 AM, Rustom Mody wrote:
> > > Given a matrix I want to shift the 1st column 0 (ie leave as is)
> > > 2nd by one place, 3rd by 2 places etc.
> > >
> > > This code works.
> > > But I wonder if numpy can do it shorter and simpler.
> > >
> > > ---------------------
> > > def transpose(mat):
> > >      return([[l[i] for l in mat]for i in range(0,len(mat[0]))])
> > > def rotate(mat):
> > >      return([mat[i][i:]+mat[i][:i] for i in range(0, len(mat))])
> > > def shiftcols(mat):
> > >     return ( transpose(rotate(transpose(mat))))
> > 
> > Without using numpy, your transpose function could be:
> > 
> > def transpose(mat):
> >     return list(zip(*mat))
> > 
> > numpy provides the roll function, but it doesn't allow for a varying
> > shift per index. I don't see a way to do it other than to roll each
> > column separately:
> > 
> > >>> mat = np.array([[1,2,3,4,5,6],
> > ...         [7,8,9,10,11,12],
> > ...         [13,14,15,16,17,18],
> > ...         [19,20,21,22,23,24],
> > ...         [25,26,27,28,29,30],
> > ...         [31,32,33,34,35,36],
> > ...         [37,38,39,40,41,42]])
> > >>> res = np.empty_like(mat)
> > >>> for i in range(mat.shape[1]):
> > ...     res[:,i] = np.roll(mat[:,i], -i, 0)
> > ...
> > >>> res
> > array([[ 1,  8, 15, 22, 29, 36],
> >        [ 7, 14, 21, 28, 35, 42],
> >        [13, 20, 27, 34, 41,  6],
> >        [19, 26, 33, 40,  5, 12],
> >        [25, 32, 39,  4, 11, 18],
> >        [31, 38,  3, 10, 17, 24],
> >        [37,  2,  9, 16, 23, 30]])
> 
> Thanks Ian!
> With that I came up with the expression
> 
> transpose(array([list(roll(mat[:,i],i,0)) for i in range(mat.shape[1])]))

That is numpy transpose of course (following a 'from numpy import *')
Not a vanilla (list) transpose

[toc] | [prev] | [next] | [standalone]


#83382

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-01-08 18:36 -0700
Message-ID<mailman.17492.1420767434.18130.python-list@python.org>
In reply to#83380
On Thu, Jan 8, 2015 at 6:13 PM, Rustom Mody <rustompmody@gmail.com> wrote:
> With that I came up with the expression
>
> transpose(array([list(roll(mat[:,i],i,0)) for i in range(mat.shape[1])]))
>
> Not exactly pretty.
> My hunch is it can be improved??...

Hmm, you could use the column_stack constructor to avoid having to
transpose the array.

>>> np.column_stack(np.roll(mat[:,i],i,0) for i in range(mat.shape[1]))
array([[ 1, 38, 33, 28, 23, 18],
       [ 7,  2, 39, 34, 29, 24],
       [13,  8,  3, 40, 35, 30],
       [19, 14,  9,  4, 41, 36],
       [25, 20, 15, 10,  5, 42],
       [31, 26, 21, 16, 11,  6],
       [37, 32, 27, 22, 17, 12]])

[toc] | [prev] | [next] | [standalone]


#83385

FromRustom Mody <rustompmody@gmail.com>
Date2015-01-08 17:45 -0800
Message-ID<852098c1-bba2-41a0-9585-323bf203aba7@googlegroups.com>
In reply to#83382
On Friday, January 9, 2015 at 7:07:26 AM UTC+5:30, Ian wrote:
> On Thu, Jan 8, 2015 at 6:13 PM, Rustom Mody wrote:
> > With that I came up with the expression
> >
> > transpose(array([list(roll(mat[:,i],i,0)) for i in range(mat.shape[1])]))
> >
> > Not exactly pretty.
> > My hunch is it can be improved??...
> 
> Hmm, you could use the column_stack constructor to avoid having to
> transpose the array.
> 
> >>> np.column_stack(np.roll(mat[:,i],i,0) for i in range(mat.shape[1]))
> array([[ 1, 38, 33, 28, 23, 18],
>        [ 7,  2, 39, 34, 29, 24],
>        [13,  8,  3, 40, 35, 30],
>        [19, 14,  9,  4, 41, 36],
>        [25, 20, 15, 10,  5, 42],
>        [31, 26, 21, 16, 11,  6],
>        [37, 32, 27, 22, 17, 12]])

You are my sweetheart!

Removing Javaish-dot-noise:

column_stack(roll(mat[:,i],i,0) for i in range(mat.shape[1]))

[toc] | [prev] | [next] | [standalone]


#83524

FromNobody <nobody@nowhere.invalid>
Date2015-01-11 04:12 +0000
Message-ID<pan.2015.01.11.04.12.53.470000@nowhere.invalid>
In reply to#83361
On Thu, 08 Jan 2015 09:56:50 -0800, Rustom Mody wrote:

> Given a matrix I want to shift the 1st column 0 (ie leave as is) 2nd by
> one place, 3rd by 2 places etc.
> 
> This code works.
> But I wonder if numpy can do it shorter and simpler.

def shiftcols(mat):
    iy,ix = np.indices(mat.shape)
    return mat[(iy+ix)%mat.shape[0],ix]

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web