2009-11-24 7 views
6

Supposons que je fais deux recarrays avec le même DTYPE et empilez:empilage recarrays numpy sans perdre leur 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)) 

Bien que a et b sont recarrays, c n'est pas:

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

je peux évidemment le transformer en un recarray encore, comme montré avec d ci-dessus, mais c'est gênant. Y a-t-il une raison pour laquelle empiler deux recarrays ne produit pas un autre recarray?

Répondre

6

Je ne sais pas. Très probablement, c'est un bug/fonctionnalité qui n'a jamais été implémenté. numpy.hstack est fondamentalement un wrapper autour d'une fonction dans numpy.core.fromnumeric. Numeric est l'un des deux prédécesseurs de numpy. La plupart des fonctions en numpy ont une convention pour sortir le même type que l'entrée en appelant la méthode __array_wrap__ de l'entrée sur la sortie, et la sortie résultante doit avoir les mêmes données, mais "enveloppé" dans la nouvelle classe. Peut-être que le concept de "wrapping" n'était pas en numérique, et n'a jamais été ajouté à cette fonction.

Vous pouvez utiliser cette technique pour faire fonction d'empilage plus intelligent

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

Cela fonctionne aussi bien pour les recarrays et réseaux réguliers

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

Je ne suis pas sûr de ce que vous prévoyez, mais vous pourrait vouloir demander sur le numpy mailing list est il ya une meilleure façon que d'utiliser la méthode documentée, mais à double soulignement, et quel est leur raisonnement pour ne pas faire l'emballage eux-mêmes.

-1

Par ailleurs, vous pouvez également utiliser:

c = np.concatenate((a,b)) 

ou

c = np.r_[a, b] 

(Source: this mailing list message)

+1

Ils ne conservent pas la mémoire non plus. –

5

Sinon, il y a quelques utilitaires d'aide à numpy.lib.recfunctions que je suis tombé sur here. Ce module a des fonctions à la fois la fusion et l'empilage 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 l'on veut ajouter des colonnes supplémentaires à un recarray, cela peut être fait en utilisant 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 

(Bien que pas une réponse à la question, je poste le dernier exemple comme référence)

Questions connexes