计算给定日期的记录数

时间:2018-10-08 20:18:23

标签: python sql pandas date count

我曾经有一个SQL查询来计算给定位置在给定日期的记录数。

输入数据结构如下: id,位置,开始日期,结束日期

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 :(得分:2)

我相信这就是您要寻找的(确保您的startdateenddate是熊猫Datetime的对象)

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

答案 1 :(得分:1)

IIUC:

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

输出:

  loc
0681    4
0682    3

答案 2 :(得分:1)

如果您要在多个日期频繁执行此操作,则这是一种解决方案: 我们创建另一个DataFrame,以检查该行是否在开始日期和结束日期之间(使用IntervalIndex,但不是必须的)。然后,我们可以将DataFrame通过另一个loc中的DataFrame变量进行分组(分组是根据索引对齐的,因此我们使用.reset_index以确保所有内容都与我们新创建的对齐DataFrame),然后取一个总和,因为我们有TrueFalse

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

答案 3 :(得分:0)

在您的帮助下,我带来了:

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

哪个工作正常。

现在,我必须对其进行调整以计算两个日期之间每一天的礼物数量。我会将其作为作业。

非常感谢

答案 4 :(得分:0)

仅使用python即可,使用两个元素排序和两个元素groupby

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

答案 5 :(得分:0)

我终于想出了一个截然不同的解决方案。当我需要将结果数据框与另一个数据框合并时,这是我所做的:

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)

最诚挚的问候

相关问题