Подсчитать количество записей за данный день - PullRequest
0 голосов
/ 08 октября 2018

Раньше у меня был SQL-запрос для подсчета количества записей за определенный день в заданном месте.

Структура входных данных была такой: id, location, start_date, end_date

import pandas as pd
data = [('20170009003','0681','2017-07-25','2017-08-02'),
('20170009221','0682','2017-07-28','2017-08-02'),
('20170009271','0682','2017-07-31','2017-08-02'),
('20170009286','0681','2017-07-18','2017-09-19'),
('20170009654','0682','2017-07-28','2017-08-03'),
('20170010053','0681','2017-07-31','2017-08-04'),
('20170010059','0681','2017-07-20','2017-08-07')]
labels = ['idnum','loc','start_date','end_date']
df = pd.DataFrame.from_records(data, columns=labels)

Это дало бы мне количество (присутствующих) людей в данный день.то есть '2018-08-01', получит:

2018-08-01, 0681, 4
2018-08-01, 0682, 3

Я хотел бы получить аналогичный результат с python / pandas.

Если это поможет, sql(функция postgreql), используемая для достижения вышеуказанной цели:

CREATE OR REPLACE FUNCTION nb_present(oneday date)
 RETURNS TABLE(ddj date, loc character, eff numeric)
 LANGUAGE sql
AS $function$
SELECT $1, loc,sum(case when ($1= start_date and start_date_end_date) then 1 
                when $1=start_date then 0.5 
                when $1=end_date then 0.5 
                when ($1 > start_date and $1 < end_date) then 1 
                else 0 end)
from passage group by 1,2 order by 1,2;
$function$

Спасибо за вашу помощь.

PS: Это мой первый пост здесь.

Ответы [ 6 ]

0 голосов
/ 09 октября 2018

Я, наконец, нашел немного другое решение.Поскольку мне нужно было объединить полученный фрейм данных с другим, вот что я сделал:

df0 = pd.DataFrame()
for dt in pd.date_range('2017-08-01', '2017-08-05'):
    df1 = df[(df['start_date'] < dt) & (df['end_date'] > dt)].groupby('loc').size().to_frame().reset_index()
    df1['Date'] = dt
    df0 = df0.append(df1)

С наилучшими пожеланиями

0 голосов
/ 09 октября 2018

Используя только python, это возможно, используя сортировку с двумя элементами и группирование с двумя элементами

from itertools import groupby
from operator import itemgetter

data = sorted(data, key= itemgetter(-1, 1))
for k, g in groupby(data, key = itemgetter(-1, 1)):
    print('{}, {}, {}'.format(k[0], k[1], len(list(g))))
2017-08-02, 0681, 1
2017-08-02, 0682, 2
2017-08-03, 0682, 1
2017-08-04, 0681, 1
2017-08-07, 0681, 1
2017-09-19, 0681, 1
0 голосов
/ 08 октября 2018

Вот одно решение, если вы хотите делать это часто в течение нескольких дат: Мы создаем еще один DataFrame, который проверяет, находится ли эта строка между датами начала и окончания (используя IntervalIndex, но не обязательно).Затем мы можем сгруппировать это DataFrame по переменной loc в другой DataFrame (группировка выравнивается по индексу, поэтому мы используем .reset_index, чтобы убедиться, что все выровнено с вновь созданным DataFrame), и просто беремсумма, так как у нас есть True или False

import pandas as pd
import numpy as np

df['start_date'] = pd.to_datetime(df.start_date)
df['end_date'] = pd.to_datetime(df.end_date)
df.index = pd.IntervalIndex.from_arrays(df.start_date, df.end_date, closed='both')

# Dates you care about
dates = pd.to_datetime(['2017-08-01', '2017-08-02', '2017-08-03'])

df_bet = pd.DataFrame(np.reshape([d in ids for d in dates for ids in df.index] ,(-1, len(df))), index=dates).T

df_bet.groupby(df.reset_index()['loc']).agg(sum)

Выход:

      2017-08-01  2017-08-02  2017-08-03
loc                                     
0681         4.0         4.0         3.0
0682         3.0         3.0         1.0
0 голосов
/ 08 октября 2018

С вашей помощью я пришел с:

import pandas as pd
data = [('20170009003','0681','2017-07-25','2017-08-02'),
('20170009221','0682','2017-07-28','2017-08-02'),
('20170009271','0682','2017-07-31','2017-08-02'),
('20170009286','0681','2017-07-18','2017-09-19'),
('20170009654','0682','2017-07-28','2017-08-03'),
('20170010053','0681','2017-07-31','2017-08-04'),
('20170010059','0681','2017-07-20','2017-08-07')]
labels = ['idnum','loc','start_date','end_date']
df = pd.DataFrame.from_records(data, columns=labels)
df['end_date'] = pd.to_datetime(df['end_date'])
df['start_date'] = pd.to_datetime(df['start_date'])
dt = pd.to_datetime('2017-08-01')
df1 = df[(df['start_date'] < dt) & (df['end_date'] > dt)].groupby('loc').size().to_frame()
df1['Date'] = dt

Что отлично работает.

Теперь мне нужно настроить его, чтобы посчитать количество подарков на каждый день между двумя датами.Я оставлю это как домашнее задание.

Большое спасибо

0 голосов
/ 08 октября 2018

IIUC:

target = '2017-08-01'
df[(df['start_date'] < target) & (df['end_date'] > target)].groupby(['loc']).size()

Выход:

  loc
0681    4
0682    3
0 голосов
/ 08 октября 2018

Я считаю, что это то, что вы ищете (убедитесь, что ваши startdate и enddate являются пандами Datetime объектами):

dt = pd.to_datetime('2018-08-01')
df1 = df[(df['startdate'] > dt) & (df['enddate'] < dt)].groupby('loc').count().to_frame()
df1['Date'] = dt
...