12
votes

Utilisation de plusieurs niveaux de masque d'index booléen dans NUMPY

J'ai le code suivant qui sélectionne d'abord des éléments d'une matrice numpue avec un masque d'index logique: xxx pré>

Je souhaite utiliser un deuxième masque booléen contre celui-ci pour choisir des objets avec: P>

masklength = len(grid[mask])
prob = 0.5
# generates an random array of bools
second_mask = np.random.rand(masklength) < prob 

# this fails to act on original object
grid[mask][second_mask] = 100


0 commentaires

4 Réponses :


7
votes

Je crois que ce qui suit fait ce que vous demandez: xxx

Cela fonctionne comme suit:

  • np.where (masque) convertit le masque booléen dans les indices où masque est vrai;
  • [A [second_mask] pour un ...] sousfile les indices pour sélectionner uniquement ceux où second_mask est vrai.

    La raison pour laquelle votre version d'origine ne fonctionne pas est que grille [masque] implique une indexation fantaisie. Cela crée une copie des données, ce qui entraîne à son tour ... [second_mask] = 100 modifiant cette copie plutôt que le tableau d'origine.


5 commentaires

Parfait, ce que je cherchais.


Vous y trouverez également une copie de tableaux impliqués dans l'extrait que vous avez posté?


@Hemmer: Il existe de nouveaux tableaux créés par np.where et A [second_mask] . La taille de ces tableaux dépend du nombre d'éléments vrais dans masque et second_mask et est indépendant de la taille de grille .


J'ai posté une solution alternative que j'ai trouvée au cas où vous seriez intéressé.


Il suffit de combiner des masques par grille [masque et second_mask] .



1
votes

Une autre solution possible que j'ai proposée après avoir pensé à cela un peu plus est que la deuxième carte conserve la taille de la première (qui peut ou non la valeur de la mémoire) et d'ajouter de manière sélective dans les nouveaux éléments:

#!/usr/bin/env python
import numpy as np

prob = 0.5    
grid = np.random.rand(4,4)

mask = grid > 0.5 
masklength = np.sum(mask)

# initialise with false map
second_mask = np.zeros((4,4), dtype=np.bool)
# then selectively add to this map using the second criteria
second_mask[mask] = np.random.rand(masklength) < prob

# this now acts on the original object
grid[second_mask] = 100


0 commentaires

8
votes

Utiliser l'indexation à plat évite une grande partie de la maux de tête:

grid.flat[ind] = 100


0 commentaires

-1
votes
In [29]: ar = linspace(1,10,10)
In [30]: ar[(3<ar)*(ar<8)]
Out[30]: array([ 4.,  5.,  6.,  7.])

0 commentaires