如何通过Pandas DataFrame映射生成新列:匹配时间获日期与温度
Pandas时间范围匹配:从Lookup表映射日期与温度
现有两个Pandas DataFrame:
import pandas as pd df1 = pd.DataFrame({ 'temperature': ['cold', 'warm', 'hot'], 'Mon_start': ['1:00', '7:00', '4:00'], 'Mon_end': ['3:00', '8:00', '6:00'], 'Tues_start': ['9:00', '16:00', '12:00'], 'Tues_end': ['10:00', '20:00', '14:00'] }) df2 = pd.DataFrame({ 'sample1': ['A', 'A', 'B', 'B'], 'data_value': ['2:00', '7:30', '18:00', '9:45'] })
需求:以df1为查找表,检查df2的data_value是否落在某一日期的起止时间范围内,匹配后为df2新增day(对应日期)和temperature(对应温度)列,期望输出:
sample1 data_value day temperature 0 A 2:00 Mon cold 1 A 7:30 Mon warm 2 B 18:00 Tues warm 3 B 9:45 Tues cold
由于数据量较大,避免低效循环,以下是高效实现方案:
步骤1:转换时间格式为可比较的时间差类型
将所有时间字符串转换为timedelta类型,方便后续范围判断:
# 转换df1的时间列 time_cols = [col for col in df1.columns if '_start' in col or '_end' in col] df1[time_cols] = df1[time_cols].apply(pd.to_timedelta) # 转换df2的data_value df2['data_value'] = pd.to_timedelta(df2['data_value'])
步骤2:重塑df1为长格式(宽表转窄表)
把每个日期的起止时间与温度对应,形成一行一个匹配规则的结构:
# 拆分Mon和Tues的规则 mon_df = df1[['temperature', 'Mon_start', 'Mon_end']].rename( columns={'Mon_start': 'start', 'Mon_end': 'end'} ).assign(day='Mon') tues_df = df1[['temperature', 'Tues_start', 'Tues_end']].rename( columns={'Tues_start': 'start', 'Tues_end': 'end'} ).assign(day='Tues') # 合并为规则表 rules_df = pd.concat([mon_df, tues_df], ignore_index=True)
此时rules_df的结构为:
| temperature | start | end | day |
|---|---|---|---|
| cold | 01:00:00 | 03:00:00 | Mon |
| warm | 07:00:00 | 08:00:00 | Mon |
| hot | 04:00:00 | 06:00:00 | Mon |
| cold | 09:00:00 | 10:00:00 | Tues |
| warm | 16:00:00 | 20:00:00 | Tues |
| hot | 12:00:00 | 14:00:00 | Tues |
步骤3:高效匹配时间范围
利用IntervalIndex快速判断每个data_value属于哪个时间区间,再关联对应的day和temperature:
# 创建时间区间索引 intervals = pd.IntervalIndex.from_arrays(rules_df['start'], rules_df['end'], closed='both') # 找到每个data_value对应的区间索引 match_idx = df2['data_value'].apply(lambda x: intervals.get_loc(x)) # 关联规则表的结果 result = df2.join(rules_df.loc[match_idx, ['day', 'temperature']].reset_index(drop=True))
执行后result就是期望的输出。
为什么不用循环或np.vectorize?
- 循环遍历会导致时间复杂度随数据量线性增长,数据量大时效率极低。
np.vectorize本质上还是循环,并没有真正实现向量化加速,只是语法上更简洁。- 上述方案利用Pandas的内置数据结构(IntervalIndex)和向量化操作,效率远高于循环,适合处理大规模数据。
内容的提问来源于stack exchange,提问作者MAtennis9
相关产品推荐
相关产品推荐

