Python 智能计算图表刻度位置
无论我在使用matplotlib、Open Flash Charts或其他图表框架,我最终都需要找到一种方法来设置x/y比例限制和间隔,因为内置程序不够智能(或者根本没有…) 只要在pylab(ipyhton-pylab)中尝试一下,就可以理解我的意思:Python 智能计算图表刻度位置,python,math,graph,Python,Math,Graph,无论我在使用matplotlib、Open Flash Charts或其他图表框架,我最终都需要找到一种方法来设置x/y比例限制和间隔,因为内置程序不够智能(或者根本没有…) 只要在pylab(ipyhton-pylab)中尝试一下,就可以理解我的意思: In [1]: a, b, x = np.zeros(10), np.ones(10), np.arange(10) In [2]: plot(x, a); plot(x, b) 您将看到在其顶部和底部边界下隐藏了两条水平线的空框架网格 我
In [1]: a, b, x = np.zeros(10), np.ones(10), np.arange(10)
In [2]: plot(x, a); plot(x, b)
您将看到在其顶部和底部边界下隐藏了两条水平线的空框架网格
我想知道是否有一些算法(我可以移植到python中)可以巧妙地设置顶部和底部的y限制和步骤,并计算每多少个值显示x厚度
例如,假设我有475个度量值作为(日期时间,温度)
作为(x,y)
2011-01-15 10:45:00 < datetime < 2011-01-17 02:20:00
2011-01-15 10:45:00
(每5分钟一次)和
26.5<温度<28.3
我对这一特殊情况的建议是:
26.4以下是我多年来一直使用的方法,非常简单,效果也很好。请原谅我使用C语言,但将其翻译成Python应该并不困难
以下功能是必需的,来自Graphic Gems第1卷
double NiceNumber (const double Value, const int Round) {
int Exponent;
double Fraction;
double NiceFraction;
Exponent = (int) floor(log10(Value));
Fraction = Value/pow(10, (double)Exponent);
if (Round) {
if (Fraction < 1.5)
NiceFraction = 1.0;
else if (Fraction < 3.0)
NiceFraction = 2.0;
else if (Fraction < 7.0)
NiceFraction = 5.0;
else
NiceFraction = 10.0;
}
else {
if (Fraction <= 1.0)
NiceFraction = 1.0;
else if (Fraction <= 2.0)
NiceFraction = 2.0;
else if (Fraction <= 5.0)
NiceFraction = 5.0;
else
NiceFraction = 10.0;
}
return NiceFraction*pow(10, (double)Exponent);
}
我在这里报告上述C代码的python版本,如果它对某人有帮助的话:
导入数学
def nice_编号(值,四舍五入=False):
''nice_number(value,round_u=False)->float''
指数=math.floor(math.log(值,10))
分数=值/10**指数
如果是圆形:
如果分数<1.5:
很好的分数=1。
elif分数<3:
很好的分数=2。
elif分数<7:
很好的分数=5。
其他:
很好的分数=10。
其他:
如果下面的分数是自动计算刻度的python代码,那么它需要数据范围和最大刻度数
例如:
auto_tick([-120, 580], max_tick=10, tf_inside=False)
Out[224]: array([-100., -0., 100., 200., 300., 400., 500.])
auto_tick([-120, 580], max_tick=20, tf_inside=False)
Out[225]: array([-100., -50., -0., 50., 100., 150., 200., 250., 300., 350., 400., 450., 500., 550.])
下面是函数的Python代码
def auto_tick(数据范围,最大刻度=10,tf_inside=False):
"""
根据范围和最大刻度数自动计算最佳刻度的工具功能
:param data_range:数据范围,例如[0.1,0.5]
:param max_tick:最大刻度数,整数,默认为10
:param tf_inside:如果仅允许勾号在内部,则为真/假
:return:勾号列表
"""
数据范围=数据范围[1]-数据范围[0]
比例=10.0**np.楼层(np.log10(数据跨度))#数据比例为10,例如1、10、100、0.1、0.01。。。
列出_tick_size_nmlz=[5.0,2.0,1.0,0.5,0.2,0.1,0.05,0.02,0.01]#范围[1,10]内规范化数据的可能刻度大小
刻度大小\u nmlz=1.0#标准化数据的初始刻度大小
对于范围内的i(len(list_tick_size_nmlz)):#每个循环减少tick size,从而增加tick number
num_tick=data_span/scale/list_tick_size_nmlz[i]#当前刻度大小的刻度数
如果num_tick>max_tick:#如果tick过多,则中断循环
勾选大小=列表勾选大小[i-1]
打破
勾选大小=勾选大小nmlz*比例#勾选原始数据的大小
ticks=np.unique(np.arange(数据范围[0]/tick大小,数据范围[1]/tick大小)。round())*tick大小#ticks列表
如果tf_在内部:#如果只允许在给定范围内打勾
ticks=ticks[(ticks>=data_range[0])*(ticks,以下是in-TypeScript/JavaScript ES6的版本:
函数niceNumber(值:number,舍入=false){
常数指数=Math.floor(Math.log10(值));
常数分数=数值/数学功率(10,指数);
让分数:数字;
if(圆形){
如果(分数<1.5){
平均分数=1.0;
}否则如果(分数<3.0){
平均分数=2.0;
}否则如果(分数<7.0){
平均分数=5.0;
}否则{
平均分数=10.0;
}
}否则{
如果(分数)我使用得越多,我就越觉得它真的很聪明,谢谢分享。你可以在JavaScript中使用Math.log10()。
//Input parameters
double AxisStart = 26.5;
double AxisEnd = 28.3;
double NumTicks = 10;
double AxisWidth;
double NewAxisStart;
double NewAxisEnd;
double NiceRange;
double NiceTick;
/* Check for special cases */
AxisWidth = AxisEnd - AxisStart;
if (AxisWidth == 0.0) return (0.0);
/* Compute the new nice range and ticks */
NiceRange = NiceNumber(AxisEnd - AxisStart, 0);
NiceTick = NiceNumber(NiceRange/(NumTicks - 1), 1);
/* Compute the new nice start and end values */
NewAxisStart = floor(AxisStart/NiceTick)*NiceTick;
NewAxisEnd = ceil(AxisEnd/NiceTick)*NiceTick;
AxisStart = NewAxisStart; //26.4
AxisEnd = NewAxisEnd; //28.4
>>> nice_bounds(26.5, 28.3)
(26.4, 28.4, 0.2)
function nice_number(value, round_){
//default value for round_ is false
round_ = round_ || false;
// :latex: \log_y z = \frac{\log_x z}{\log_x y}
var exponent = Math.floor(Math.log(value) / Math.log(10));
var fraction = value / Math.pow(10, exponent);
if (round_)
if (fraction < 1.5)
nice_fraction = 1.
else if (fraction < 3.)
nice_fraction = 2.
else if (fraction < 7.)
nice_fraction = 5.
else
nice_fraction = 10.
else
if (fraction <= 1)
nice_fraction = 1.
else if (fraction <= 2)
nice_fraction = 2.
else if (fraction <= 5)
nice_fraction = 5.
else
nice_fraction = 10.
return nice_fraction * Math.pow(10, exponent)
}
function nice_bounds(axis_start, axis_end, num_ticks){
//default value is 10
num_ticks = num_ticks || 10;
var axis_width = axis_end - axis_start;
if (axis_width == 0){
axis_start -= .5
axis_end += .5
axis_width = axis_end - axis_start
}
var nice_range = nice_number(axis_width);
var nice_tick = nice_number(nice_range / (num_ticks -1), true);
var axis_start = Math.floor(axis_start / nice_tick) * nice_tick;
var axis_end = Math.ceil(axis_end / nice_tick) * nice_tick;
return {
"min": axis_start,
"max": axis_end,
"steps": nice_tick
}
}
auto_tick([-120, 580], max_tick=10, tf_inside=False)
Out[224]: array([-100., -0., 100., 200., 300., 400., 500.])
auto_tick([-120, 580], max_tick=20, tf_inside=False)
Out[225]: array([-100., -50., -0., 50., 100., 150., 200., 250., 300., 350., 400., 450., 500., 550.])