2016-06-13 3 views
0

Ich habe eine Liste von Strings, die etwa 6 Millionen Elemente enthält, und ich versuche, das Auftreten für jeden der eindeutigen Werte zu zählen.Python zählt Vorkommen in einer Liste: Wie man es schneller macht?

Hier ist mein Code:

lines = [6 million strings] 
unique_val = list(set(lines)) # contains around 500k items 

mydict = {} 
for val in unique_val: 
    mydict[val] = lines.count(val) 

ich den obigen Code gefunden habe funktioniert sehr langsam gegeben, dass die Liste Ich zähle riesig.

Ich frage mich, ob es einen Weg gibt, es schneller zu machen?

Vielen Dank

+0

Dies kann groß genug sein für 'pyspark' und es wäre für diese Art von Problem gut geeignet. –

+0

Sind Sie bereit, nicht-pure-python-Pakete (wie numpy oder pyspark?) Zu verwenden. –

+0

Außerdem habe ich Ihren Code so bearbeitet, dass er richtig funktioniert, indem Sie die richtige Klammer verwenden - ich weiß, dass Bearbeitungscode normalerweise verpönt ist (es schien ein sehr offensichtlicher Tippfehler zu sein), aber wenn Sie das Original aus irgendeinem Grund meinten, machen Sie die Änderungen –

Antwort

1

Wenn Sie nicht das collections Modul verwenden.

counts = dict() 
for line in lines: 
    counts[line] = counts.get(line,0) + 1 

Oder wenn Sie nur Counter verwenden möchten nicht

from collection import defaultdict 
counts = defaultdict(int) 
for line in lines: 
    counts[line] += 1 
+0

Hallo Michael, wie funktioniert das erste? Es scheint, dass counts zu nichts initialisiert wird, also sehe ich nicht, wie es aktualisiert wird? (Wenn ich es laufe, scheint es auch nicht zu funktionieren ...). Die "get" -Funktion sucht nach einem Schlüssel und gibt 0 zurück, wenn dieser Schlüssel nicht vorhanden ist, aber da wir niemals irgendwelche Schlüssel hinzufügen, ist das nicht immer 0? –

+0

@de_Knight, :) Es funktioniert offensichtlich nicht. Ich habe am Ende die '+ 1' verpasst. Ich habe es jetzt bearbeitet –

1

Wie wäre es damit,

from collections import defaultdict 
import collections 

lines = [600 million strings] 

d = defaultdict(int) 
for line in lines: 
    for word, count in collections.Counter(line).items(): 
     d[word] += count 
+0

Warum würden Sie dies über DeepSpace tun, wenn das scheint viel prägnanter für das gleiche Ergebnis? (Zugegeben, ich denke nicht, dass er den Ruf haben sollte, in seinen zu setzen) –

+0

@de_Knight, thx für den Hinweis darauf. Ich habe gerade meine Antwort bearbeitet. – SparkAndShine

+0

Hmm ich verstehe immer noch nicht, wie das besser ist als 'd = Counter (Linien)'. Warum schleifen wir, rufen Counter mehrfach und Dictionary-Kopien? Gibt es eine Speicheroptimierung, die du vielleicht machst? –

1

Numpy Lösung

denke ich numpy Sie geben die schnellste Antwort mit unique:

result = dict(zip(*np.unique(lines, return_counts=True))) 

Numpy ist ziemlich stark unter der Haube optimiert. Pro der verlinkten Dokumente, die magischen Kreise um die return_counts Flagge:

return_counts: Bool, optional

Bei True zurückgeben auch die Anzahl der jeweils eindeutigen Wert kommt in ar auf.


Zeit

ich Ihren ursprünglichen Ansatz abgestimmt ist, um den Zähler Ansatz

result = Counter(lines) 

und den numpy Ansatz auf einem Satz erzeugt durch

N = 1000000 
lines = [chr(i%100) for i in range(N) ] 

Obviousl y, dieser Test ist keine gute Abdeckung, aber es ist ein Anfang.

Sie sind Ansatz in 0,584s betrieben; DeepSpace-Zähler in 0,162 (3,5-fache Beschleunigung) und numpy in 0,0861 (7-fache Beschleunigung). Auch dies hängt von vielen Faktoren ab, einschließlich der Art der Daten, die Sie haben: Die Schlussfolgerung kann sein, dass entweder numpy oder ein Counter eine Beschleunigung bietet, mit einem Zähler, der keine externe Bibliothek benötigt

1

Calling list.count ist sehr teuer . Der Wörterbuchzugriff (O (1) amortisierte Zeit) und der Operator in sind jedoch relativ günstig. Der folgende Ausschnitt zeigt eine viel bessere Zeitkomplexität.

def stats(lines): 
    histogram = {} 
    for s in lines: 
     if s in histogram: 
      histogram[s] += 1 
     else: 
      histogram[s] = 1 
    return histogram 
Verwandte Themen