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

使用TimedeltaIndex时matplotlib fill_between绘图报错咨询

matplotlib fill_between触发DTypePromotionError的原因及解决办法

问题场景

使用matplotlib.pyplot.fill_between绘制填充图时,当索引为pandas.TimedeltaIndex且序列值为浮点数时,会抛出DTypePromotionError,示例代码如下:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

idx = pd.TimedeltaIndex(['0 days 00:00:00', '0 days 06:00:00', '0 days 12:00:00', '0 days 18:00:00'],
                        dtype='timedelta64[ns]', freq='6H')
ts1 = pd.Series(np.array([  0., 5439.802205, 4506.0691, 640.734375]), index=idx)
ts2 = pd.Series(np.array([747., 740.4, 717., 740.4]), index=idx)

plt.figure()
plt.fill_between(ts1.index, ts1, ts2, where=(ts1 > ts2))
plt.fill_between(ts1.index, ts1, ts2, where=(ts1 <= ts2))
plt.show()

错误信息

DTypePromotionError: The DType <class 'numpy.dtypes.TimeDelta64DType'> could not be promoted by <class 'numpy.dtypes.Float64DType'>. This means that no common DType exists for the given inputs. For example they cannot be stored in a single array unless the dtype is `object`. The full list of DTypes is: (<class 'numpy.dtypes.TimeDelta64DType'>, <class 'numpy.dtypes.Float64DType'>)

可正常运行的对照场景

  • 不使用TimedeltaIndex:仅保留浮点数序列,使用默认整数索引时可正常绘图。
  • 保留TimedeltaIndex但使用整数序列:将序列值替换为整数范围,绘图无报错。

原因分析

这个问题的核心是numpy的类型提升规则与matplotlib内部处理逻辑的冲突:

  • 调用fill_between时,matplotlib会尝试将传入的索引(TimedeltaIndex本质是timedelta64[ns]类型)和序列值进行内部数值对齐与计算。
  • 对于整数序列,timedelta64类型可以和int64隐式提升(因为时间差本质是整数纳秒计数),因此能兼容处理。
  • 但float64(浮点数序列)与timedelta64之间没有公共的可兼容 dtype——numpy不支持这两种类型的直接转换或提升,除非转为object类型,而matplotlib的内部数值计算逻辑不允许这种低效的object类型操作,因此抛出类型提升错误。
  • 当使用默认整数索引时,整数索引可与浮点数序列正常提升为float64类型,因此不会触发冲突。

解决方案

将TimedeltaIndex转换为matplotlib可直接处理的数值类型(如总小时数、总秒数)即可解决问题,示例代码如下:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

idx = pd.TimedeltaIndex(['0 days 00:00:00', '0 days 06:00:00', '0 days 12:00:00', '0 days 18:00:00'],
                        dtype='timedelta64[ns]', freq='6H')
# 将TimedeltaIndex转换为总小时数的数值数组
x_values = idx.total_seconds() / 3600

ts1 = pd.Series(np.array([  0., 5439.802205, 4506.0691, 640.734375]), index=idx)
ts2 = pd.Series(np.array([747., 740.4, 717., 740.4]), index=idx)

plt.figure()
plt.fill_between(x_values, ts1, ts2, where=(ts1 > ts2))
plt.fill_between(x_values, ts1, ts2, where=(ts1 <= ts2))
# 手动设置x轴标签,还原时间差格式
plt.xticks(x_values, idx.astype(str))
plt.show()

内容的提问来源于stack exchange,提问作者CodeNStuff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:45:14