2016-04-06 4 views
-1

Ich habe eine CSV-Datei mit einer Spalte, die unterschiedliche Datumsbereiche für eine Million Datensätze hat. Zum Beispiel habe ich etwas in der Art: 2004-2016; 1980-2016; 1991-2006; 2000-2012; 1998 - 2011finden Sie das am häufigsten vorkommende Datumsintervall aus einer Reihe von unterschiedlichen Datumsintervallen in Python

Wenn ich herausfinden möchte, welche 3, 5 oder 7 Jahre in all diesen Datensätzen am häufigsten vorkommen, wie soll ich das in Python machen? Es spielt keine Rolle, ob einige Datensätze gelöscht werden, aber ich versuche herauszufinden, welche Häufigkeit von 7 Jahren oder eine Häufigkeit von 10 Jahren für alle Bereiche am häufigsten ist. Kann jemand helfen?

+0

Wie laden Sie die Daten? In einer Liste wie '['2004-2016', '1980-2016', ...]'? – Reti43

+1

Wofür benötigen Sie Hilfe? Was hast du probiert und wo bleibst du stecken? Hast du schon einen Code geschrieben? –

Antwort

0
  • Parse-Datei; Erhalten Sie 2-Element-Tupel: ((2004, 2016), (1980-2016), ...).
  • Transform es zu Unterschieden: (12, 36, ...).
  • Erstellen Sie Counter Objekt mit dieser Sequence und rufen Sie most_common Methode.
-1

Teilen Sie Ihre Sequenz in einzelne Bereiche auf. Angenommen, Sie rufen das resultierende Sequenz-Diff auf.

from collections import Counter 

diff = ["2004-2016", "1980-2016", "1991-2006", "2000-2012", "1998 - 2011"] 

diff_frequency = Counter(map(lambda x: abs(eval(x)), diff)).most_common() 

most_common_diff = diff_frequency[0] 
1

können Sie eine collections.defaultdict von collections.Counter verwenden, um dies zu handhaben. Die defaultdict wird der Gruppe die Datumsbereiche durch die Anzahl von Jahren verwendet, und die Counter verfolgt die Spuren der Grafen von Bereich Strings für die Anzahl der Jahre:

from collections import defaultdict, Counter 

year_ranges = defaultdict(Counter) 

s = '2004-2016; 1980-2016; 1991-2006; 2000-2012; 1998 - 2011; 2004-2016' 
for start, end in [r.split('-') for r in s.split('; ')]: 
    start, end = int(start), int(end) 
    year_ranges[end-start].update(['{}-{}'.format(start, end)]) # update counter for normalised range string 

>>> print(year_ranges) 
defaultdict(<class 'collections.Counter'>, {36: Counter({'1980-2016': 1}), 12: Counter({'2004-2016': 1, '2000-2012': 1}), 13: Counter({'1998-2011': 1}), 15: Counter({'1991-2006': 1})}) 

Wenn Sie die häufigste Bereich Zeichenfolge wissen wollen mit Jahr Bereich von 12:

>>> year_ranges[12].most_common(1) 
[('2004-2016', 2)] 

nicht sicher, wie Sie Fälle behandeln wollen, wo es mehrere Bereich Strings sind im selben Jahr Bereich mit gleichwertigen Zählungen darstellt.

+0

@ Reti43: weil 'eval' auf nicht vertrauenswürdigen Daten gefährlich ist. Auch ist es langsam und es gibt 1 Million Datensätze. Die Methode, die ich zeige, hat auch den Vorteil, dass die Datumsbereichs-Zeichenketten normalisiert werden, bevor sie gezählt werden, z. B. "1998 - 2011" und "1998-2011" werden als gleich angesehen. – mhawke

+0

@ Reti43: Wie wird eine 'try' Anweisung die Ausführung von beliebigem Code verhindern? Wenn die Eingabe bösartig ist, aber gültiger Code, den 'eval()' ausführen kann, kann keine Ausnahme ausgelöst werden. Was ist, wenn die Daten os.system ('rm -rf/tmp') '(oder schlechter) enthalten? Im Allgemeinen ist es eine schlechte Idee, 'eval()' zu verwenden. Und es ist 4-6 mal langsamer als die direkte String-Manipulation, die ich zeige. Und Sie müssen die Eingabe-Strings immer noch normalisieren, um vernünftige Werte zu erhalten. – mhawke

+0

Ich bestehe nicht auf 'eval()'. Sie haben auch darauf hingewiesen, dass es schneller ist. Unter der Annahme einer schlechten Eingabe kann 'int()' jedoch fehlschlagen. – Reti43

Verwandte Themen