You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含Datetime类型X值的二维双线性插值实现及绘图示例请求

双线性插值处理含Datetime坐标的DataFrame并绘图示例

我明白你的痛点——scipy.interpolate.interp2d不支持直接传入Datetime类型的坐标,而且原始数据是长格式的,需要整理成插值函数要求的结构。下面是针对你的DataFrame的完整解决方案,包含代码和可视化:

第一步:修正并生成原始数据

先把你提供的代码补全修正(比如import语句分开,确保数据生成逻辑正确):

import pandas as pd
import numpy as np
from scipy.interpolate import interp2d
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter

# 生成原始时间序列(5分钟间隔,共13个点)
time = pd.date_range('2018-05-14 00:00:00','2018-05-14 01:00:00',freq='5T')
# 生成y轴里程值(10个点)
mile = np.linspace(0,100,10)
# 构造长格式数据
x = list(time)*len(mile)
y = np.repeat(mile,len(time))
# 生成z值:每个mile组对应不同均值的正态分布
z = []
for i in range(0,10,1):
    z.extend(np.random.normal(loc=i*5, scale=5, size=len(time)))
origin_data = pd.DataFrame({'x':x, 'y':y ,'z':z})

第二步:将Datetime转换为数值类型

把Datetime类型的x转换成相对于起始时间的分钟数(比Unix时间戳更直观),这样就能满足interp2d的数值输入要求:

# 提取原始数据的起始时间
start_time = origin_data['x'].min()
# 将Datetime转为分钟数:(x - start_time).dt.total_seconds()/60
origin_data['x_num'] = (origin_data['x'] - start_time).dt.total_seconds() / 60

# 提取唯一的x_num和y值(interp2d需要一维的x、y输入)
x_unique = origin_data['x_num'].unique()
y_unique = origin_data['y'].unique()

# 将长格式数据转为二维矩阵(z_matrix的行对应y_unique,列对应x_unique)
z_matrix = origin_data.pivot(index='y', columns='x_num', values='z').values

第三步:准备目标插值点并执行插值

生成你需要的目标x(1分钟间隔)和y(固定值91),同样转换为数值类型,然后进行双线性插值:

# 生成目标时间序列(1分钟间隔)
target_x = pd.date_range('2018-05-14 00:00:00','2018-05-14 01:00:00',freq='1T')
# 转为分钟数
target_x_num = (target_x - start_time).dt.total_seconds() / 60
# 目标y值
target_y = np.array([91])

# 创建插值函数,指定kind='linear'实现双线性插值
interp_func = interp2d(x_unique, y_unique, z_matrix, kind='linear')
# 计算插值结果
target_z = interp_func(target_x_num, target_y)

# 将插值结果整理成DataFrame方便查看
result_df = pd.DataFrame({
    'x': target_x,
    'y': target_y.repeat(len(target_x)),
    'z': target_z.flatten()
})
print("插值结果前5行:")
print(result_df.head())

第四步:可视化原始数据与插值结果

用matplotlib绘制原始点的散点图,再叠加插值后的曲线,直观对比:

fig, ax1 = plt.subplots(figsize=(10,6))

# 绘制原始数据散点图
scatter = ax1.scatter(origin_data['x'], origin_data['y'], c=origin_data['z'], cmap='viridis', alpha=0.6, label='原始数据点')
# 设置x轴日期格式
ax1.xaxis.set_major_formatter(DateFormatter('%H:%M'))
ax1.set_xlabel('时间')
ax1.set_ylabel('里程')
ax1.set_title('原始数据与插值结果对比')

# 绘制插值结果曲线(y=91处的z值随时间变化)
ax2 = ax1.twinx()
ax2.plot(target_x, result_df['z'], color='red', linewidth=2, label='y=91处插值结果')
ax2.set_ylabel('z值')

# 添加图例
fig.legend(loc='upper right', bbox_to_anchor=(1.15, 1))
# 添加颜色条
plt.colorbar(scatter, ax=ax1, label='原始z值')

plt.tight_layout()
plt.show()

关键说明

  • Datetime转数值:这里用相对分钟数,既保留了时间的连续性,又避免了Unix时间戳的大数问题,插值结果更稳定。
  • 数据格式转换:pivot方法把长格式的DataFrame转成二维矩阵,完美匹配interp2d对z输入的要求(z必须是二维数组,对应x和y的网格)。
  • 双线性插值:通过kind='linear'指定双线性插值,这是interp2d的默认选项,明确指定能确保插值效果符合预期。

内容的提问来源于stack exchange,提问作者YQ.Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:36:06