<div class="gmail_quote">On Mon, Dec 6, 2010 at 12:26 PM, Christopher Barker <span dir="ltr"><<a href="mailto:Chris.Barker@noaa.gov">Chris.Barker@noaa.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

<div class="im">On 12/5/10 7:56 PM, Wai Yip Tung wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
I'm fairly new to numpy and I'm trying to figure out the right way to do<br>
things. Continuing on my question about using recarray as a relation.<br>
</blockquote>
<br></div>
note that recarrays (or structured arrays, AFAIK, the difference is atturube access only -- I don't use recarrays) are far more static than a database table. So you may really want to use a database, or maybe pytables. Or maybe even just stick with lists.<br>


<br>
But if you are keeping things in memory, should be able to do what you want.<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
In [339]: arr = np.array([<br>
     .....:     (1, 2.2, 0.0),<br>
     .....:     (3, 4.5, 0.0)<br>
     .....:     ],<br>
     .....:     dtype=[<br>
     .....:         ('unit',int),<br>
     .....:         ('price',float),<br>
     .....:         ('amount',float),<br>
     .....:     ]<br>
     .....: )<br>
<br>
In [340]: data = arr.view(recarray)<br>
<br>
<br>
One of the most common thing I want to do is to append rows to data.<br>
</blockquote>
<br></div>
numpy arrays do not naturally support appending, as you have discovered.<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
 I<br>
think concatenate() might be the method.<br>
</blockquote>
<br></div>
yes.<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
But I get a problem:<br>
</blockquote>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
In [342]: np.concatenate((data0,[1,9.0,9.0]))<br>
---------------------------------------------------------------------------<br>
TypeError                                 Traceback (most recent call last)<br>
<br>
c:\Python26\Lib\site-packages\numpy\<ipython console>  in<module>()<br>
<br>
TypeError: expected a readable buffer object<br>
</blockquote>
<br></div>
concatenate expects two arrays to be joined. If you pass in something that can easily be turned into an array, it will work, but a tuple can be converted to multiple types of arrays, so it doesn't know what to do. So you need to re-construct the second array:<br>


<br>
a2 = np.array( [(3,5.5, 3)], dtype=dt)<br>
arr = np.concatenate( (arr, a2) )<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
In [343]: data.amount = data.unit * data.price<br>
</blockquote>
<br></div>
yup<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
But sometimes it may require me to add a new column not already exist,<br>
e.g.:<br>
<br>
In [344]: data.discount_price = data.price * 0.9<br>
<br>
<br>
How can I add a new column?<br>
</blockquote>
<br></div>
you can't. what you need to do is create a new array with a new dtype that includes the new field.<br>
<br>
The trick is that numpy only supports homogenous arrays -- evey item is the same data type. So when you could a strut array like above, numpy does not define it as a 2-d table, but rather, a 1-d array, each element of which is a structure.<br>


<br>
so you need to do something like:<br>
<br>
# create a new array<br>
data2 = np.zeros(len(data), dtype=dt2)<br>
<br>
# fill the array:<br>
for field_name in dt.fields.keys():<br>
    data2[field_name] = data[field_name]<br>
<br>
# now some calculations:<br>
data2['discount_price'] = data2['price'] * 0.9<br>
<br>
I don't know of a way to avoid that loop when filling the array.<br>
<br>
Better yet -- anticipate your needs and create the array with all the fields you need in the first place.<br>
<br>
You can see that ndarrays are pretty static -- struct arrays can be useful data storage, but are not very suitable when things are changing much.<br>
<br>
You could write a class that wraps an andarray, and supports what you need better -- it could be a pretty usefull general purpose class, too. I've got one that handle the appending part, but nothing with adding new fields.<br>


<br>
Here's appending with my class:<br>
<br>
data3 = accumulator.accumulator(dtype = dt2)<br>
data3.append((1, 2.2, 0.0, 0.0))<br>
data3.append((3, 4.5, 0.0, 0.0))<br>
data3.append((2, 1.2, 0.0, 0.0))<br>
data3.append((5, 4.2, 0.0, 0.0))<br>
print repr(data3)<br>
<br>
# convert to regular array for calculations:<br>
data3 = np.array(data3)<br>
<br>
# now some calculations:<br>
data3['discount_price'] = data3['price'] * 0.9<br>
<br>
You wouldn't have to convert to a regular array, except that I haven't written the code to support field access yet -- I don't think it would be too hard, though.<br>
<br>
I've enclosed some test code, and my accumulator class, in case you find it useful.<br>
<br>
<br>
<br>
-Chris<br>
<br></blockquote><div><br>numpy.lib.recfunctions has a method for easily adding new columns.  Of course, it really returns a new recarray rather than adding it to an existing recarray.  Appending records to such an array, however is a different story, and you have to do something like you demonstrated above.<br>

<br>Ben Root<br><br></div></div>