étant donné un tableau d'entiers comme
[1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5]
J'ai besoin de masquer des éléments qui se répètent plus de N
fois. Pour clarifier: l'objectif principal est de récupérer le tableau de masques booléens, pour l'utiliser plus tard pour les calculs de binning.
J'ai trouvé une solution assez compliquée
import numpy as np
bins = np.array([1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5])
N = 3
splits = np.split(bins, np.where(np.diff(bins) != 0)[0]+1)
mask = []
for s in splits:
if s.shape[0] <= N:
mask.append(np.ones(s.shape[0]).astype(np.bool_))
else:
mask.append(np.append(np.ones(N), np.zeros(s.shape[0]-N)).astype(np.bool_))
mask = np.concatenate(mask)
donner par exemple
bins[mask]
Out[90]: array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
Existe-t-il une meilleure façon de procéder?
EDIT, # 2
Merci beaucoup pour les réponses! Voici une version mince de l'intrigue de référence de MSeifert. Merci de m'avoir indiqué simple_benchmark
. N'afficher que les 4 options les plus rapides:
Conclusion
L'idée proposée par Florian H , modifiée par Paul Panzer semble être un excellent moyen de résoudre ce problème car elle est assez simple et directe numpy
. numba
Cependant, si vous êtes satisfait de l' utilisation , la solution de MSeifert surpasse l'autre.
J'ai choisi d'accepter la réponse de MSeifert comme solution car c'est la réponse la plus générale: elle gère correctement les tableaux arbitraires avec des blocs (non uniques) d'éléments répétitifs consécutifs. En cas numba
est un non- droit , la réponse de Divakar vaut également le coup d'oeil!
Réponses:
Je veux présenter une solution utilisant numba qui devrait être assez facile à comprendre. Je suppose que vous voulez "masquer" les éléments répétitifs consécutifs:
Par exemple:
Performance:
Utilisation
simple_benchmark
- mais je n'ai pas inclus toutes les approches. C'est une échelle log-log:Il semble que la solution numba ne puisse pas battre la solution de Paul Panzer qui semble être un peu plus rapide pour les grands tableaux (et ne nécessite pas de dépendance supplémentaire).
Cependant, les deux semblent surpasser les autres solutions, mais ils renvoient un masque au lieu du tableau "filtré".
la source
out
argument (ou peut-être la forme fonctionnelle de l'opérateur), donc je n'ai pas pu enregistrer cette copie. Btw j'aime biensimple_benchmark
.simple_benchmark
! merci pour cela et merci bien sûr pour la réponse. Étant donné que j'utilise égalementnumba
d'autres choses, je suis également enclin à l'utiliser ici et à en faire la solution. entre un rocher et un endroit dur là-bas ...Avertissement: ceci est juste une implémentation plus solide de l'idée de @ FlorianH:
Pour les baies plus grandes, cela fait une énorme différence:
la source
[1,1,1,1,2,2,1,1,2,2]
.Approche n ° 1: voici une méthode vectorisée -
Exemple d'exécution -
Approche n ° 2: version un peu plus compacte -
Approche n ° 3: utiliser les comptes groupés et
np.repeat
(ne nous donnera pas le masque) -Approche n ° 4: avec une
view-based
méthode -Approche # 5: Avec une
view-based
méthode sans indices deflatnonzero
-la source
Vous pouvez le faire avec l'indexation. Pour tout N, le code serait:
production:
la source
timeit
runs.Une manière beaucoup plus agréable serait d'utiliser
numpy
la fonctionunique()
-s. Vous obtiendrez des entrées uniques dans votre tableau et également le nombre de fois qu'elles apparaissent:production:
la source
Vous pouvez utiliser une boucle while qui vérifie si l'élément de tableau N positions en arrière est égal à celui en cours. Notez que cette solution suppose que la baie est ordonnée.
la source
len(question)
pourlen(bins)
Vous pouvez utiliser grouby pour regrouper les éléments communs et liste de filtres qui sont plus longs que N .
la source
Solution
Vous pourriez utiliser
numpy.unique
. La variablefinal_mask
peut être utilisée pour extraire les éléments tragiques du tableaubins
.Sortie :
la source
bins
, non?final_values
directement, vous pouvez décommenter la ligne ne commenté dans la solution et dans ce cas , vous pourriez jeter trois lignes:mask = ...
,final_mask = ...
etbins[final_mask]
.