我一直在尝试计算动态变化日期之间每个ID的行数。
我的数据集如下:
<表类>
日期
ID
Minimum_Date
分钟+ 6 m
分钟+ 12 m
分钟+ 18 m
tbody><<tr>2017-07-31 1 2017-07-31 2018-01-31 2018-07-31 2019-01-31 2018-05-08 1 2017-07-31 2018-01-31 2018-07-31 2019-01-31 2018-11-10 1 2017-07-31 2018-01-31 2018-07-31 2019-01-31 … … … … … … 2019-07-08 13 2019-07-08 2020-01-08 2020-07-08 2021-01-08 2019-08-10 13 2019-07-08 2020-01-08 2020-07-08 2021-01-08 2019-09-19 13 2019-07-08 2020-01-08 2020-07-08 2021-01-08 2019-12-23 13 2019-07-08 2020-01-08 2020-07-08 2021-01-08 表类>
我想你是从Date
和ID
列开始的。在这种情况下,在transform
:
groupby.transform
可以为您提供正确形状的组最小日期,以便与Date
列进行比较 带有dictionary参数的series.transform
可以通过每次移动几个月来获得您想要的边界日期的数据帧。这必须在DateOffset
中完成。
>>> dates = df.groupby('ID')['Date'].transform('min')
>>> dates
0 2017-07-31
1 2017-07-31
2 2017-07-31
4 2019-07-08
5 2019-07-08
6 2019-07-08
7 2019-07-08
Name: Date, dtype: datetime64[ns]
>>> dates = dates.transform({f'min + {n}m': lambda s, months=n: s + pd.offsets.DateOffset(months=months) for n in [0, 6, 12, 18]})
>>> dates
min + 0m min + 6m min + 12m min + 18m
0 2017-07-31 2018-01-31 2018-07-31 2019-01-31
1 2017-07-31 2018-01-31 2018-07-31 2019-01-31
2 2017-07-31 2018-01-31 2018-07-31 2019-01-31
4 2019-07-08 2020-01-08 2020-07-08 2021-01-08
5 2019-07-08 2020-01-08 2020-07-08 2021-01-08
6 2019-07-08 2020-01-08 2020-07-08 2021-01-08
7 2019-07-08 2020-01-08 2020-07-08 2021-01-08
从那里比较所有这些日期很容易,但需要使用.le()
和.gt()
而不是<=
和>
来指定我们比较的维度:
>>> dates.le(df['Date'], axis='index').groupby(df['ID']).sum()
min + 0m min + 6m min + 12m min + 18m
ID
1 3 2 1 0
13 4 0 0 0
这些是累积的,因为ID 1的所有3个日期都计算在min + 0m
列中,即使它们也在后面的列中。我们可以用两种方法中的一种来纠正这个错误,或者改变这个累积结果:
>>> cumul = dates.le(df['Date'], axis='index').groupby(df['ID']).sum()
>>> cumul.diff(-1, axis='columns').fillna(cumul).astype(int)
min + 0m min + 6m min + 12m min + 18m
ID
1 1 1 1 0
13 4 0 0 0
另一种方法是比较日期小于一个边界日期但大于下一个边界日期:
>>> dates
min + 0m min + 6m min + 12m min + 18m
0 2017-07-31 2018-01-31 2018-07-31 2019-01-31
1 2017-07-31 2018-01-31 2018-07-31 2019-01-31
2 2017-07-31 2018-01-31 2018-07-31 2019-01-31
4 2019-07-08 2020-01-08 2020-07-08 2021-01-08
5 2019-07-08 2020-01-08 2020-07-08 2021-01-08
6 2019-07-08 2020-01-08 2020-07-08 2021-01-08
7 2019-07-08 2020-01-08 2020-07-08 2021-01-08
>>> next_date = dates.shift(-1, axis='columns', fill_value=pd.Timestamp.max)
>>> next_date
min + 0m min + 6m min + 12m min + 18m
0 2018-01-31 2018-07-31 2019-01-31 2262-04-11 23:47:16.854775807
1 2018-01-31 2018-07-31 2019-01-31 2262-04-11 23:47:16.854775807
2 2018-01-31 2018-07-31 2019-01-31 2262-04-11 23:47:16.854775807
4 2020-01-08 2020-07-08 2021-01-08 2262-04-11 23:47:16.854775807
5 2020-01-08 2020-07-08 2021-01-08 2262-04-11 23:47:16.854775807
6 2020-01-08 2020-07-08 2021-01-08 2262-04-11 23:47:16.854775807
7 2020-01-08 2020-07-08 2021-01-08 2262-04-11 23:47:16.854775807
>>> between = dates.le(df['Date'], axis='index') & next_date.gt(df['Date'], axis='index')
>>> between
min + 0m min + 6m min + 12m min + 18m
0 True False False False
1 False True False False
2 False False True False
4 True False False False
5 True False False False
6 True False False False
7 True False False False
>>> between.groupby(df['ID']).sum()
min + 0m min + 6m min + 12m min + 18m
ID
1 1 1 1 0
13 4 0 0 0