[Numpy-discussion] Subclassing record array

Darren Dale dsdale24@gmail....
Sun Oct 18 07:06:52 CDT 2009


On Sun, Oct 18, 2009 at 12:22 AM, Charles R Harris
<charlesr.harris@gmail.com> wrote:
>
>
> 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.

The units package I have been working on is called quantities. It is
available at the python package index, and the project is hosted at
launchpad as python-quantities. If quantities isn't a good fit, please
let me know why. At least the code can provide some example of how to
subclass ndarray.

Darren


More information about the NumPy-Discussion mailing list