智能计算图表刻度位置

2024-10-01 13:33:06 发布

您现在位置:Python中文网/ 问答频道 /正文

无论我在使用matplotlib、openflash图表还是其他图表框架,我总是需要找到一种方法来设置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)

你会看到一个空的框架网格在它的上下边界下隐藏了两条水平线。在

我想知道是否有一些算法(我可以移植到python)来巧妙地设置y的上下极限和步数,并计算出每个值显示x的厚度。在

例如,假设我有475个度量值作为(datetime, temperature)作为(x, y)

^{pr2}$

(每5分钟一次)和

26.5 < temperature < 28.3

我对这个案例的建议是:

26.4 <= y_scale <= 28.4 with a thick every .2

每12项(每小时一次)在x_scale上打勾。在

但是如果我在20天内用-21.5 < temperature < 38.7来做20次测量呢?有标准化的方法吗?在


Tags: 方法函数in框架间隔plotmatplotlibnp
3条回答

我在这里报告我的python版本的上述C代码,如果它可能有任何帮助的人:

import math

def nice_number(value, round_=False):
    '''nice_number(value, round_=False) -> float'''
    exponent = math.floor(math.log(value, 10))
    fraction = value / 10 ** exponent

    if round_:
        if fraction < 1.5: nice_fraction = 1.
        elif fraction < 3.: nice_fraction = 2.
        elif fraction < 7.: nice_fraction = 5.
        else: niceFraction = 10.
    else:
        if fraction <= 1: nice_fraction = 1.
        elif fraction <= 2: nice_fraction = 2.
        elif fraction <= 5: nice_fraction = 5.
        else: nice_fraction = 10.

    return nice_fraction * 10 ** exponent

def nice_bounds(axis_start, axis_end, num_ticks=10):
    '''
    nice_bounds(axis_start, axis_end, num_ticks=10) -> tuple
    @return: tuple as (nice_axis_start, nice_axis_end, nice_tick_width)
    '''
    axis_width = axis_end - axis_start
    if axis_width == 0:
        nice_tick = 0
    else:
        nice_range = nice_number(axis_width)
        nice_tick = nice_number(nice_range / (num_ticks -1), round_=True)
        axis_start = math.floor(axis_start / nice_tick) * nice_tick
        axis_end = math.ceil(axis_end / nice_tick) * nice_tick

    return axis_start, axis_end, nice_tick

用作:

^{pr2}$

还要添加javascript移植:

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
    }
}

以下是我多年来使用的方法,它很简单,效果很好。请原谅我是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);
 }

像下面的例子一样,根据您希望显示的主刻度数选择轴的“良好”起点/终点。如果不关心刻度,可以将其设置为常量(例如:10)。在

^{pr2}$

下面是我的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代码

^{pr2}$

相关问题 更多 >