提取DataFrame中列的连续值序列的最小与最大日期
解决方案
要提取连续值序列的起止日期,核心是先给连续相同值的行打上同一分组标签,再基于分组计算起止日期,具体实现步骤如下:
- 生成连续分组标识
通过判断当前行var值是否与上一行不同,生成布尔序列后累加,得到每个连续序列的唯一分组ID:
import pandas as pd # 构造原DataFrame timeseries = pd.date_range("2018-01-01", periods=10, freq="m") df = pd.DataFrame(data = ["a","a","b","a","a","c","c","c","a","a"], index = timeseries, columns = ['var']) # 生成连续分组ID,区分被中断的相同值序列 df['group_id'] = df['var'].ne(df['var'].shift()).cumsum()
- 计算每个分组的起止日期
用transform方法对分组后的日期(即DataFrame的索引)计算最小/最大值,自动将结果映射回原DataFrame的每一行:
# 计算每个连续序列的最小、最大日期 df['min Date'] = df.groupby('group_id').transform(lambda x: x.index.min()) df['max Date'] = df.groupby('group_id').transform(lambda x: x.index.max())
- 调整日期格式(可选,匹配示例输出)
如果需要将日期转为m/d/Y格式,可通过dt.strftime处理:
# 转换日期格式并去除月份前的0 df['min Date'] = df['min Date'].dt.strftime('%m/%d/%Y').str.lstrip('0') df['max Date'] = df['max Date'].dt.strftime('%m/%d/%Y').str.lstrip('0')
最终输出结果与示例一致:
var min Date max Date 2018-01-31 a 1/31/2018 2/28/2018 2018-02-28 a 1/31/2018 2/28/2018 2018-03-31 b 3/31/2018 3/31/2018 2018-04-30 a 4/30/2018 5/31/2018 2018-05-31 a 4/30/2018 5/31/2018 2018-06-30 c 6/30/2018 8/31/2018 2018-07-31 c 6/30/2018 8/31/2018 2018-08-31 c 6/30/2018 8/31/2018 2018-09-30 a 9/30/2018 10/31/2018 2018-10-31 a 9/30/2018 10/31/2018
关键说明
- 普通
groupby('var')会将所有相同var值的行归为一组,而ne(df['var'].shift()).cumsum()生成的group_id,能区分被不同值中断的相同序列(比如第一次的a和第四次的a会被分到不同组)。 transform方法的作用是将分组计算结果广播到原DataFrame的每一行,避免聚合后丢失原行信息。
内容的提问来源于stack exchange,提问作者Martin Yordanov Georgiev
相关产品推荐
相关产品推荐

