hist绘制np.log转换数据时触发[-inf,-inf]范围非有限ValueError
问题描述
绘制图表时执行如下代码行:
sub3.hist(x=np.log(df[i]), bins = 100, color="grey")
抛出错误:
ValueError: supplied range of [-inf, -inf] is not finite.
其中df与df_norm是存储数据完全一致的pandas DataFrame,区别仅在于df_norm经过了minmax归一化处理,完整绘图代码如下:
tb = widgets.TabBar([str(c) for c in range(16)]) k = 0 for c in range(len(df_norm.columns)): with tb.output_to(c, select=(c < 3)): colours = ["orange", "green"] fig = plt.figure(figsize=(20, 5)) plt.subplots_adjust(bottom = 0., left = 0, top = 1., right = 1) p = 0 g = 1 for i in df_norm.columns[k:k+2]: sub1 = fig.add_subplot(2,3,g) sub1.hist(x=df[i], bins = 100, alpha=0.3, color=colours[p]) sub2 = fig.add_subplot(2,3,g+1) sub2.hist(x=df_norm[i], bins = 100, alpha=0.3, color=colours[p]) sub3 = fig.add_subplot(2,3,g+2) sub3.hist(x=np.log(df[i]), bins = 100, color="grey") sub1.set_title(i) sub2.set_title('title ' + i) sub3.set_title('title ' + i) sub1.set_ylabel('label') p = p + 1 k = k + 1 g = g + 3
完整错误堆栈跟踪如下:
ValueError Traceback (most recent call last) <ipython-input-179-d6170fc0d99d> in <module>() 20 sub2.hist(x=df_norm[i], bins = 100, alpha=0.3, color=colours[p]) 21 sub3 = fig.add_subplot(2,3,g+2) # two rows, two columns, second cell ---> 22 sub3.hist(x=np.log(df[i]), bins = 100, color="grey") 23 sub1.set_title(i) 24 sub2.set_title('title ' + i) 4 frames <__array_function__ internals> in histogram(*args, **kwargs) /usr/local/lib/python3.7/dist-packages/numpy/lib/histograms.py in _get_outer_edges(a, range) 314 if not (np.isfinite(first_edge) and np.isfinite(last_edge)): 315 raise ValueError( ---> 316 "supplied range of [{}, {}] is not finite".format(first_edge, last_edge)) 317 elif a.size == 0: 318 # handle empty arrays. Can't determine range, so use 0-1. ValueError: supplied range of [-inf, -inf] is not finite
错误原因
这个报错逻辑非常直接:传给np.log()的df[i]列里,所有有效值都小于等于0。
- 自然对数
np.log()仅支持大于0的实数作为输入:输入0时计算结果为-inf(负无穷),输入负数时结果为nan(非数值) - 整列数据计算对数后不存在任何有限数值,numpy生成直方图自动计算数值边界时,拿到的最大、最小值全是
-inf,就会触发“范围不是有限值”的报错。
修复方法
- 先定位异常列:代码跑到报错位置时,直接执行
print(df[i].min())查看当前遍历列的最小值,即可确认是否全为0或负数 - 调整对数变换逻辑,不要直接硬算:
- 如果列中只有0和正数,把
np.log(df[i])替换为np.log1p(df[i])即可,该函数原生计算log(1+x),天然兼容x=0的场景,比手动加极小值偏移的方式更准确 - 如果列中存在负数,先匹配数据业务逻辑处理:允许数值平移的场景,可以给整列加一个足够大的常数把所有值抬到0以上再做对数变换;如果负数属于异常脏数据,先过滤无效值再绘图
- 如果列中只有0和正数,把
- 可以加一步前置校验:对数变换完成后执行
np.isfinite(变换后数组).all(),返回True就说明不存在无穷值、非数值,可正常传入绘图。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

