2009-11-24 11 views
6

Supongamos que crea dos recarrays con el mismo dtype y apilarlas:apilamiento recarrays numpy sin perder su recarrayness

>>> 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)) 

Aunque a y b son recarrays, c no es:

>>> 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) 
>>> d.foo 
array([     0,  111050731618561,     0, 
        7718048, 8246760947200437872]) 

que pueda obviamente, conviértalo de nuevo en una recarray, como se muestra en d arriba, pero eso no es conveniente. ¿Hay alguna razón por la que apilar dos recarrays no produzca otra recarray?

Respuesta

6

No lo sé. Lo más probable es que sea un error/característica que nunca se haya implementado. numpy.hstack es básicamente un contenedor alrededor de una función en numpy.core.fromnumeric. Numeric es uno de los dos predecesores de numpy. La mayoría de las funciones en numpy tienen una convención para generar el mismo tipo que la entrada llamando al método __array_wrap__ de la entrada en la salida, y la salida resultante debe tener los mismos datos, pero "envuelta" en la nueva clase. Tal vez el concepto de "envoltura" no era numérico, y nunca se agregó a esta función.

Puede utilizar esta técnica para hacer una función inteligente de apilamiento

def hstack2(arrays) : 
    return arrays[0].__array_wrap__(numpy.hstack(arrays)) 

Esto funciona tanto para recarrays y matrices regulares

>>> 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'> 

No estoy seguro de lo que estás planeando, pero Tal vez quiera preguntar en el numpy mailing list si hay una manera mejor que usar el método documentado, pero de doble subrayado, y cuál es su razonamiento para no realizar el envoltorio por sí mismos.

5

otra parte, hay algunas empresas de servicios auxiliares en numpy.lib.recfunctions la que yo me encontré con here. Este módulo tiene funciones tanto para la fusión y apilar 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]) 

Si se quiere añadir columnas adicionales a un recarray, esto se puede hacer usando 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 

(Aunque no es una respuesta a la pregunta, estoy publicando el último ejemplo como referencia)

Cuestiones relacionadas