Python 在pandas中计算面板数据集中并发实体的数量
我有一组数年内患者就诊的数据。变量包括患者id和就诊日期。我感兴趣的是确定在任何一天有多少患者仍在接受治疗。我假设患者最后一次就诊表明他们不再接受治疗 患者有不同的就诊次数和就诊日期。这也意味着患者接受不同长度的治疗。以下是我的数据示例:Python 在pandas中计算面板数据集中并发实体的数量,python,pandas,Python,Pandas,我有一组数年内患者就诊的数据。变量包括患者id和就诊日期。我感兴趣的是确定在任何一天有多少患者仍在接受治疗。我假设患者最后一次就诊表明他们不再接受治疗 患者有不同的就诊次数和就诊日期。这也意味着患者接受不同长度的治疗。以下是我的数据示例: index patient_id visit_date 0 01 2014-08-10 1 01 2014-08-12 2 01 2014-08-13 3
index patient_id visit_date
0 01 2014-08-10
1 01 2014-08-12
2 01 2014-08-13
3 02 2014-08-12
4 02 2014-08-15
5 03 2014-08-13
6 03 2014-08-15
7 03 2014-08-16
理想情况下,我希望最终数据集如下所示:
date num_patients
2014-08-10 1
2014-08-11 1
2014-08-12 2
2014-08-13 3
2014-08-14 2
2014-08-15 2
2014-08-16 1
我正在使用pandas,并尝试使用reindex
解决此问题,但未成功。如果我使用的是Stata
,我会使用xtset
和tsfill
,但我不知道这些在熊猫中的等价物。我会注意到,我的数据集在数千天内有超过300000个观测值,因此我们希望能找到一个有效的解决方案
我一直在努力找出解决我问题的最佳方法,希望能得到任何帮助
2016年3月19日编辑
我意识到我可能不太清楚我的最终结果。我试图统计某一天有多少患者正在接受治疗,即使他们那天没有预约
例如,(见上面的输出表)我希望2014-08-13年的患者数量为3,因为患者1、2和3仍在接受治疗。患者1和3当天有实际就诊,但患者2没有。然而,患者2仍然是计数的,因为她还没有登录她的最后一次访问(2014-0815),这表明她仍然处于治疗的中间。p>
感谢所有的帮助和建议 设置
设置数据框,使visit\u date
格式化为pandasdatetime
对象并用作索引。索引
列被删除,因为它是冗余的
import pandas as pd
from StringIO import StringIO
# Create DataFrame from the example data
data = '''index patient_id visit_date
0 01 2014-08-10
1 01 2014-08-12
2 01 2014-08-13
3 02 2014-08-12
4 02 2014-08-15
5 03 2014-08-13
6 03 2014-08-15
7 03 2014-08-16
'''
df = pd.read_csv(StringIO(data), delim_whitespace=True)
# Remove the 'index' column; this is redundant
df.drop('index', axis=1, inplace=True)
# Convert 'visit_date' to datetime and set it as the index
df.visit_date = pd.to_datetime(df.visit_date, format='%Y-%m-%d')
df.set_index('visit_date', inplace=True, drop=True)
# Peek at the first five rows
print(df.head())
数据帧概览:
patient_id
visit_date
2014-08-10 1
2014-08-12 1
2014-08-13 1
2014-08-12 2
2014-08-15 2
patient_id
visit_date
2014-08-10 1
2014-08-12 2
2014-08-13 2
2014-08-15 2
2014-08-16 1
请注意,患者id
已转换为整数。只要每个id都是唯一的,这就与分析的其余部分无关
分析
使用重新采样
由于这现在是一个简单的方法,pandas提供了一种使用重采样来计算访问次数的简单方法:
# set bin size to 1 (D)ay and count
visits_count = df.resample('D').count()
print(visits_count)
哪些产出:
patient_id
visit_date
2014-08-10 1
2014-08-11 0
2014-08-12 2
2014-08-13 2
2014-08-14 0
2014-08-15 2
2014-08-16 1
使用groupby
提取计数的一种有效方法是对数据进行分组,并对每组应用汇总函数
def count_visits(grp):
count = grp.patient_id.size
return count
visits_df = df.groupby(df.index).apply(count_visits)
print(visits_df)
输出熊猫系列:
visit_date
2014-08-10 1
2014-08-12 2
2014-08-13 2
2014-08-15 2
2014-08-16 1
使用聚合
或者,您可以使用agg
功能获得类似的结果
import numpy as np
visits_df = df.groupby(df.index).agg(np.size)
print(visits_df)
输出数据帧:
patient_id
visit_date
2014-08-10 1
2014-08-12 1
2014-08-13 1
2014-08-12 2
2014-08-15 2
patient_id
visit_date
2014-08-10 1
2014-08-12 2
2014-08-13 2
2014-08-15 2
2014-08-16 1
阅读更多
- 本教程将带您走得更远
这是获得所需输出的一种方法,但我不确定它在非常大/稀疏的数据集上的效率
import pandas as pd
from StringIO import StringIO
from pandas.tseries.offsets import DateOffset
str = '''patient_id visit_date
01 2014-08-10
01 2014-08-12
01 2014-08-13
02 2014-08-12
02 2014-08-15
03 2014-08-13
03 2014-08-15
03 2014-08-16
'''
df = pd.read_csv(StringIO(str), delim_whitespace=True)
df['visit_date'] = pd.to_datetime(df['visit_date'], format='%Y-%m-%d')
df = df.set_index('visit_date', drop=True)
# function to fill in the gaps for each patient
def fill_gaps(group):
return group.asfreq(DateOffset(days=1))
filled_df = df.groupby('patient_id').apply(fill_gaps)
这就是此时填充的_df的样子:
patient_id
patient_id visit_date
1 2014-08-10 1
2014-08-11 NaN
2014-08-12 1
2014-08-13 1
2 2014-08-12 2
2014-08-13 NaN
2014-08-14 NaN
2014-08-15 2
3 2014-08-13 3
2014-08-14 NaN
2014-08-15 3
2014-08-16 3
索引包含我们需要的所有信息,因此我们删除patient_id列并重置索引。此时,您可以使用@gauden在其答案中提到的任何解决方案,并查看哪个解决方案在您的数据集上最快
filled_df = filled_df.drop('patient_id', axis=1)
filled_df = filled_df.reset_index()
filled_df = filled_df.set_index('visit_date')
final_df = filled_df.groupby(filled_df.index).size()
现在,final_df看起来像原始问题中的最终数据集:
visit_date
2014-08-10 1
2014-08-11 1
2014-08-12 2
2014-08-13 3
2014-08-14 2
2014-08-15 2
2014-08-16 1
非常感谢你的帮助!我不知道重采样,我认为这将是非常有帮助的。代码的最终输出与我想要的略有不同(参见原始帖子)。例如,有没有办法让2014-08-13的计数为3而不是2?应该是3,因为从技术上讲,患者1、2和3正在接受治疗(即使患者2在2014-08-13没有就诊)。@Eric刚刚在您的扩展问题中添加了缺少的部分。你的解决方案结合了他的答案和我的答案。我可以建议你选择一个作为你的解决方案,然后再投票给另一个吗?:)