Использовать счетчик $ count, чтобы получить итоговый результат агрегирования
Запрос:
db.collection.aggregate(
[
{
$match: {
...
}
},
{
$aggregate: {
...
}
},
{
$count: "totalCount"
}
]
)
Результат:
{
"totalCount" : Number of records (some integer value)
}
Вы можете объединить Counter
с defaultdict
, чтобы сделать это довольно эффективно, когда вы разбили словарь по дате. Итак, сначала разделим по дате:
from collections import Counter, defaultdict
dtd = defaultdict(list)
for date, time in (item.split() for item in dtl):
dtd[date].append(time[:2])
Теперь вы можете легко сосчитать существующие элементы и использовать их для инициализации defaultdict
, который будет возвращать нули за отсутствующие времена:
for key in dtd:
dtd[key] = defaultdict(int, Counter(dtd[key]))
[1113 ] Результат:
defaultdict(list, {
'03/01/19': defaultdict(int, {
'09': 3,
'10': 2,
'11': 1,
'12': 5,
'17': 1,
'21': 1
}),
'05/01/19': defaultdict(int, {'14': 1, '17': 2, '21': 1}),
'06/01/19': defaultdict(int, {'11': 1, '12': 2})
})
Поскольку объекты здесь defaultdict
, вы сможете запрашивать даты и время, которых не было в исходном наборе данных. Вы можете избежать этого, преобразовав результат в обычный dict
, содержащий только те ключи, которые вы хотите после завершения:
hours = ['%02d' % h for h in range(24)]
dtd = {date: {h: d[h] for h in hours} for date, d in dtd}
Я бы предложил использовать collections.defaultdict
, так как некоторые из ваших показателей могут быть 0.
Вот вариант:
from collections import defaultdict
dtl = ['06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00',
'05/01/19 21:00', '05/01/19 17:00', '05/01/19 17:00',
'05/01/19 14:00', '03/01/19 21:00', '03/01/19 17:00',
'03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00',
'03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00',
'03/01/19 10:00', '03/01/19 10:00', '03/01/19 09:00',
'03/01/19 09:00','03/01/19 09:00',]
# Nested defaultdict
result = defaultdict(lambda: defaultdict(int))
for date_time in dtl:
date, time = date_time.split()
result[date][time.split(':')[0]] += 1
Вывод (используя pprint
):
defaultdict(<function <lambda> at 0x7f20d5c37c80>,
{'03/01/19': defaultdict(<class 'int'>,
{'09': 3,
'10': 2,
'11': 1,
'12': 5,
'17': 1,
'21': 1}),
'05/01/19': defaultdict(<class 'int'>,
{'14': 1,
'17': 2,
'21': 1}),
'06/01/19': defaultdict(<class 'int'>, {'12': 2, '11': 1})})
Если вы действительно хотите показать 0
для печати, тогда я не действительно вижу способ сохранить массив times
, как я сделал здесь, и инициализировать ваш dict
таким образом.
times = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
'11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21',
'22', '23']
dtl = ['06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00',
'05/01/19 21:00', '05/01/19 17:00', '05/01/19 17:00',
'05/01/19 14:00', '03/01/19 21:00', '03/01/19 17:00',
'03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00',
'03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00',
'03/01/19 10:00', '03/01/19 10:00', '03/01/19 09:00',
'03/01/19 09:00','03/01/19 09:00']
result = {date_time.split()[0] : {time : 0 for time in times} for date_time in dtl}
for date_time in dtl:
date, time = date_time.split()
result[date][time.split(':')[0]] += 1
Вывод ниже:
{'06/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 1, '12': 2, '13': 0, '14': 0, '15': 0, '16': 0, '17': 0, '18': 0, '19': 0, '20': 0, '21': 0, '22': 0, '23': 0}, '05/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 0, '12': 0, '13': 0, '14': 1, '15': 0, '16': 0, '17': 2, '18': 0, '19': 0, '20': 0, '21': 1, '22': 0, '23': 0}, '03/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 3, '10': 2, '11': 1, '12': 5, '13': 0, '14': 0, '15': 0, '16': 0, '17': 1, '18': 0, '19': 0, '20': 0, '21': 1, '22': 0, '23': 0}}