问题回顾
上一篇文章我们最终画到了这样的图
这里我们知道它并非直线,但在图片中直接观察,我们看不到这样的效果。
matplotlib给出了一些默认非线性化的轴,显然我的不适用。
解决办法
然后我就去查api了
看不懂…
但是多多少少还是有些收获,里面指出了非线性化轴的思想:对这个轴重新映射投影。
例如:这样一组值:[1,10,20,50,80,100,500,1000]
我们使用一些非线性化函数来缩短他们值之间的差距。
这里的非线性函数我使用的是x^n次方的反函数相当于y(1/n),选取奇函数大于0的那半只,在负号情况下使用添加符号的方法使其成为奇函数,避免重复值。
我们先来看一下x^n的走势
**可以发现x^n都通过(0,0)和(1,1)这点,对于0-1之间的数,n越大,变化的越剧烈,同样的在1到正无穷上,越大的数变化的越快。我们恰巧使用的就是这一部分。
例如:1-2与100-101,两者相差1,但在n=2时,一个是1-4,一个是10000-10201。x轴上同样的距离表示了两个数值上差许多数量级的数。
我们的非线性化轴就是要表示这种效果。对于等距的轴,每一段表示的数值并不相等
现在你把上面的图像旋转九十度,把y作为输入,x为输出,是不是就变成了输入差距很大,但在输出的时候变化不大了?
而这个变化大小取决于n的选取,正向时n越大,输出变化越大,反过来1/n时同样变化距离,原数据的输出变化越大。也就是说你的原始数据差距越大,就应该吧n调大,来减小特别大的值占用轴的空间。
代码
import numpy
from matplotlib import pyplot
def nolinear_plot_test(i_data,num,level):
i_len=len(i_data)#取输入数据数量
o_step=int(i_len/num)#计算步长并向下取整
o_lable=i_data[0:i_len:o_step]#取要标记的标签值lables
real_value=list(range(0,i_len,1))
for i in range(0,i_len,1):#非线性函数,输出变化后实际横轴的值
if (i_data[i])>=0:
real_value[i]=(i_data[i])**(1/level)
else:
real_value[i] = -((-i_data[i]) ** (1 /level))
o_ticks=real_value[0:i_len:o_step]#取要标记的轴值ticks
return real_value,o_ticks,o_lable
i_data是你要改变的那个轴原始数据,num是你显示的值的数量,level是你想设置的非线性化程度最好是奇数,偶数我还没有试过。
输出中,real_value是你绘图时使用的坐标轴上的值,o_ticks与o_lable是在修正这个轴标签时使用。
绘图时替换原始的轴数据,这我替换的是y轴的
pyplot.plot(x1,real_value,color='green')
然后用ticks修正轴上的显示
pyplot.yticks(ticks=o_ticks,labels=o_lable)
对之前的图进行一下处理(下面是处理了x轴的效果,y轴不需要处理),这次能看出来是曲线了,坐标轴可能显示还是有些不尽人意,但还可以接受