Выбор привлекательной линейной шкалы для оси Y графика

Вот простейший код для извлечения кода

:

      # importing required modules
      import PyPDF2

      # creating a pdf file object
      pdfFileObj = open('filename.pdf', 'rb')

      # creating a pdf reader object
      pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

      # printing number of pages in pdf file
      print(pdfReader.numPages)

      # creating a page object
      pageObj = pdfReader.getPage(5)

      # extracting text from page
      print(pageObj.extractText())

      # closing the pdf file object
      pdfFileObj.close()
74
задан An̲̳̳drew 21 January 2009 в 13:36
поделиться

5 ответов

Давным-давно я записал модуль графика, который покрыл это приятно. Закапывание серой массы получает следующее:

  • Определяют нижнюю и верхнюю границу данных. (Остерегайтесь особого случая где нижняя граница = верхняя граница!
  • Делят диапазон на необходимое количество галочек.
  • Округляют в большую сторону диапазон галочки в хорошие суммы.
  • Корректируют нижнюю и верхнюю границу соответственно.

Позволяет, берут Ваш пример:

15, 234, 140, 65, 90 with 10 ticks
  1. нижняя граница = 15
  2. верхняя граница = 234
  3. диапазон = 234-15 = 219
  4. диапазон галочки = 21.9. Это должно быть 25.0
  5. новая нижняя граница = 25 * раунд (15/25) = 0
  6. новая верхняя граница = 25 * раунд (1+235/25) = 250

Так диапазон = 0,25,50..., 225,250

можно получить хороший диапазон галочки со следующими шагами:

  1. делятся на 10^x таким образом, что результат находится между 0,1 и 1.0 (включая 0,1, исключая 1).
  2. переводят соответственно:
    • 0.1-> 0.1
    • < = 0.2-> 0.2
    • < = 0.25-> 0.25
    • < = 0.3-> 0.3
    • < = 0.4-> 0.4
    • < = 0.5-> 0.5
    • < = 0.6-> 0.6
    • < = 0.7-> 0.7
    • < = 0.75-> 0.75
    • < = 0.8-> 0.8
    • < = 0.9-> 0.9
    • < = 1.0-> 1.0
  3. умножаются 10^x.

В этом случае, 21.9 разделен на 10^2 для получения 0.219. Это - < = 0.25, таким образом, мы теперь имеем 0.25. Умноженный на 10^2 это дает 25.

Позволяет, смотрят на тот же пример с 8 галочками:

15, 234, 140, 65, 90 with 8 ticks
  1. нижняя граница = 15
  2. верхняя граница = 234
  3. диапазон = 234-15 = 219
  4. диапазон галочки = 27.375
    1. Делится на 10^2 для 0,27375, переводит в 0,3, который дает (умноженный на 10^2) 30.
  5. новая нижняя граница = 30 * раунд (15/30) = 0
  6. новая верхняя граница = 30 * раунд (1+235/30) = 240

, Которые дают результат, который Вы запросили;-).

------Добавленный KD------

Вот код, который достигает этого алгоритма, не используя таблицы поиска, и т.д....:

double range = ...;
int tickCount = ...;
double unroundedTickSize = range/(tickCount-1);
double x = Math.ceil(Math.log10(unroundedTickSize)-1);
double pow10x = Math.pow(10, x);
double roundedTickRange = Math.ceil(unroundedTickSize / pow10x) * pow10x;
return roundedTickRange;

Вообще говоря, количество галочек включает нижнюю галочку, таким образом, фактические сегменты оси y являются тем меньше, чем количество галочек.

93
ответ дан Toon Krijthe 7 November 2019 в 07:41
поделиться

Кажется, что вызывающая сторона не говорит Вам диапазоны, которые это хочет.

, Таким образом, Вы свободны к измененному конечные точки, пока Вы не получаете его приятно делимый Вашим количеством маркировки.

Позволяют нам определить "хороший". Я назвал бы хорошим, если маркировки выключены:

1. 2^n, for some integer n. eg. ..., .25, .5, 1, 2, 4, 8, 16, ...
2. 10^n, for some integer n. eg. ..., .01, .1, 1, 10, 100
3. n/5 == 0, for some positive integer n, eg, 5, 10, 15, 20, 25, ...
4. n/2 == 0, for some positive integer n, eg, 2, 4, 6, 8, 10, 12, 14, ...

Находят макс. и минута Вашего ряда данных. Давайте назовем эти точки:

min_point and max_point.

Теперь все, что необходимо сделать, является находкой, 3 значения:

- start_label, where start_label < min_point and start_label is an integer
- end_label, where end_label > max_point and end_label is an integer
- label_offset, where label_offset is "nice"

, которые соответствуют уравнению:

(end_label - start_label)/label_offset == label_count

существует, вероятно, много решений, поэтому просто выбирают то. Большую часть времени я держал пари, что можно установить

start_label to 0

, поэтому просто пробуют различное целое число

end_label

, пока смещение не "хорошо"

6
ответ дан Pyrolistical 7 November 2019 в 07:41
поделиться

Вот большой ответ Toon Krijtje в JavaScript

const makeYAxis = (min,max,tickCount) => {
    const result = [];
    const range = Math.abs(max-min);
    const stepSizeUnrounded = range / ( tickCount-1 );
    const pow10x = Math.pow(10,  Math.ceil(Math.log10(stepSizeUnrounded)-1) );
    const stepSize = Math.ceil(stepSizeUnrounded / pow10x) * pow10x;
    const lBound = stepSize * Math.floor(min/stepSize);
    const uBound = stepSize * Math.ceil(max/stepSize);
    for(let i=lBound;i<=uBound;i+=stepSize) result.push(i);
    return result;
};

console.log(makeYAxis(15,234,6));
// > [0, 50, 100, 150, 200, 250]
0
ответ дан 24 November 2019 в 11:38
поделиться

Спасибо за вопрос и ответ, очень полезно. Gamecat, мне интересно, как вы определяете, до какого диапазона тиков следует округлить.

диапазон тиков = 21,9. Это должно быть 25,0

Чтобы сделать это алгоритмически, нужно было бы добавить логику к алгоритму, приведенному выше, чтобы сделать этот масштаб подходящим для больших чисел? Например, с 10 тиками, если диапазон равен 3346, тогда диапазон тиков будет равен 334,6, а округление до ближайших 10 даст 340, когда 350, вероятно, лучше.

Как вы думаете?

0
ответ дан 24 November 2019 в 11:38
поделиться

Попробуйте этот код. Я использовал его в нескольких сценариях построения графиков, и он хорошо работает. Это тоже довольно быстро.

public static class AxisUtil
{
    public static float CalculateStepSize(float range, float targetSteps)
    {
        // calculate an initial guess at step size
        float tempStep = range/targetSteps;

        // get the magnitude of the step size
        float mag = (float)Math.Floor(Math.Log10(tempStep));
        float magPow = (float)Math.Pow(10, mag);

        // calculate most significant digit of the new step size
        float magMsd = (int)(tempStep/magPow + 0.5);

        // promote the MSD to either 1, 2, or 5
        if (magMsd > 5.0)
            magMsd = 10.0f;
        else if (magMsd > 2.0)
            magMsd = 5.0f;
        else if (magMsd > 1.0)
            magMsd = 2.0f;

        return magMsd*magPow;
    }
}
8
ответ дан 24 November 2019 в 11:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: