基于ID及播种-收获日期区间筛选数据行的实现问询
解决方案:按ID对应的播种/收获日期筛选时间区间内的数据
前提准备:统一日期格式
首先确保所有日期列都是datetime类型,否则无法正确比较:
import pandas as pd # 示例数据 df = pd.DataFrame({ 'ID': ['106', '106', '106', '107', '107'], 'time': ['2020-03-15', '2020-05-20', '2020-11-10', '2020-06-01', '2020-09-30'], 'sowing_date': ['2020-04-21', '2020-04-21', '2020-04-21', '2020-05-10', '2020-05-10'], 'harvesting_date': ['2020-11-01', '2020-11-01', '2020-11-01', '2020-10-01', '2020-10-01'] }) # 转换为datetime类型 for col in ['time', 'sowing_date', 'harvesting_date']: df[col] = pd.to_datetime(df[col])
方法1:直接布尔索引(最简洁高效)
如果同一ID的sowing_date和harvesting_date在所有行中重复,直接逐行判断时间是否在区间内即可:
filtered_df = df[(df['time'] >= df['sowing_date']) & (df['time'] <= df['harvesting_date'])]
执行后会保留ID106中2020-05-20的行,ID107中2020-06-01和2020-09-30的行,符合需求。
方法2:合并日期配置表(适用于日期单独存储的场景)
如果播种/收获日期是单独的配置表(每个ID仅存一行日期),先合并原数据和配置表,再筛选:
# 示例ID日期配置表 id_date_config = pd.DataFrame({ 'ID': ['106', '107'], 'sowing_date': ['2020-04-21', '2020-05-10'], 'harvesting_date': ['2020-11-01', '2020-10-01'] }) id_date_config['sowing_date'] = pd.to_datetime(id_date_config['sowing_date']) id_date_config['harvesting_date'] = pd.to_datetime(id_date_config['harvesting_date']) # 合并数据 merged_df = df.merge(id_date_config, on='ID') # 筛选区间内的数据 filtered_df = merged_df[(merged_df['time'] >= merged_df['sowing_date']) & (merged_df['time'] <= merged_df['harvesting_date'])]
方法3:GroupBy + Transform(解决你之前groupby未达预期的问题)
如果一定要用groupby,核心是用transform把每个ID的日期广播到所有行,再做筛选:
# 提取每个ID的播种/收获日期(取组内第一个值,确保同一ID日期统一) df['group_sowing'] = df.groupby('ID')['sowing_date'].transform('first') df['group_harvest'] = df.groupby('ID')['harvesting_date'].transform('first') # 筛选时间在区间内的行 filtered_df = df[(df['time'] >= df['group_sowing']) & (df['time'] <= df['group_harvest'])] # 可删除临时生成的列 filtered_df = filtered_df.drop(['group_sowing', 'group_harvest'], axis=1)
之前groupby没成功大概率是没用到transform,直接对分组做操作无法将日期映射回原数据的每一行。
内容的提问来源于stack exchange,提问作者Sak
相关产品推荐
相关产品推荐

