如何按月获取 pandas 中不同类别的唯一计数?
How to get unique count by month for different categories in pandas?
我有一个这样的 pandas 数据框:
Month ID
Sep 21 ID_1
Sep 21 ID_2
Sep 21 ID_3
Oct 21 ID_1
Oct 21 ID_2
Oct 21 ID_4
Oct 21 ID_5
Nov 21 ID_1
Nov 21 ID_2
Nov 21 ID_3
Nov 21 ID_4
Dec 21 ID_2
Dec 21 ID_3
Dec 21 ID_4
Dec 21 ID_5
Jan 22 ID_3
Jan 22 ID_4
Jan 22 ID_5
并且我想要像这样的格式的 ID 计数作为输出 pandas 数据帧:
作为值,我可以获得每个月的 ID 的唯一计数,例如 10 月 2 日的 ID1 应该被计算在 2 个月以内,因为它现在出现了 2 个月,而在 11 月 ID2 将被计算在 3 个月以内,因为它是持续出现 3 个月。但由于 ID5 在 10 月首次出现,因此在 10 月将被计算在 1 个月以内,依此类推。任何出现超过4次的ID都应计入4个月+类别。
在 pandas 中,我不确定如何使用这种方法来获得这个独特的计数并拥有一个枢轴 table。
首先,这将创建一个发生矩阵。请注意,我对 easy-sorting.
使用 date-time 格式 Month
step1 = pd.crosstab(
df['ID'],
pd.to_datetime(df['Month'], format='%b %y')
)
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
ID
ID_1 1 1 1 0 0
ID_2 1 1 1 1 0
ID_3 1 0 1 1 1
ID_4 0 1 1 1 1
ID_5 0 1 0 1 1
然后,做满足连续性条件的累加和
for month_prev, month_next in zip(step1.columns, step1.columns[1:]):
step1[month_next] = (step1[month_next] + step1[month_prev]) * step1[month_next]
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
ID
ID_1 1 2 3 0 0
ID_2 1 2 3 4 0
ID_3 1 0 1 2 3
ID_4 0 1 2 3 4
ID_5 0 1 0 1 2
然后,我们应用melt
、groupby
、value_counts
来计算每个月的cumsum-values,unstack
移动Month
到列,其余 3 种方法来处理格式。
step2 = pd.melt(step1)\
.groupby('Month')['value']\
.value_counts()\
.unstack(level=0)\
.fillna(0)\
.drop(0)\
.astype(int)
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
value
1 3 2 1 1 0
2 0 2 1 1 1
3 0 0 2 1 1
4 0 0 0 1 1
进一步格式化的最后一步:
step2.columns = step2.columns.strftime('%b %y')
step2.loc[4] = step2.loc[step2.index>=4].sum()
step2.index = (step2.index.astype(str) + ' Month').str.replace('4 Month', '4 Month+')
Month Sep 21 Oct 21 Nov 21 Dec 21 Jan 22
value
1 Month 3 2 1 1 0
2 Month 0 2 1 1 1
3 Month 0 0 2 1 1
4 Month+ 0 0 0 1 1
我有一个这样的 pandas 数据框:
Month ID
Sep 21 ID_1
Sep 21 ID_2
Sep 21 ID_3
Oct 21 ID_1
Oct 21 ID_2
Oct 21 ID_4
Oct 21 ID_5
Nov 21 ID_1
Nov 21 ID_2
Nov 21 ID_3
Nov 21 ID_4
Dec 21 ID_2
Dec 21 ID_3
Dec 21 ID_4
Dec 21 ID_5
Jan 22 ID_3
Jan 22 ID_4
Jan 22 ID_5
并且我想要像这样的格式的 ID 计数作为输出 pandas 数据帧:
作为值,我可以获得每个月的 ID 的唯一计数,例如 10 月 2 日的 ID1 应该被计算在 2 个月以内,因为它现在出现了 2 个月,而在 11 月 ID2 将被计算在 3 个月以内,因为它是持续出现 3 个月。但由于 ID5 在 10 月首次出现,因此在 10 月将被计算在 1 个月以内,依此类推。任何出现超过4次的ID都应计入4个月+类别。
在 pandas 中,我不确定如何使用这种方法来获得这个独特的计数并拥有一个枢轴 table。
首先,这将创建一个发生矩阵。请注意,我对 easy-sorting.
使用 date-time 格式Month
step1 = pd.crosstab(
df['ID'],
pd.to_datetime(df['Month'], format='%b %y')
)
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
ID
ID_1 1 1 1 0 0
ID_2 1 1 1 1 0
ID_3 1 0 1 1 1
ID_4 0 1 1 1 1
ID_5 0 1 0 1 1
然后,做满足连续性条件的累加和
for month_prev, month_next in zip(step1.columns, step1.columns[1:]):
step1[month_next] = (step1[month_next] + step1[month_prev]) * step1[month_next]
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
ID
ID_1 1 2 3 0 0
ID_2 1 2 3 4 0
ID_3 1 0 1 2 3
ID_4 0 1 2 3 4
ID_5 0 1 0 1 2
然后,我们应用melt
、groupby
、value_counts
来计算每个月的cumsum-values,unstack
移动Month
到列,其余 3 种方法来处理格式。
step2 = pd.melt(step1)\
.groupby('Month')['value']\
.value_counts()\
.unstack(level=0)\
.fillna(0)\
.drop(0)\
.astype(int)
Month 2021-09-01 2021-10-01 2021-11-01 2021-12-01 2022-01-01
value
1 3 2 1 1 0
2 0 2 1 1 1
3 0 0 2 1 1
4 0 0 0 1 1
进一步格式化的最后一步:
step2.columns = step2.columns.strftime('%b %y')
step2.loc[4] = step2.loc[step2.index>=4].sum()
step2.index = (step2.index.astype(str) + ' Month').str.replace('4 Month', '4 Month+')
Month Sep 21 Oct 21 Nov 21 Dec 21 Jan 22
value
1 Month 3 2 1 1 0
2 Month 0 2 1 1 1
3 Month 0 0 2 1 1
4 Month+ 0 0 0 1 1