web-dev-qa-db-fra.com

Comment convertir un tableau Numpy 2D avec le type d'objet en un tableau 2D régulier de flotteurs

Dans le cadre du programme plus vaste sur lequel je travaille, je me suis retrouvé avec des tableaux d'objets avec des chaînes, des coordonnées 3D, etc., tous mélangés. Je sais que les tableaux d'objets ne sont peut-être pas très appréciés par rapport aux tableaux structurés, mais j'espère pouvoir contourner ce problème sans changer beaucoup de codes.

Supposons que chaque ligne de mon tableau obj_array (avec N lignes) a le format de 

Single entry/object of obj_array:  ['NAME',[10.0,20.0,30.0],....] 

Maintenant, j'essaie de charger ce tableau d'objets et de découper le bloc de coordonnées 3D. Jusque là, tout fonctionne bien avec simplement demander, disons. 

obj_array[:,[1,2,3]]

Cependant, le résultat est aussi un tableau d'objets et je vais faire face au problème car je veux former un tableau 2D de flottants avec:

size [N,3] of N rows and 3 entries of X,Y,Z coordinates

Pour l'instant, je boucle sur les lignes et assigne chaque ligne à une ligne d'un tableau d'imbrication 2D de destination pour résoudre le problème. Je me demande s’il existe un meilleur moyen d’utiliser les outils de conversion de tableau de numpy? J'ai essayé quelques choses et je ne pouvais pas le contourner.

Centers   = np.zeros([N,3])

for row in range(obj_array.shape[0]):
    Centers[row,:] = obj_array[row,1]

Merci

12
Moe

Petit problème méchant ... Je me suis amusé avec cet exemple de jouet:

>>> arr = np.array([['one', [1, 2, 3]],['two', [4, 5, 6]]], dtype=np.object)
>>> arr
array([['one', [1, 2, 3]],
       ['two', [4, 5, 6]]], dtype=object)

Ma première hypothèse était:

>>> np.array(arr[:, 1])
array([[1, 2, 3], [4, 5, 6]], dtype=object)

Mais cela conserve le type object, alors peut-être alors:

>>> np.array(arr[:, 1], dtype=np.float)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: setting an array element with a sequence.

Vous pouvez normalement contourner ce problème en procédant comme suit:

>>> np.array(arr[:, 1], dtype=[('', np.float)]*3).view(np.float).reshape(-1, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a readable buffer object

Pas ici cependant, ce qui était un peu déroutant. Apparemment, c’est le fait que les objets de votre tableau sont des listes qui jettent ceci au loin, car le remplacement des listes par des nuplets fonctionne:

>>> np.array([Tuple(j) for j in arr[:, 1]],
...          dtype=[('', np.float)]*3).view(np.float).reshape(-1, 3)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

Comme il ne semble pas exister de solution tout à fait satisfaisante, le plus simple est probablement de choisir:

>>> np.array(list(arr[:, 1]), dtype=np.float)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

Bien que cela ne soit pas très efficace, il est probablement préférable d’utiliser quelque chose comme:

>>> np.fromiter((Tuple(j) for j in arr[:, 1]), dtype=[('', np.float)]*3,
...             count=len(arr)).view(np.float).reshape(-1, 3)
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])
10
Jaime

En me basant sur l'exemple de Jaime, je pense que vous pouvez le faire très simplement en utilisant np.vstack():

arr = np.array([['one', [1, 2, 3]],['two', [4, 5, 6]]], dtype=np.object)
float_arr = np.vstack(arr[:, 1]).astype(np.float)

Cela fonctionnera que les éléments "numériques" de votre tableau d'objets soient des tableaux, listes ou n-uplets numD.

4
ali_m

Cela fonctionne très bien sur votre tableau pour convertir un objet en un tableau de flotteurs. Le traitement des numéros est extrêmement facile après. Merci pour ce dernier post !!!! Je viens de le modifier pour inclure n'importe quelle taille de DataFrame:

float_arr = np.vstack(arr[:, :]).astype(np.float)
1
Matt

Vous voudrez peut-être utiliser un tableau structuré pour pouvoir facilement y accéder lorsque vous devez accéder aux noms et aux valeurs indépendamment. Dans cet exemple, il y a deux points de données:

x = zeros(2, dtype=[('name','S10'), ('value','f4',(3,))])
x[0][0]='item1'
x[1][0]='item2'
y1=x['name']
y2=x['value']

le résultat:

>>> y1
array(['item1', 'item2'], 
      dtype='|S10')
>>> y2
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]], dtype=float32)

Voir plus de détails: http://docs.scipy.org/doc/numpy/user/basics.rec.html

1
CT Zhu

Ce problème se produit généralement lorsque vous avez un ensemble de données avec différents types, généralement des dates dans la première colonne ou plus.

Ce que j’utilise, c’est de stocker la colonne de date dans une variable différente; et prenez le reste de la "matrice de fonctionnalités X" dans X. J'ai donc des dates et X, par exemple.

Ensuite, j'applique la conversion à la matrice X en tant que:

X = np.array(list(X[:,:]), dtype=np.float)

J'espère aider!

1
Pablo Ruiz Ruiz

C’est beaucoup plus rapide de convertir simplement votre tableau d’objets en tableau Flatt NumPy: arr=np.array(arr, dtype=[('O', np.float)]).astype(np.float) - à partir de là, pas de boucle, indexez-le comme vous le feriez normalement sur un tableau NumPy. Vous auriez à le faire par morceaux avec vos différents types de données arr[:, 1], arr[:,2], etc. Le même problème avec un objet NumPy Tuple est retourné à partir d'une fonction C++ DLL: la conversion de 17 millions d'éléments prend <2. 

0
Matt