python - 如何创建按日期排序的groupby ID变量第一次出现的指标列?
问题描述
我在表单的数据框中有一些医院就诊医疗保健数据:
CLIENT_ID | DATE_ENCOUNTER | DATE_CONSELLING | COUNSELLING_COUNT 个 |
---|---|---|---|
54950 | 2017-11-24 | 钠 | 0 |
54950 | 2018-01-19 | 钠 | 0 |
54950 | 2018-03-13 | 钠 | 0 |
54950 | 2018-05-11 | 2018-04-30 | 1 |
54950 | 2018-12-17 | 2018-06-25 | 3 |
67777 | 2015-09-01 | 钠 | 0 |
67777 | 2015-12-01 | 钠 | 0 |
67777 | 2016-02-28 | 2016-02-28 | 1 |
70000 | 2019-06-07 | 2019-06-07 | 1 |
70000 | 2019-08-09 | 2019-06-07 | 1 |
我想创建一个列COUNSELLING_STARTED
来指示客户是否CLIENT_ID
已经开始咨询,但只是第一次。即COUNSELLING_COUNT == 1
对于每个CLIENT_ID
应该导致以下数据帧的第一次出现:
CLIENT_ID | DATE_ENCOUNTER | DATE_CONSELLING | COUNSELLING_COUNT 个 | COUNSELLING_STARTED |
---|---|---|---|---|
54950 | 2017-11-24 | 钠 | 0 | 0 |
54950 | 2018-01-19 | 钠 | 0 | 0 |
54950 | 2018-03-13 | 钠 | 0 | 0 |
54950 | 2018-05-11 | 2018-04-30 | 1 | 1 |
54950 | 2018-12-17 | 2018-06-25 | 3 | 0 |
67777 | 2015-09-01 | 钠 | 0 | 0 |
67777 | 2015-12-01 | 钠 | 0 | 0 |
67777 | 2016-02-28 | 2016-02-28 | 1 | 1 |
70000 | 2019-06-07 | 2019-06-07 | 1 | 1 |
70000 | 2019-08-09 | 2019-06-07 | 1 | 0 |
下面是生成数据框的代码:
data = {'CLIENT_ID':[54950,54950,54950,54950,54950,67777,67777,67777,70000,70000],
'DATE_ENCOUNTER':['2017-11-24','2018-01-19','2018-03-13','2018-05-11','2018-12-17','2015-09-01','2015-12-01','2016-02-28','2019-06-07','2019-08-09'],
'DATE_COUNSELLING':[np.nan,np.nan,np.nan,'2018-04-30','2018-06-25',np.nan,np.nan,'2016-02-28','2019-06-07','2019-06-07'],
'COUNSELLING_COUNT':[0,0,0,1,3,0,0,1,1,1]}
df = pd.DataFrame(data)
解决方案
更新
在我最初的回答中,我错过了一个事实,即如果有人没有咨询日期,我的方法会1
为他们的第一个条目分配一个。这是解决此问题的两种快速方法。
一种选择是在执行我描述的 groupby 之前使用 NA 显式删除这些行:
dropped = df[~df['DATE_COUNSELLING'].isna()]
df.loc[:, 'COUNSELLING_STARTED'] = 0
df.loc[dropped['DATE_COUNSELLING'].isna().groupby(dropped['CLIENT_ID']).idxmin(), 'COUNSELLING_STARTED'] = 1
# note that `dropped` is used inside the brackets in the last line
第二种选择是简单地做我以前做过的事情,然后覆盖错误的条目(即,咨询是 NA):
df.loc[:, 'COUNSELLING_STARTED'] = 0
df.loc[df['DATE_COUNSELLING'].isna().groupby(df['CLIENT_ID']).idxmin(), 'COUNSELLING_STARTED'] = 1
df.loc[df['DATE_COUNSELLING'].isna(), 'COUNSELLING_STARTED'] = 0
# last line catches people with no counseling
这是我原来的答案:
df.loc[:, 'COUNSELLING_STARTED'] = 0
df.loc[df['DATE_COUNSELLING'].isna().groupby(df['CLIENT_ID']).idxmin(), 'COUNSELLING_STARTED'] = 1
解释(使用我的第一种方法):
查找咨询日期在哪里nan
;然后按客户端 ID 分组并找到最小值的索引(这将是第一个条目):
>>> dropped['DATE_COUNSELLING'].isna().groupby(dropped['CLIENT_ID']).idxmin()
CLIENT_ID
54950 3
67777 7
70000 8
Name: DATE_COUNSELLING, dtype: int64
1
您正在使用这些索引来选择在新列中写入的位置。即使dropped
没有任何 NA 值,我们仍然.isna()
在 groupby 中使用以获取我们可以接受的值min
(而不是字符串)。你也可以做类似的事情.astype(bool)
。
那么决赛df
是:
CLIENT_ID DATE_ENCOUNTER ... COUNSELLING_COUNT COUNSELLING_STARTED
0 54950 2017-11-24 ... 0 0
1 54950 2018-01-19 ... 0 0
2 54950 2018-03-13 ... 0 0
3 54950 2018-05-11 ... 1 1
4 54950 2018-12-17 ... 3 0
5 67777 2015-09-01 ... 0 0
6 67777 2015-12-01 ... 0 0
7 67777 2016-02-28 ... 1 1
8 70000 2019-06-07 ... 1 1
9 70000 2019-08-09 ... 1 0
[10 rows x 5 columns]
如果您想明确选择最早的咨询日期(而不是第一个非 NA 值),则可以将其用作索引器:
>>> pd.to_datetime(dropped['DATE_COUNSELLING']).groupby(dropped['CLIENT_ID']).idxmin()
CLIENT_ID
54950 3
67777 7
70000 8
Name: DATE_COUNSELLING, dtype: int64
这给出了相同的结果,因为日期是为每个客户排序的(即最早观察到的日期是第一个非 NA 值)。
推荐阅读
- javascript - mongo db:使用 $gte 和 $lte 通过仅输入年份来查找字符串日期
- json - jq:将单个对象视为 1 元素数组
- mongodb - mongo 在聚合中使用 $add 聚合
- javascript - JavaScript 替换字符串中的特殊 HTML(&character; 格式)字符
- android - 创建聊天室应用程序以“无效文档参考”结尾
- java - 与 getMappedResults() 一起使用时查找无法正常工作
- opencv - 在 OpenCV 中使用单应性时如何检测地平线
- nginx - 如何将我的 nginx 配置转换为 haproxy?
- python - 在 Jupyter 笔记本中的 2 个 python 内核之间进行更改
- javascript - 使用 jquery 验证插件进行远程验证后如何使用 ajax 提交表单