2016-04-06 2 views
-1

У меня есть файл CSV со столбцом, который имеет разные диапазоны дат для миллиона записей. Например, у меня есть что-то вроде этого: 2004-2016; 1980-2016; 1991-2006; 2000-2012; 1998 - 2011узнать наиболее часто встречающийся интервал дат из набора изменяющихся интервалов дат в python

Если я хочу узнать диапазон 3, 5 или 7 лет, который наиболее часто встречается во всех этих записях, как это сделать в Python? Не имеет значения, устранено ли несколько записей, но я пытаюсь выяснить, какая 7-часовая частота или 10-летняя частота наиболее распространены для всех диапазонов. Может кто-нибудь помочь?

+0

Как вы загружаете данные? В списке, например '['2004-2016', '1980-2016', ...]'? – Reti43

+1

С чем именно вам нужна помощь? Что вы пробовали, и где вы застреваете? Вы еще писали код? –

ответ

0
  • Parse file; получить 2-элементные кортежи: ((2004, 2016), (1980-2016), ...).
  • Преобразуйте его в различия: (12, 36, ...).
  • Создать Counter объект с этим sequnce и позвонить most_common метод.
-1

Разделите свою последовательность на отдельные диапазоны. Предполагая, что вы вызываете полученную последовательность diff.

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

Вы можете использовать collections.defaultdict из collections.Counter справиться с этим. defaultdict используется, чтобы сгруппировать диапазоны дат по количеству лет, и Counter отслеживает графами строк диапазона для этого ряда лет:

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})}) 

Если вы хотите знать, наиболее распространенную строку диапазона с год диапазон 12:

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

Не знаю, как вы хотите обрабатывать случаи, когда Есть несколько строк диапазона, представляющих один и тот же диапазон года с эквивалентными пунктами.

+0

@ Reti43: потому что 'eval' опасен для ненадежных данных. Также он медленный, и есть 1 миллион записей. Метод, который я покажу, также имеет то преимущество, что строки диапазона дат нормализуются до подсчета, например, «1998 - 2011» и «1998-2011» считаются одинаковыми. – mhawke

+0

@ Reti43: Как будет выполняться инструкция 'try', чтобы предотвратить выполнение произвольного кода? Если ввод вредоносный, но действительный код, который 'eval()' может выполнить, исключение не может быть поднято. Что, если данные содержат 'os.system ('rm -rf/tmp')' (или хуже)? В общем, неплохо использовать 'eval()'. И это в 4-6 раз медленнее, чем прямая манипуляция строк, которую я показываю. И вам все равно придется нормализовать входные строки, чтобы получить разумные подсчеты. – mhawke

+0

Я не настаиваю на 'eval()'. Вы также отметили, что это быстрее. Однако, предполагая возможность плохого ввода, 'int()' может терпеть неудачу. – Reti43

Смежные вопросы