2015-08-18 1 views
2

Я использую Python для составления списков. Должно быть легко! Я не знаю, почему я так много борюсь с этим.Создание списка на основе списка месяцев в Python

У меня есть некоторые данные, которые я рассчитываю по дате. Существует столбец даты, как это:

Created on 
5/1/2015 
5/1/2015 
6/1/2015 
6/1/2015 
7/1/2015 
8/1/2015 
8/1/2015 
8/1/2015 

В этом случае было бы 2 блоков, созданных в мае, 2 единицы, в июне, 1 Unit в июле и 3 единицы в августе.

Я хочу, чтобы отразить, что в списке, который начинается в апреле ([апрель, май отсчеты подсчитывает, подсчет июня, и т.д ...]):

NumberofUnits = [0, 2, 3, 1, 3, 0, 0, 0, 0, 0, 0, 0] 

У меня есть хороший список месяцев

monthnumbers 

Out[69]: [8, 5, 6, 7] 

У меня также есть список с unitcounts = [2, 3, 1, 3]. Я получил это с помощью value_counts.

Так что это вопрос составления списка нулей и замены деталей списком единиц, верно?

По какой-то причине все мои попытки либо не составляют список, либо составляют список с одним нулем в нем.

NumberofUnits = [0]*12 

for i in range(0,len(monthnumbers)): 
    if **monthnumbers[i] == (i+4):** **This part is wrong**  
     NumberofUnits.append(unitcounts[i]) 
     s = slice(0,i+1) 

Я также попытался

NumberofUnits = [] 
for i in range(0, 12): 
    if len(NumberofUnits) > i: 
     unitcounts[i:]+unitcounts[:i] 
     NumberofUnits.append(unitcounts[i]) 
     s = slice(0,i+1) 
    else: 
     unitcounts.append(0) 

Но это не учитывает тот факт, что в этом раунде мои данные начинается с мая, так что мне нужно ноль в первом слоте.

+0

Есть только две записи с мая. – zero323

ответ

1

Вы можете рассчитывать записи с помощью collections.counter

from collections import Counter 

lines = ['5/1/2015', '5/1/2015', ..., '8/1/2015'] 
month_numbers = [int(line.split("/")[0]) for line in lines] 

cnt = Counter(month_numbers) 

Если у вас уже есть счетчики, вы можете заменить выше

from collections import defaultdict 

cnt = defaultdict(int, zip(monthnumbers, unitcounts)) 

и просто карту для записей с (month_number - смещение) по модулю 12:

[x[1] for x in sorted([((i - offset) % 12, cnt[i]) for i in range(1, 13)])] 
1

Если данные поступают из файла или любого итерационного файла, вы можете использовать OrderedDict, создание ключей в порядке, начиная с 4/april, то увеличивает счетчик на каждый месяц вы столкнулись окончательно распечатать список значений в конце, который будет находиться в требуемом порядке:

from collections import OrderedDict 

od = OrderedDict((i % 12 or 12, 0) for i in range(4, 16)) 
# -> OrderedDict([(4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0), (10, 0), (11, 0), (12, 0), (1, 0), (2, 0), (3, 0)]) 

with open("in.txt") as f: 
    for line in f: 
     mn = int(line.split("/",1)[0]) 
     od.setdefault(mn, 0) 
     od[mn] += 1 

print(list(od.values())) 
[0, 2, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0] 

Если вы не сделаете логику как и выше, связывая данные, когда вы на самом деле разбираете их, тогда будет намного сложнее выяснить, что такое счет за какой месяц. Создание ассоциации сразу - гораздо более простой подход.

Если у вас есть список, кортеж и т.д. .. значений логика точно такая же:

for dte in list_of_dates: 
     mn = int(dte.split("/",1)[0]) 
     od.setdefault(mn, 0) 
     od[mn] += 1 
+0

Спасибо за ваш ответ. Я смущен, хотя, что находится в вашем in.text файле? – jenryb

+0

@jenryb, я просто использовал даты из вашего вопроса, неважно, откуда они пришли из логики, точно так же, просто перебирайте даты и применяйте их. –

+0

Спасибо. Это сработало и вырезало тонны ненужного кода подсчета, который я пытался раньше. – jenryb

1

Почему не просто:

counter = [0]*12 
for m in monthnumbers: 
    counter[(m - 4) % 12] += 1 

print counter 
0

Ниже более «старой школы» подход. Предполагается, что ваши даты находятся в первом столбце вашего файла CSV, то есть cols[0].Он проверяет даты ввода, он вызывает исключение ValueError, если дата недействительна или если она старше последней. Он также справится, если ваш ввод пропускает один или несколько месяцев.

import csv 
from datetime import datetime 

with open("input.csv", "r") as f_input: 
    csv_input = csv.reader(f_input) 
    header = next(csv_input) 
    last_date = datetime(year=2015, month=4, day=1) 
    cur_total = 0 
    units_by_month = [] 

    for cols in csv_input: 
     cur_date = datetime.strptime(cols[0], "%m/%d/%Y") 

     if cur_date.month == last_date.month: 
      cur_total += 1 
     elif cur_date < last_date: 
      raise ValueError, "Date is older" 
     else: 
      extra_months = ((cur_date.month + 12 - last_date.month) if cur_date.year - last_date.year else (cur_date.month - last_date.month)) - 1 
      units_by_month.extend([cur_total] + ([0] * extra_months)) 
      last_date = cur_date 
      cur_total = 1 

    units_by_month.extend([cur_total] + [0] * ((8-len(units_by_month)) if len(units_by_month) < 9 else 0)) 
    print units_by_month 

Так для ввода это даст следующий результат:

[0, 2, 2, 1, 3, 0, 0, 0, 0, 0] 

Если один дополнительный вход был добавлен 3/1/2016, будет отображено следующее:

[0, 2, 2, 1, 3, 0, 0, 0, 0, 0, 0, 1] 
Смежные вопросы