基于日期区间的高效电价查询Python实现方案问询
高效电价匹配的Python实现方案
一、使用Pandas(推荐,处理大量时间序列数据)
Pandas专门针对时间序列和数据匹配做了优化,merge_asof或cut方法都能高效完成区间匹配,完全避免暴力遍历。
实现步骤:
- 将电价区间数据整理为DataFrame,并确保起始日期为datetime类型;
- 将每日能耗数据也转为带datetime日期的DataFrame;
- 使用
merge_asof按日期匹配对应的电价(需先对两个DataFrame的日期列排序)。
代码示例:
import pandas as pd # 1. 定义电价数据 tariff_data = pd.DataFrame({ 'start_date': pd.to_datetime(['2023-01-01', '2023-04-01', '2023-10-01']), 'unit_cost': [0.2384, 0.2761, 0.2566] }) # 2. 模拟每日能耗数据(示例) energy_usage = pd.DataFrame({ 'date': pd.date_range(start='2023-02-15', end='2023-11-20', freq='D'), 'daily_consumption': [10.5, 9.2, 11.1] * 90 # 模拟消耗量数据 }) # 3. 按日期匹配电价(merge_asof要求两边日期列已排序) tariff_data_sorted = tariff_data.sort_values('start_date') energy_usage_sorted = energy_usage.sort_values('date') # 匹配最近的不大于当前日期的start_date matched_data = pd.merge_asof( energy_usage_sorted, tariff_data_sorted, left_on='date', right_on='start_date', direction='backward' ) # 计算每日费用 matched_data['daily_cost'] = matched_data['daily_consumption'] * matched_data['unit_cost'] print(matched_data[['date', 'daily_consumption', 'unit_cost', 'daily_cost']].head())
二、使用标准库bisect(轻量场景,无第三方依赖)
如果不需要处理大规模数据,用标准库的bisect模块实现二分查找,时间复杂度为O(log n),比暴力遍历的O(n)高效得多。
实现步骤:
- 将电价的起始日期转换为时间戳(整数),并按顺序存储;
- 对应存储单价列表;
- 对任意日期,转换为时间戳后用
bisect.bisect_right找到插入位置,从而获取对应的单价。
代码示例:
import bisect from datetime import datetime # 定义电价数据(按起始日期升序排列) tariff_start_dates = [ datetime(2023, 1, 1), datetime(2023, 4, 1), datetime(2023, 10, 1) ] tariff_unit_costs = [0.2384, 0.2761, 0.2566] # 将日期转为时间戳(整数,方便二分查找) start_timestamps = [dt.timestamp() for dt in tariff_start_dates] def get_unit_cost(target_date): target_ts = target_date.timestamp() # 找到第一个大于target_ts的起始日期索引 idx = bisect.bisect_right(start_timestamps, target_ts) # 因为区间连续,对应索引为idx-1 return tariff_unit_costs[idx-1] if idx > 0 else None # 测试匹配 test_date1 = datetime(2023, 5, 10) test_date2 = datetime(2023, 12, 5) print(f"{test_date1.date()} 的单价: {get_unit_cost(test_date1)}") print(f"{test_date2.date()} 的单价: {get_unit_cost(test_date2)}") # 计算每日费用(模拟数据) daily_data = [ (datetime(2023, 3, 15), 8.7), (datetime(2023, 7, 20), 12.3), (datetime(2023, 11, 5), 9.8) ] for date, consumption in daily_data: cost = consumption * get_unit_cost(date) print(f"{date.date()}: 消耗量{consumption},费用{cost:.4f}")
方案对比
- Pandas:适合处理大规模时间序列数据,代码简洁,内置优化的算法,无需手动实现查找逻辑;
- bisect:适合轻量场景,无第三方依赖,代码轻量,查找效率高。
内容的提问来源于stack exchange,提问作者Gordon Mckeown
相关产品推荐
相关产品推荐

