2014-04-09 5 views
5

Ich habe eine riesige np.array genannt arr mit N-Werte und 10% dieser Werte wählen zufällig von:Invert die zufällige Auswahl der Schlüssel in einem Array numpy

choice=random.sample(range(N), int(N*percent)) # percent has values 0-1 
newarr=arr[choice] 

N über 2 Millionen Werte sein könnte.

Eigentlich brauche ich auch ein Array mit den anderen 90% der Werte. Also im Moment habe ich die folgende verwenden, die sehr langsam ist:

def buildRevChoice(choice, nevents): 
     revChoice=[] 
     for i in range(N): 
      if not i in choice: 
       revChoice.append(i) 
     return revChoice 

Können Sie sich eine Methode, dies zu zumachen?

+0

Schnelle Optimierung: Erstellen Sie in 'buildRevChoice' ein' set' aus 'choice', um die Suche zu beschleunigen. –

+1

Verwenden Sie keine Python-Schleifen für große Arrays, wenn Sie Leistung benötigen. Verwenden Sie die funktionale Programmierung von Python/Numpy und die Vektorisierung von Numpy. –

+0

Ja, ich weiß, aber ich habe keine andere Lösung per Google gefunden. Konnte nicht an eine vernünftige Suchphrase denken. – user575736

Antwort

6

Sie können nur random.shuffle die Liste, dann teilen Sie es, wie Sie möchten.

Und Sie erhalten Ihre zwei Listen, die erste enthält die ausgewählten und die zweite enthält den Rest.

+2

keine schlechte Lösung; Allerdings bin ich etwas vorsichtig bei der Leistung von random.shuffle. Potenziell hat random.permutation eine bessere Leistung. Und abhängig davon, wie das implementiert wird, kann np.argsort (random.randint()) ein schnellerer Weg sein, um einen Permutationsindex zu generieren. –

+0

@EelcoHoogendoorn Ich habe nicht mit 'numpy' gearbeitet, also ist alles, was ich weiß, das grundlegende Python :) Wäre der O (n) Fisher Yates Shuffle Algorithmus eine gute Wahl für das Mischen? – 0605002

+0

Jeder Algorithmus, den Sie selbst implementieren, ist eine schlechte Wahl, es sei denn, Sie planen eine C-Erweiterung. Beachten Sie, dass ich Shuffle nicht bewertet habe. Ich stelle mir einfach vor, dass der zufälligste In-Place-Shuffle-Algorithmus nicht unbedingt der effizienteste ist. –

2

Wenn Sie mit dem Speicheraufwand eines Maskenarrays zufrieden sind, scheint dies schneller zu sein als die Auswahl der anderen Werte nach Index und behält die Reihenfolge der Elemente in are bei. Hier ist, was ich mit Timings von IPython Notebook bekam:

N = 2000000 
arr = random.random(N) 
percent = 0.10 

Meine Lösung:

%% timeit 
choice = random.choice(N, N*percent) 
mask = zeros_like(arr, bool) 
mask[choice] = True 
newarr = arr[mask] 
revchoice = arr[~mask] 

10 Schlaufen, am besten von 3: 18,1 ms pro Schleife

0605002 Lösung:

tmp = range(N) 
random.shuffle(tmp) 
cut = int(N * percent) 
newarr, revchoice = tmp[:cut], tmp[cut:] 

1 Schleifen, am besten 3: 603 ms pro Schleife

+0

Vielen Dank, das sind zwei sehr gute Lösungen, ich werde prüfen, welche schneller ist. Ich bin nicht an Speicherprobleme gewöhnt. In welchem ​​Fall sollte ich keine Masken verwenden? – user575736

+1

Diese Lösung (und die andere von 0605002) verwendet ein Array, das die gleiche Größe wie 'arr' hat. Wenn Ihr Array also halb so groß wie der verfügbare Speicher ist, haben Sie nicht genug Platz, um die Maske zu erstellen. Wenn Sie vermeiden, die Maske zu erstellen, können Sie mit nur 10% mehr Speicher für das Indexarray auskommen. 2 Millionen Punkte sind nicht so viele. – chthonicdaemon

+1

Ich habe meine Antwort mit Timings aktualisiert. Meine Lösung ist eine Größenordnung schneller. – chthonicdaemon

Verwandte Themen