2016-04-11 7 views
1

Ich möchte n Proben (ohne Ersatz) aus dem Produkt von zwei Listen erhalten. Wie unten gezeigt, berechne ich momentan das gesamte Produkt und entwerfe dann daraus, aber dies wird für lange Listen rechenintensiv. Gibt es eine Möglichkeit, diesen Prozess zu optimieren? Das heißt, dass nicht das gesamte Produkt berechnet werden muss, sondern eine effektivere Probenahme erforderlich ist.Schnellste Möglichkeit, aus Produkt von zwei Listen zu probieren

Aktuelle naiver Ansatz (fälschlicherweise mit Ersatz Abtasten, wie weiter unten angegeben):

from itertools import product 
from random import choice 

def get_sample(a,b,n): 
"""return n samples from the product a and b""" 
    D = list(product(a,b)) 
    D = [choice(D) for _ in range(n)] 

    return D 
+1

Sie haben eine Probe mit Ersatz geschrieben - das heißt, der Code kann zweimal das gleiche Element auswählen. Ist das Absicht? 'random.sample' ist eine Probe ohne Ersatz. – user2357112

+2

Es sei denn, es gibt etwas, das Ihr Code tun soll, aber gerade nicht tut, das ist das gleiche wie das Sampling von 'a' und das Sampling von' b' 'n'. Im Moment besteht keine Notwendigkeit, 'D' zu materialisieren. – DSM

+0

Bei Ersatz: Das ist ein wirklich guter Punkt. Entschuldigung, ich wollte ohne Ersatz probieren. @DSM: Das ist eigentlich eine sehr gute Idee und scheint im Einklang zu sein, was andere vorschlagen – Unayko

Antwort

1

Sie sollte in Ordnung sein, wenn man nur wirklich nicht Verwendung list wenn Sie nicht wollen eine list; eine nicht-Stichprobe kann nun durch

from itertools import product 

def get_first_n_sample(a,b,n): 
"""return n samples from the product a and b""" 
    D = product(a,b) 
    D = [D.next() for _ in range(n)] ## if you're on Python2, use xrange! 
    return D 

gefunden werden, wenn Sie nur Stichproben aus einigen Kombinationen von a und b wollen, ist ein Iterator eindeutig nicht der richtige Ansatz, und daher itertools nicht, entweder . Unter der Annahme, a und b sind schnell auf Direktzugriff (zB list s, tuple e):

from random import choice 

def get_random_sample(a, b): 
    return (choice(a), choice(b)) 

bekommen neinzigartige Proben ist komplizierter, aber:

from random import sample 

def get_random_samples(a, b, n): 
    n_prod = len(a) * len(b) 
    indices = sample(range(n_prod), n) 
    return [(a[idx % len(a)], b[idx // len(a)]) for idx in indices] 
+0

Das '/' anstelle von '//' verursacht Probleme in 3. – DSM

+0

@DSM stimmt. wird behoben –

+0

Das ist nett. Sollte nicht _a, b = a * n, b * n_ vor n_prod? Andernfalls, wenn das Element _a [i] _ einmal abgetastet wird, kann es nicht erneut abgetastet werden. Im Gegensatz dazu würde ich, wenn ich das Produkt der Listen berechne, _n_ Paare haben, wobei _a [i] _ das erste Element ist (umgekehrt für alle _b [i] _). Oder fehlt mir etwas? – Unayko

-1

Leider kann man nicht eine zufällige Stichprobe aus einem Iterator nehmen. Ein Iterator (wie product) bedeutet, dass Sie immer nur einen Wert kennen und mehr als einen Wert kennen müssen, um eine Zufälligkeit zu erzielen.

Der naive Ansatz kann effizienter sein, wenn auch mit random.sample() etwa so:

from itertools import product 
import random 
def get_sample(a,b,n): 
"""return n samples from the product a and b""" 
    D = list(product(a,b)) 
    return random.sample(D, n) 
0

Wenn Sie eine Probe wollen mit Ersatz, wie Ihr Code es derzeit tut, können Sie zufällige Elemente von product(a, b) mit (choice(a), choice(b):

nehmen

Wenn Sie eine Probe ohne Ersatz wollen, um eine Probe von Zufallsindexpaare machen:

sample = [(a[i // len(b)], b[i % len(b)]) 
      for i in random.sample(xrange(len(a)*len(b)), n)] 
Verwandte Themen