我有以下问题,正如我所读到的,它被称为"缺口和岛屿"问题。我的数据样本如下(我也排除了一些与用户相关的列,但我想方法是一样的(:
用户报告日期 | ||
---|---|---|
john | 标记 | 2021年1月 |
john | 标记 | 2021年2月1日//tr>|
john | 标记 | 2021年3月1日|
john | 标记 | 2021年4月1日|
john | 标记 | 2021年5月1日//tr>|
john | 标记 | 2021年6月1日//tr>|
john | 标记 | 2021年7月1日|
john | 标记 | 2021年8月1日|
john | 标记 | 2021年9月1日//tr>|
john | 标记 | 2021年1月10日//tr>|
john | 标记 | 2021年1月11日//tr>|
john | 尼克 | 2021年1月12日//tr>|
john | 尼克 | 2021年1月13日 |
john | 尼克 | 2021年1月14日//tr>|
john | 尼克 | 2021年1月15日//tr>|
john | 尼克 | 2021年1月16日//tr>|
john | 尼克 | 2021年1月17日//tr>|
john | 尼克 | 2021年1月18日//tr>|
john | 尼克 | 2021年1月19日 |
john | 尼克 | 2021年1月20日 |
john | 标记 | 2021年1月21日//tr>|
john | 标记 | 2021年1月22日//tr>|
john | 标记 | 2021年1月23日//tr>|
john | 标记 | 2021年1月24日//tr>|
john | 标记 | 2021年1月25日//tr>
正如@Arne在评论中提到的,如果您分配一个新的数据帧列,然后用user
和reports_to
对其进行聚合,则链接答案确实有效。
分配
# ADD NEW GROUP SEQ COLUMN
staff_df = (
staff_df.assign(
group_seq = lambda df: (
df["reports_to"].ne(df["reports_to"].shift()).cumsum()
)
)
)
staff_df
# user reports_to date group_seq
# 0 john mark 2021-01-01 1
# 1 john mark 2021-01-02 1
# 2 john mark 2021-01-03 1
# 3 john mark 2021-01-04 1
# 4 john mark 2021-01-05 1
# 5 john mark 2021-01-06 1
# 6 john mark 2021-01-07 1
# 7 john mark 2021-01-08 1
# 8 john mark 2021-01-09 1
# 9 john mark 2021-01-10 1
# 10 john mark 2021-01-11 1
# 11 john nick 2021-01-12 2
# 12 john nick 2021-01-13 2
# 13 john nick 2021-01-14 2
# 14 john nick 2021-01-15 2
# 15 john nick 2021-01-16 2
# 16 john nick 2021-01-17 2
# 17 john nick 2021-01-18 2
# 18 john nick 2021-01-19 2
# 19 john nick 2021-01-20 2
# 20 john mark 2021-01-21 3
# 21 john mark 2021-01-22 3
# 22 john mark 2021-01-23 3
# 23 john mark 2021-01-24 3
# 24 john mark 2021-01-25 3
聚合
agg_df = (
staff_df.groupby(["user", "reports_to", "group_seq"]).agg(
min = ("date", "min"), max = ("date", "max")
).sort_values(["min", "max"])
)
agg_df
# min max
# user reports_to group_seq
# john mark 1 2021-01-01 2021-01-11
# nick 2 2021-01-12 2021-01-20
# mark 3 2021-01-21 2021-01-25
代码在这里。
import pandas as pd
from io import StringIO
df = '''
user reports_to date
john mark 1/1/2021
john mark 2/1/2021
john mark 3/1/2021
john mark 4/1/2021
john mark 5/1/2021
john mark 6/1/2021
john mark 7/1/2021
john mark 8/1/2021
john mark 9/1/2021
john mark 10/1/2021
john mark 11/1/2021
john nick 12/1/2021
john nick 13/1/2021
john nick 14/1/2021
john nick 15/1/2021
john nick 16/1/2021
john nick 17/1/2021
john nick 18/1/2021
john nick 19/1/2021
john nick 20/1/2021
john mark 21/1/2021
john mark 22/1/2021
john mark 23/1/2021
john mark 24/1/2021
john mark 25/1/2021
'''
inf=StringIO(df)
df = pd.read_csv(inf,sep="t")
df['group'] = (( (df.user != df.user.shift() ) | (df.reports_to != df.reports_to.shift()) ).cumsum())
# must do this
df['date'] = pd.to_datetime(df['date'])
result = ( df.groupby(['user','group','reports_to'])['date']
.agg({min, max})
.rename(columns={'min': 'from','max':'to'})
.reset_index() )