On Sat, Oct 17, 2009 at 9:13 AM, Loïc BERTHE <berthe.loic@gmail.com> wrote:
  Hi,

I would like to create my own class of record array to deal with units.

Here is the code I used, inspired from
http://docs.scipy.org/doc/numpy-1.3.x/user/basics.subclassing.html#slightly-more-realistic-example-attribute-added-to-existing-array
:


[code]
from numpy import *

class BlocArray(rec.ndarray):
   """ Recarray with units and pretty print """

   fmt_dict = {'S' : '%10s', 'f' : '%10.6G', 'i': '%10d'}

   def __new__(cls, data, titles=None, units=None):

       # guess format for each column
       data2 = []
       for line in zip(*data) :
           try : data2.append(cast[int](line))         # integers
           except ValueError :
               try : data2.append(cast[float](line))   # reals
               except ValueError :
                   data2.append(cast[str](line))       # characters

       # create the array
       dt = dtype(zip(titres, [line.dtype for line in data2]))
       obj = rec.array(data2, dtype=dt).view(cls)

       # add custom attributes
       obj.units = units or []
       obj._fmt = " ".join(obj.fmt_dict[d[1][1]] for d in dt.descr) + '\n'
       obj._head = "%10s "*len(dt.names) % dt.names +'\n'
       obj._head += "%10s "*len(dt.names) % tuple('(%s)' % u for u in
units) +'\n'

       # Finally, we must return the newly created object:
       return obj

titles =  ['Name', 'Nb', 'Price']
units = ['/', '/', 'Eur']
data = [['fish', '1', '12.25'], ['egg', '6', '0.85'], ['TV', 1, '125']]
bloc = BlocArray(data, titles=titles, units=units)

In [544]: bloc
Out[544]:
     Name         Nb      Price
      (/)        (/)      (Eur)
     fish          1      12.25
      egg          6       0.85
       TV          1        125
[/code]

It's almost working, but I have some isues :

  - I can't access data through indexing
In [563]: bloc['Price']
/home/loic/Python/numpy/test.py in <genexpr>((r,))
    50
    51     def __repr__(self):
---> 52         return self._head + ''.join(self._fmt % tuple(r) for r in self)

TypeError: 'numpy.float64' object is not iterable

So I think that overloading the __repr__ method is not that easy

  - I can't access data through attributes now :
In [564]: bloc.Nb
AttributeError: 'BlocArray' object has no attribute 'Nb'

  - I can't use 'T' as field in theses array as the T method is
already here as a shortcut for transpose


Have you any hints to make this work ?



On adding units in general, you might want to contact Darren Dale who has been working in that direction also and has added some infrastructure in svn to make it easier. He also gave a short presentation at scipy2009 on that problem, which has been worked on before. No sense in reinventing the wheel here.

Chuck