Stacking numpy recarrays without losing their recarrayness
Suppose I make two recarrays with the same dtype and stack them:
>>> import numpy as np
>>> dt = [('foo', int), ('bar', float)]
>>> a = np.empty(2, dtype=dt).view(np.recarray)
>>> b = np.empty(3, dtype=dt).view(np.recarray)
>>> c = np.hstack((a,b))
Although a
and b
are recarrays, c
is not:
>>> c.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'numpy.ndarray' object has no attribute 'foo'
>>> d = c.view(np.recarray)
>>&开发者_StackOverflowgt; d.foo
array([ 0, 111050731618561, 0,
7718048, 8246760947200437872])
I can obviously turn it into a recarray again, as shown with d
above, but that is inconvenient. Is there a reason why stacking two recarrays does not produce another recarray?
Alternatively, there are some helper utilities in numpy.lib.recfunctions
which I stumbled across here. This module has functions for both merging and stacking recarrays
:
from numpy.lib.recfunctions import stack_arrays
c = stack_arrays((a, b), asrecarray=True, usemask=False)
c.foo
>>> array([ 140239282560000, 4376479720, -4611686018427387904,
4358733828, 4365061216])
If one wants to add extra columns to a recarray
, this can be done using merge_arrays
:
import numpy as np
from numpy.lib.recfunctions import merge_arrays
dt1 = [('foo', int), ('bar', float)]
dt2 = [('foobar', int), ('barfoo', float)]
aa = np.empty(6, dtype=dt1).view(np.recarray)
bb = np.empty(6, dtype=dt2).view(np.recarray)
cc = merge_arrays((aa, bb), asrecarray=True, flatten=True)
type(cc)
>>> numpy.core.records.recarray
(Although not an answer to the question, I'm posting the latter example as a reference)
I don't know. Most likely it's a bug/feature that's never been implemented. numpy.hstack
is basically a wrapper around a function in numpy.core.fromnumeric
. Numeric is one of the two predecessors of numpy. Most functions in numpy have a convention to output the same type as the input by calling the method __array_wrap__
of the input on the output, and the resulting output is should have the same data, but "wrapped" in the new class. Perhaps the concept of "wrapping" was not in numeric, andnever got added to this function.
You can use this technique to make a smarter stacking function
def hstack2(arrays) :
return arrays[0].__array_wrap__(numpy.hstack(arrays))
This works for both recarrays and regular arrays
>>> f = hstack2((a,b))
>>> type(f)
<class 'numpy.core.records.recarray'>
>>> f.foo
array([ 140633760262784, 111050731618561, 140633760262800,
7536928, 8391166428122670177])
>>> x = numpy.random.rand(3)
>>> y = numpy.random.rand(2)
>>> z = hstack2((x,y))
>>> type(z)
<type 'numpy.ndarray'>
I'm not sure what you're planning, but you might want to ask on the numpy mailing list is there's a better way than using the documented, but double-underscored method, and what their reasoning is for not doing the wrapping themselves.
Incidentally, you can also use:
c = np.concatenate((a,b))
or
c = np.r_[a, b]
( Source: this mailing list message )
精彩评论