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-... : [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 ? -- LB
On Sat, Oct 17, 2009 at 9:13 AM, Loïc BERTHE
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-... :
[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
On Sun, Oct 18, 2009 at 12:22 AM, Charles R Harris
On Sat, Oct 17, 2009 at 9:13 AM, Loïc BERTHE
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-... :
[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
participants (3)
-
Charles R Harris
-
Darren Dale
-
Loïc BERTHE