2010-06-30 6 views
2

J'ai un tableau numpy qui ressemble àLe choix d'un échantillon aléatoire de chaque rangée de tableau numpy, à l'exception des nombres négatifs

>>> a 
array([[ 3. , 2. , -1. ], 
     [-1. , 0.1, 3. ], 
     [-1. , 2. , 3.5]]) 

Je voudrais sélectionner une valeur de chaque ligne au hasard, mais je voudrais exclure les -1 valeurs de l'échantillonnage aléatoire.

Ce que je fais est actuellement:

x=[] 
for i in range(a.shape[0]): 
    idx=numpy.where(a[i,:]>0)[0] 
    idxr=random.sample(idx,1)[0] 
    xi=a[i,idxr] 
    x.append(xi) 

et obtenir

>>> x 
[3.0, 3.0, 2.0] 

Cela devient un peu lent pour les grands tableaux et je voudrais savoir s'il existe un moyen de sélectionner conditionnellement au hasard valeurs de la matrice originale a sans traiter individuellement chaque ligne.

+0

Je n'ai aucune expérience avec NumPy, mais je l'aurais deviné générer un nombre aléatoire prendrait plus de temps que d'accéder à la valeur du tableau. Il en va de même pour l'ajout à une liste. Avez-vous profilé votre programme pour vous assurer que vous optimisez la bonne chose? – torak

+0

J'ai profilé le programme et les lignes 'idx' et' idxr' sont les plus lentes, avec un temps presque égal pour chacune. – fideli

+0

Vous attendez-vous toujours à avoir le même nombre de valeurs exclues dans chaque ligne? Si oui, vous pouvez vectoriser le tout et le faire dans deux lignes de code sans boucles python ... –

Répondre

3

Je ne pense vraiment pas que vous trouverez quelque chose dans Numpy qui fasse exactement ce que vous demandez comme emballé, alors j'ai décidé d'offrir quelles optimisations je pourrais penser.

Il y a plusieurs choses qui pourraient ralentir ici. Tout d'abord, numpy.where() est plutôt lent car il doit vérifier chaque valeur du tableau découpé (la tranche est également générée pour chaque ligne), puis générer un tableau de valeurs. La meilleure chose que vous pourriez faire si vous planifiez ce processus encore et encore sur la même matrice serait de trier chaque rangée. Ensuite, vous utiliseriez simplement une recherche binaire pour trouver où commencent les valeurs positives et utilisez simplement un nombre aléatoire pour en sélectionner une valeur. Bien sûr, vous pouvez également stocker les indices où les valeurs positives commencent après les avoir trouvées une fois avec des recherches binaires.

Si vous ne comptez pas répéter ce processus plusieurs fois, je vous recommande d'utiliser Cython pour accélérer la ligne numpy.where. Cython vous permet de ne pas avoir besoin de découper les lignes et d'accélérer le processus global.

Ma dernière suggestion est d'utiliser random.choice plutôt que random.sample à moins que vous faites vraiment un plan sur le choix de la taille des échantillons qui sont plus grandes que 1.

+0

Je vais faire ce processus sur des tableaux similaires mais nouvellement générés plusieurs fois, donc je vais regarder dans Cython. Merci! – fideli

Questions connexes