Pandas非整数索引DataFrame标记连续日期最大值的实现问题
问题描述
现有如下结构的DataFrame:
date 01.01.2003 02.01.2003 03.01.2003 05.01.2003 06.01.2003
尝试运行这段代码:
for i in (df['date']): if df['date'].iloc[i+1]-df['date'].iloc[i] == 1 : df['Max'] = df['date'].iloc[i+1] else : df['Max'] = ''
结果报错:
Addition/subtraction of integers and integer-arrays with Timestamp is no longer supported. Instead of adding/subtracting `n`, use `n * obj.freq`
换成timedelta(days=1)后,又出现无法使用非整数索引的错误。
需求很明确:给每一组连续日期的最后一行标记该组的最大日期(也就是最后一个日期),其余行留空,期望输出如下:
date max 01.01.2003 02.01.2003 03.01.2003 03.01.2003 05.01.2003 06.01.2003 06.01.2003
注:仅在连续日期组最后一行填最大值,非连续日期需重新分组。
解决方案
1. 先把日期列转成datetime类型
要处理日期逻辑,首先得确保date列是datetime格式,不然没法正确计算日期差:
import pandas as pd df['date'] = pd.to_datetime(df['date'], format='%d.%m.%Y')
2. 给连续日期分组
通过计算当前日期与上一行日期的差值,判断是否属于同一连续组:
# 标记分组:如果当前日期和前一天差不是1天,就开启新分组 df['group'] = (df['date'] - df['date'].shift(1) != pd.Timedelta(days=1)).cumsum()
3. 标记每组的最后一行日期
先通过分组获取每组的最大日期,再只保留每组最后一行的该值,其余行置空:
# 获取每组的最大日期 df['max'] = df.groupby('group')['date'].transform('max') # 仅保留每组最后一行的max值,其余设为空 df['max'] = df.apply( lambda row: row['max'] if row.name == df[df['group'] == row['group']].index[-1] else '', axis=1 ) # 可选:把日期转回原字符串格式 df['max'] = df['max'].apply(lambda x: x.strftime('%d.%m.%Y') if isinstance(x, pd.Timestamp) else x) df['date'] = df['date'].dt.strftime('%d.%m.%Y') # 删掉临时的group列 df.drop('group', axis=1, inplace=True)
最终输出
运行后就能得到符合要求的结果:
date max 0 01.01.2003 1 02.01.2003 2 03.01.2003 03.01.2003 3 05.01.2003 4 06.01.2003 06.01.2003
原代码出错原因
- 循环里
for i in df['date']的i是日期值,不是索引,用iloc[i+1]相当于把日期当整数索引用,完全不符合逻辑。 - 日期类型不能直接和整数1相减,必须用
pd.Timedelta(days=1)来做差值比较。
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

