[Numpy-tickets] [NumPy] #235: r_, c_, hstack, vstack, column_stack should be made more consistent

NumPy numpy-tickets at scipy.net
Sun Aug 6 23:36:15 CDT 2006


#235: r_, c_, hstack, vstack, column_stack should be made more consistent
-------------------------+--------------------------------------------------
 Reporter:  baxissimo    |       Owner:  somebody
     Type:  enhancement  |      Status:  new     
 Priority:  normal       |   Milestone:          
Component:  numpy.lib    |     Version:  devel   
 Severity:  normal       |    Keywords:          
-------------------------+--------------------------------------------------
 Here's essentially what these different methods do:

 vstack(tup):
    concatenate( map(atleast_2d,tup), axis=0 )

 hstack(tup):
    concatenate( map(atleast_1d,tup),axis=1 )

 column_stack(tup):
    arrays = map( transpose,map(atleast_2d,tup) )
    concatenate(arrays,1)

 (note that column_stack transposes *everything* not just 1-d inputs,
 so it doesn't do quite what I would expect, i.e. only transposing
 1-d inputs)

 The above 3 are pretty much exactly the code used by numpy.  That's
 all there is to those 3 functions.
 For r_ and c_ I'm summarizing, but effectively they do something like:

 r_[args]:
    concatenate( map(atleast_1d,args),axis=0 )

 c_[args]:
    concatenate( map(atleast_1d,args),axis=1 )

 c_ behaves almost exactly like hstack -- with the addition of range
 literals being allowed.

 r_ is most like vstack, but a little different since it effectively
 uses atleast_1d, instead of atleast_2d.  So you have
 {{{
 >>> numpy.vstack((1,2,3,4))
 array([[1],
       [2],
       [3],
       [4]])
 }}}
 but
 {{{
 >>> numpy.r_[1,2,3,4]
 array([1, 2, 3, 4])
 }}}
 However for cases like that with just 0-d or 1-d inputs, c_ behaves
 identically to r_, so if you wanted to get a 1-d output you could have
 just used c_.


 I think the right thing to do would be to make r_ behave more like vstack.
 That would make things more consistent, and make for less for the user to
 remember.

 After making that change, to make things even more consistent, it
 might make sense to rename r_ and c_  to v_ and h_ instead.  Then it's
 easy to remember  'v_' is like 'vstack',  'h_' is like hstack.

 Furthermore, I propose that column_stack should only transpose its 1d
 inputs.  "Stack colums" defnitely doesn't imply to me that something
 that already has columns will be transposed.  Currently it is
 documented to only work on 1d inputs, so hopefully that's a change
 that wouldn't affect too many people.  The function in
 numpy/lib/shape_base.py could be replaced with this:
 {{{
 def column_stack(tup):
    def transpose_1d(array):
         if array.ndim<2: return _nx.transpose(atleast_2d(array))
         else: return array
    arrays = map(transpose_1d,map(atleast_1d,tup))
    return _nx.concatenate(arrays,1)
 }}}

 If r_, and c_ get renamed to v_, h_, then c_ could be re-introduced
 with behavior similar to column_stack.


 SUMMARY:
  * make r_ behave like "vstack plus range literals"
  * make column_stack only transpose its 1d inputs.
  * rename r_,c_ to v_,h_ (or something else) to make their connection with
 vstack and hstack clearer.  Maybe vs_ and hs_ would be better?
  * make a new vertsion of 'c_' that acts like column_stack so that there's
 a nice parallel v_<=>vstack,  h_<=>hstack, c_<=>column_stack

-- 
Ticket URL: <http://projects.scipy.org/scipy/numpy/ticket/235>
NumPy <http://projects.scipy.org/scipy/numpy>
The fundamental package needed for scientific computing with Python.


More information about the Numpy-tickets mailing list