我曾经有一个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:这是我在这里的第一篇文章。
答案 0 :(得分:2)
我相信这就是您要寻找的(确保您的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
答案 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
),然后取一个总和,因为我们有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
答案 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)
最诚挚的问候