9
votes

Calculer intelligemment des positions de tickerie de cartes

Tout ce que j'utilise Matplotlib, des diagrammes en flash Open-Flash ou d'autres graphiques, j'ai toujours terminé de trouver un moyen de définir des limites et des intervalles d'échelle X / Y puisque les produits ne sont pas assez intelligents (ou pas du tout ... )

Essayez simplement ceci dans pylab (ipythton -pylab) pour comprendre ce que je veux dire: xxx

Vous verrez juste et vide la grille de cadre masquant les 2 lignes horizontales sous C'est ses bordures supérieures et inférieures.

Je me demande s'il y a un algorithme autour (que je peux porter à Python) pour définir des limites et des étapes clôturées élégamment supérieures et inférieures et de calculer toutes les valeurs montrant l'épaisseur X. < P> Par exemple, disons que j'ai 475 mesures comme (datetétime, température) comme (x, y) avec xxx

(une toutes les 5 minutes) et xxx

Ma suggestion pour ce cas particulier pourrait être de définir:

26.4 <= y__scale <= 28.4 avec un épaisseur tous les .2

et une tique sur x_scale tous les 12 éléments (une fois par heure).

mais qu'en est-il de seulement 20 mesures sur 20 jours avec -21.5 , et ainsi de suite? Y a-t-il une méthode standardisée autour?


0 commentaires

4 Réponses :


11
votes

Ce qui suit est ce que j'ai utilisé pendant des années, ce qui est simple et qui fonctionne assez bien. Pardonne-moi pour que cela soit c mais traduire en python ne devrait pas être difficile.

La fonction suivante est nécessaire et provient des gemmes graphiques Volume 1. P>

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


1 commentaires

Plus j'utilise cela, plus je trouve cela vraiment intelligent, merci pour le partage.



5
votes

Je signalez ici ma version Python de Code ci-dessus si elle peut être de toute aide pour une personne: xxx pré>

Utiliser comme: p> xxx pré>

Ajoutez également un portage JavaScript: P>

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


1 commentaires

Vous pouvez utiliser math.log10 () dans javascript.



0
votes

Vous trouverez ci-dessous mon code Python pour calculer automatiquement les ticks, il a besoin de la plage de données et du nombre maximum de tiques.

Par exemple: P>

def auto_tick(data_range, max_tick=10, tf_inside=False):
    """
    tool function that automatically calculate optimal ticks based on range and the max number of ticks
    :param data_range:   range of data, e.g. [-0.1, 0.5]
    :param max_tick:     max number of ticks, an interger, default to 10
    :param tf_inside:    True/False if only allow ticks to be inside
    :return:             list of ticks
    """
    data_span = data_range[1] - data_range[0]
    scale = 10.0**np.floor(np.log10(data_span))    # scale of data as the order of 10, e.g. 1, 10, 100, 0.1, 0.01, ...
    list_tick_size_nmlz = [5.0, 2.0, 1.0, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]   # possible tick sizes for normalized data in range [1, 10]
    tick_size_nmlz = 1.0     # initial tick size for normalized data
    for i in range(len(list_tick_size_nmlz)):                 # every loop reduces tick size thus increases tick number
        num_tick = data_span/scale/list_tick_size_nmlz[i]     # number of ticks for the current tick size
        if num_tick > max_tick:                               # if too many ticks, break loop
            tick_size_nmlz = list_tick_size_nmlz[i-1]
            break
    tick_size = tick_size_nmlz * scale             # tick sizse for the original data
    ticks = np.unique(np.arange(data_range[0]/tick_size, data_range[1]/tick_size).round())*tick_size    # list of ticks

    if tf_inside:     # if only allow ticks within the given range
        ticks = ticks[ (ticks>=data_range[0]) * (ticks<=data_range[1])]

    return ticks


0 commentaires

0
votes

et voici la version de @uesp Réponse dans TypeScript / JavaScript ES6:

function niceNumber(value: number, round = false) {

  const exponent = Math.floor(Math.log10(value));
  const fraction = value / Math.pow(10, exponent);

  let niceFraction: number;

  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 * Math.pow(10, exponent);

}

export function calcTicks(minValue: number, maxValue: number, ticksCount: number) {

  const range = niceNumber(maxValue - minValue);

  const tickValue = niceNumber(range / (ticksCount - 1), true);

  const ticks: number[] = [];
  for (let i = 0; i < ticksCount; i++) {
    ticks.push(minValue + tickValue * i);
  }

  return ticks;

}


0 commentaires