给定开始日期和结束日期当天的活动项目数
Count of active items on day given start and stop date
我有一个包含 2 列的数据框,如下所示。
+------+-------------+------------+
| id | start_date | stop_date |
+------+-------------+------------+
| Foo | 2019-06-01 | 2019-06-03 |
| Bar | 2019-06-07 | 2019-06-10 |
| Pop | 2019-06-09 | 2019-06-11 |
| Bob | 2019-06-13 | |
| Tom | 2019-06-01 | 2019-06-05 |
| Tim | 2019-06-04 | 2019-06-05 |
| Ben | 2019-06-07 | 2019-06-09 |
| Ted | 2019-06-08 | 2019-06-09 |
+------+------------+-------------+
我需要 return 2 个 df,其中一个包含日期范围内的活动项目数(如下例)
+------------+-------+
| Day |Active |
+------------+-------+
| 2019-06-01 | 2 |
| 2019-06-02 | 2 |
| 2019-06-03 | 2 |
| 2019-06-04 | 2 |
| 2019-06-05 | 2 |
| 2019-06-06 | 0 |
| 2019-06-07 | 2 |
| 2019-06-08 | 3 |
| 2019-06-09 | 4 |
| 2019-06-10 | 2 |
| 2019-06-11 | 1 |
| 2019-06-12 | 0 |
| 2019-06-13 | 1 |
| 2019-06-14 | 1 |
| 2019-06-15 | 1 |
+------------+-------+
另一个 returns 是一个 df,其中包含给定日期的活动项目,即
2019-06-10 returns df:
| Bar | 2019-06-07 | 2019-06-10 |
| Pop | 2019-06-09 | 2019-06-11 |
到目前为止,我已尝试 return 第二个示例:
active_date = pd.Timestamp('2019-06-10')
df_active = df[(df['start_date'] <= active_date) & ((df["stop_date"].isnull()) | (df["stop_date"] > active_date))]`
感谢任何帮助!
你可以这样做:
df[["start_date", "stop_date"]] = df[["start_date", "stop_date"]].apply(pd.to_datetime)
df = df.ffill(axis=1)
df["days"] = [
pd.date_range(s, e, freq="D") for s, e in zip(df["start_date"], df["stop_date"])
]
df2 = (
df.explode("days")
.groupby("days")["id"]
.nunique()
.reindex(pd.date_range(df["start_date"].min(), df["stop_date"].max()), fill_value=0)
)
输出:
2019-06-01 2
2019-06-02 2
2019-06-03 2
2019-06-04 2
2019-06-05 2
2019-06-06 0
2019-06-07 2
2019-06-08 3
2019-06-09 4
2019-06-10 2
2019-06-11 1
2019-06-12 0
2019-06-13 1
Freq: D, Name: id, dtype: int64
然后,使用 pd.IntervalIndex:
active_date = pd.Timestamp('2019-06-10')
df[
pd.IntervalIndex.from_arrays(df["start_date"], df["stop_date"]).contains(
active_date
)
].drop("days", axis=1)
输出:
id start_date stop_date
1 Bar 2019-06-07 2019-06-10
2 Pop 2019-06-09 2019-06-11
我有一个包含 2 列的数据框,如下所示。
+------+-------------+------------+
| id | start_date | stop_date |
+------+-------------+------------+
| Foo | 2019-06-01 | 2019-06-03 |
| Bar | 2019-06-07 | 2019-06-10 |
| Pop | 2019-06-09 | 2019-06-11 |
| Bob | 2019-06-13 | |
| Tom | 2019-06-01 | 2019-06-05 |
| Tim | 2019-06-04 | 2019-06-05 |
| Ben | 2019-06-07 | 2019-06-09 |
| Ted | 2019-06-08 | 2019-06-09 |
+------+------------+-------------+
我需要 return 2 个 df,其中一个包含日期范围内的活动项目数(如下例)
+------------+-------+
| Day |Active |
+------------+-------+
| 2019-06-01 | 2 |
| 2019-06-02 | 2 |
| 2019-06-03 | 2 |
| 2019-06-04 | 2 |
| 2019-06-05 | 2 |
| 2019-06-06 | 0 |
| 2019-06-07 | 2 |
| 2019-06-08 | 3 |
| 2019-06-09 | 4 |
| 2019-06-10 | 2 |
| 2019-06-11 | 1 |
| 2019-06-12 | 0 |
| 2019-06-13 | 1 |
| 2019-06-14 | 1 |
| 2019-06-15 | 1 |
+------------+-------+
另一个 returns 是一个 df,其中包含给定日期的活动项目,即 2019-06-10 returns df:
| Bar | 2019-06-07 | 2019-06-10 |
| Pop | 2019-06-09 | 2019-06-11 |
到目前为止,我已尝试 return 第二个示例:
active_date = pd.Timestamp('2019-06-10')
df_active = df[(df['start_date'] <= active_date) & ((df["stop_date"].isnull()) | (df["stop_date"] > active_date))]`
感谢任何帮助!
你可以这样做:
df[["start_date", "stop_date"]] = df[["start_date", "stop_date"]].apply(pd.to_datetime)
df = df.ffill(axis=1)
df["days"] = [
pd.date_range(s, e, freq="D") for s, e in zip(df["start_date"], df["stop_date"])
]
df2 = (
df.explode("days")
.groupby("days")["id"]
.nunique()
.reindex(pd.date_range(df["start_date"].min(), df["stop_date"].max()), fill_value=0)
)
输出:
2019-06-01 2
2019-06-02 2
2019-06-03 2
2019-06-04 2
2019-06-05 2
2019-06-06 0
2019-06-07 2
2019-06-08 3
2019-06-09 4
2019-06-10 2
2019-06-11 1
2019-06-12 0
2019-06-13 1
Freq: D, Name: id, dtype: int64
然后,使用 pd.IntervalIndex:
active_date = pd.Timestamp('2019-06-10')
df[
pd.IntervalIndex.from_arrays(df["start_date"], df["stop_date"]).contains(
active_date
)
].drop("days", axis=1)
输出:
id start_date stop_date
1 Bar 2019-06-07 2019-06-10
2 Pop 2019-06-09 2019-06-11