【问题标题】:Python: How can I populate rows between dates for each ID?Python:如何在每个 ID 的日期之间填充行?
【发布时间】:2021-11-06 05:51:52
【问题描述】:
目标:我想把每个月的现任和离任成员都绘制出来。
所以我有两个数据框(见下文):数据框 A 有一个 ID、他们加入俱乐部的日期和 YTD 日期。 数据框 B 具有每个 ID 的开始日期、结束日期和成员资格类型。
我想在 Dataframe A 中填充显示会员类型以及活动和终止标志的新列。
从概念上讲,我什至不确定如何在 Python、Excel 甚至 SQL 上解决这个问题。如果是针对一个事件和一个 ID,我可以简单地在 Python 上创建一个掩码。但我不确定如何在数据帧之间循环它。有什么建议吗?
数据框 A
| ID |
Date |
Created Date |
| 123 |
2001-03-01 |
2001-03-01 |
| 123 |
2001-04-01 |
2001-03-01 |
| 123 |
2001-05-01 |
2001-03-01 |
| 123 |
2001-06-01 |
2001-03-01 |
| 456 |
2001-05-01 |
2001-05-01 |
| 456 |
2001-06-01 |
2001-05-01 |
数据框 B
| ID |
Start Date |
End Date |
Membership |
| 123 |
2001-03-01 |
2001-04-30 |
Bronze |
| 123 |
2001-05-01 |
2001-06-01 |
Iron |
| 456 |
2001-05-01 |
2001-06-30 |
Gold |
期望的输出
| ID |
Date |
Join Date |
Leave Date |
Active |
Termination |
| 123 |
2001-03-01 |
2001-03-05 |
2001-06-30 |
1 |
|
| 123 |
2001-04-01 |
2001-03-05 |
2001-06-30 |
1 |
|
| 123 |
2001-05-01 |
2001-03-05 |
2001-06-30 |
1 |
|
| 123 |
2001-06-01 |
2001-03-05 |
2001-06-30 |
|
1 |
| 456 |
2001-05-01 |
2001-05-01 |
2001-06-30 |
1 |
|
| 456 |
2001-06-01 |
2001-05-01 |
2001-06-30 |
|
1 |
【问题讨论】:
标签:
python
sql
pandas
dataframe
date
【解决方案1】:
首先,您应该确保所需的所有日期都是日期时间格式。
接下来,获取唯一 ID 的加入日期和离开日期。
将它们合并在一起并创建列,然后根据条件进行过滤。
示例代码:
df_a["Date"] = pd.to_datetime(df_a["Date"], errors = 'coerce')
df_b["Start Date"] = pd.to_datetime(df_b["Start Date"], errors = 'coerce')
df_b["End Date"] = pd.to_datetime(df_b["End Date"], errors = 'coerce')
df_join = df_a.groupby(by="ID", as_index=False).agg({"Start Date": "min"}).rename(columns={"Start Date": "Join Date"}, inplace=True)
df_leave = df_b.groupby(by="ID", as_index=False).agg({"End Date": "min"}).rename(columns={"End Date": "Leave Date"}, inplace=True)
df = pd.merge(df_a, df_join, on="ID", how="left")
df = pd.merge(df, df_leave, on="ID", how="left")
df["Active"] = (df["Date"].dt.to_period('M') < df["Leave Date"].dt.to_period('M'))
df["Termination"] = (df["Date"].dt.to_period('M') >= df["Leave Date"].dt.to_period('M'))
此答案将采用布尔格式。如果你想采用数字格式
df.loc[df["Active"] == True, "Active"] = 1
df.loc[df["Termination"] == True, "Termination"] = 1