グラフを描画するプログラムをscratchから書かねばならなくなった時に、軸の目盛り(tick)の間隔をいい感じに設定する方法。

By | 2020年5月14日 , Last update: 2022年8月7日

はじめに

人間の人生において、少なくとも一度はグラフを描画するプログラムをJFreeChartやChart.jsの力を借りずにscratchから書かねばならない場面に出くわすものです。

この記事ではそんな時におそらく役立つグラフの軸の目盛りの間隔をいい感じに設定する方法について書きます。

スポンサーリンク

やりたいこと

グラフといえば普通は2次元、たまに3次元、もっと気の利いたグラフだと次元のものが思い浮かぶと思いますが、単に軸の数が増えるだけです。また、向きについても片方だけ考慮すれば良さそうですので、1次元のもの(数直線)かつ、データがすべて負でない値をとる場合を考えます。

それで、以下のデータを数直線上に図からはみ出さないようにプロットすることを考えます。

しかし、データを点として単純にプロットするだけですと、数直線を見ただけではデータが分布している範囲がわかりにくいと思います。

そこで、原点以外に個の目盛りをつけることにします。

2190
1947
1628
2902
581
74
515
4401
1671
3690

上記の個の目盛りをいい感じにつける方法を考えます。

単純な方法

上記のデータ列を例にとって考えます。

も適当な値を置きます。とかにしてみます。原点を含めると6個の目盛りをつけることになります。

上記のデータ列のデータの最大値は4401ですので、5個目の目盛りを4401とすると、隣接する目盛りの間隔は880.2になります。したがって、目盛り付きの数直線は下図のようになります。

目盛りとしては正確なのかもしれませんが、正確すぎるせいかグラフ全体の見た目的にbusyな印象を受けますね。

わかりやすい目盛り

「目盛りの間隔が880.2である。」というのは数字にあまり強くない人にとっては直感的はわかりにくいと思う(※個人の感想です。)ので、もう少しなんとかならないか考えてみます。

例えば、目盛りの間隔を800にすれば、目盛り付きの数直線は下図のようになります。


スポンサーリンク

ちょっと見やすくなったような気がします。

実は最初の図よりも2番目の図の方が画像上における目盛りの幅を意図的に詰めてありますが、それでも2番目の図の方が見やすいように感じますし、「4401」の点を図上の目盛りとしては一番右側に位置する4000の目盛りのさらに右側にプロットすることになったとしてもそれほど違和感を感じないと思います。

解くべき問題

定式化

ここまでの考察で、グラフの目盛りをいい感じに設定するためには、

ある正の実数値が与えられたときに、を10進数で表示したときの最上位の桁以外の桁を0としたときの値を求める。

ことを考えればよさそうです。

上記の記述はどことなく文学的で微妙だということであれば、


スポンサーリンク

ある正の実数値が与えられたときに、

(1)

となるような整数の組を求め、さらにを求める。

というように書くことができそうです。

解いてみた(`・ω・´)

(1)式の及び, と計算できますので、は以下のように表すことができます。

 (2)

なお、はみんな大好き床関数です。

プログラム例

PHPとかPython3とか

(2)式のを求めるプログラムはPHPだと以下のように書けます。

<?php
argv[1]);
x));
x/pow(10,n);
echo $y."\n";
?>

また、Python3だと以下のように書けます。
#!/usr/bin/env python3
import sys
import math
args = sys.argv
x = float(args[1])
n = math.floor(math.log10(x))
y = math.floor(x/math.pow(10,n))*math.pow(10,n)
print("{0:d}".format(int(y)))

実行してみた

スポンサーリンク

PHPのプログラムを実行すると以下のような結果が得られます。

[panda@pandanote.info ~]$ php floor_function.php 12322
10000
[panda@pandanote.info ~]$ php floor_function.php 123
100
[panda@pandanote.info ~]$ php floor_function.php 600
600
[panda@pandanote.info ~]$ php floor_function.php 880.2
800
[panda@pandanote.info ~]$ php floor_function.php 999
900
[panda@pandanote.info ~]$ php floor_function.php 1
1

Python3でも実行してみました。PHP版とは実行時のOSが異なるのは気にしない方向でお願いいたします。

C:\Users\Pandanote>python3 floor_function.py 12322
10000
C:\Users\Pandanote>python3 floor_function.py 123
100
C:\Users\Pandanote>python3 floor_function.py 600
600
C:\Users\Pandanote>python3 floor_function.py 880.2
800
C:\Users\Pandanote>python3 floor_function.py 999
900
C:\Users\Pandanote>python3 floor_function.py 1
1

ちょっとした応用

グラフの目盛りの間隔を決めるという目的で(1)式の及びを求める場合に、「目盛りの数は増えてもいいからのいずれかになるようにしたい。」というニーズもあると思います。

そのようなニーズに応える場合には、以下のように場合分けするとよさそうです。なお、目盛りの数は最大で本になる可能性があります。

  • の場合にはとみなす。
  • の場合にはとみなす。
  • の場合にはそのままとする。

まとめ

この記事の数直線はSVGで作成していますが、今どき(この記事を最初に書いた時点(2020年5月)の時点の情報です。)のブラウザならだいたい対応してますし、ディスプレイの解像度とか気にしなくていいので、割とおすすめです。

…と雑にSVGをおすすめしたところで、この記事は以上です。