Afficher le tableau d'objets sous différents dtype

Oct 05 2020

Je voudrais afficher un tableau d'objets avec un dtype qui encapsule des lignes entières :

data = np.array([['a', '1'], ['a', 'z'], ['b', 'a']], dtype=object)
dt = np.dtype([('x', object), ('y', object)])
data.view(dt)

J'obtiens une erreur :

TypeError: Cannot change data-type for object array.

J'ai essayé les solutions de contournement suivantes :

dt2 = np.dtype([('x', np.object, 2)])
data.view()
data.view(np.uint8).view(dt)
data.view(np.void).view(dt)

Tous les cas entraînent la même erreur. Existe-t-il un moyen d'afficher un tableau d'objets avec un dtype différent ?

J'ai également essayé une approche plus générale (c'est pour référence, car elle est fonctionnellement identique à ce qui est montré ci-dessus):

dt = np.dtype(','.join(data.dtype.char * data.shape[1]))
dt2 = np.dtype([('x', data.dtype, data.shape[1])])

Réponses

2 MadPhysicist Oct 05 2020 at 21:40

Il semble que vous pouvez toujours forcer la vue d'un tampon en utilisant np.array:

view = np.array(data, dtype=dt, copy=not data.flags['C_CONTIGUOUS'])

Bien qu'il s'agisse d'une approche rapide et sale, les données sont copiées dans ce cas et dt2ne sont pas appliquées correctement :

>>> print(view.base)
None
>>> np.array(data, dtype=dt2, copy=not data.flags['C_CONTIGUOUS'])
array([[(['a', 'a'],), (['1', '1'],)],
       [(['a', 'a'],), (['z', 'z'],)],
       [(['b', 'b'],), (['a', 'a'],)]], dtype=[('x', 'O', (2,))])

Pour une approche plus correcte (dans certaines circonstances), vous pouvez utiliser le constructeur brutnp.ndarray :

real_view = np.ndarray(data.shape[:1], dtype=dt2, buffer=data)

Cela donne une vue fidèle des données :

>>> real_view
array([(['a', '1'],), (['a', 'z'],), (['b', 'a'],)], dtype=[('x', 'O', (2,))])
>>> real_view.base is data
True

Comme indiqué, cela ne fonctionne que lorsque les données ont des lignes C-contiguës.