Graviness Blog

算数・数学・科学・電脳・雑記・アホの順の密度で記事が構成されます。
<< November 2018 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >> ブログランキング・にほんブログ村へ
 
RECOMMEND
ビッグバン宇宙論 (上)
ビッグバン宇宙論 (上) (JUGEMレビュー »)
サイモン・シン, 青木 薫
RECENT COMMENT
  • 豊臣秀吉と曾呂利新左衛門から学ぶ数列の和
    優乃 (07/12)
  • 【誰か解いて】漸化式 a_(n+1) = f(n) * a_n ^ g(n) + h(n) の一般項
    優乃 (02/18)
  • 【誰か解いて】漸化式 a_(n+1) = f(n) * a_n ^ g(n) + h(n) の一般項
    S.S.+ (02/16)
  • 豊臣秀吉と曾呂利新左衛門から学ぶ数列の和
    坂井昭 (03/19)
  • d/dx(x↑↑n): 高さが定数のテトレーションの微分 - 数学的帰納法を用いる方法
    (09/30)
  • 全ての三角形は二等辺三角形
    優乃 (09/28)
  • 全ての三角形は二等辺三角形
    亀レス (09/28)
  • 全ての三角形は二等辺三角形
    優乃 (09/24)
  • 全ての三角形は二等辺三角形
    亀レス (09/23)
  • 【未解決】新しい演算子を創る
    $_ (09/10)
RECENT TRACKBACK
MOBILE
qrcode
PROFILE
無料ブログ作成サービス JUGEM
 
点の重なりを考慮した最適な点のサイズの導出

データを散布図等で表示するとき、データ数が多くて画面が点で塗り潰れてしまう経験はないでしょうか。

下図は10000個のデータを散布図で表示した例です。下図(左)は中央の帯の部分が点で塗り潰れています。描画領域を大きくするか、下図(右)のように点のサイズを小さく調節することで塗り潰れがなくなり、精確なデータ分析、そして美しく表示できます。

しかし、固定的なデータ数を扱う場合は問題となりませんが、データ数が変わるようなシチュエーションの場合はその都度調節する必要があり面倒です。

本記事では、データ数に応じて最適な点のサイズを自動計算する式とその導出を示します。結論を示すと、x個の点を描画するときの個々の点のサイズs(x)は次式で得られます。

s(x) = S1 * S / (S1 * x + S)

S1: 点を1個描画するときの(x=1のときの)、1個の点による描画面積。
S: 総描画面積の上限。e.g. 画面の半分程度が埋まるのであればその面積。

例えば、S1=36px、S=3600pxの場合、s(x) = 3600 / (x + 100) となります。100点描画するとき個々の点のサイズはs(100)=18pxで描画され、同様にして1000点描画するときs(1000)=3.3px、10000点描画するときs(10000)=0.4pxとなります。

Pythonプログラムの例を示します。データ数len(data)に応じて点の描画サイズsを自動計算しています。

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

data = np.random.normal(size=1000) # normal dist.

S_1, S_m = 36, 3600
s = S_1 * S_m / (S_1 * len(data) + S_m) # see

plt.title(f"count={len(data)}")
plt.ylim((-4.0, 4.0))
plt.scatter(x=np.arange(len(data)), y=data, s=s)
plt.savefig(f"sample.{len(data)}.png")
plt.close()

以降で結論に至るまでの導出を示します。

JUGEMテーマ:コンピュータ

点1個の描画面積をsとするとき、x個の点による総描画面積S(x)は次式で表現できる。

上式は点を打てば点の描画面積分、総描画面積が純増することを意味する。しかし、実際には点は増えれば増えるほど点同士の重なりが生じるため純増しない。点の個数xに依存させて決める総描画面積S(x)を、単純に点の個数xで割った次式によりsを定めることにする。

前述通りS(x)は点の重なりの程度を考慮する必要がある。点のサイズsに対し描画可能な範囲全体が小さい、あるいは各点の位置が集中するとき、純増と比べて相対的にS(x)は小さくなる。

以降で関数S(x)を定める。S(x)は次の特性を持つものとする。

特性1. x >= 1のとき、S(x) <= const. * x
重なりを考慮するときの総描画面積S(x)は、重なりを考慮しない総描画面積よりも小さい。
S(x)は1次関数以下である。
特性2. x >= 1のとき、S'(x) >= 0
x個の点による総描画面積は、点の数が多いほど大きい。
S(x)は単調増加関数である。
特性3-1. S(1) = S1、S(m) = Sm
S1 < Sm、m > 1は定数。実用性を持たせるための特性。
S(x)をx=1, x=mの2点で調節する。
特性3-2. S'(1) = D1
D1 > 0は定数。実用性を持たせるための特性。
急激なサイズ増加等しないようx=1での微分係数で調節する。

特性1、2を満たす関数は無限にある。特性3-*により、未知の変数の上限は3つである。関数の候補として次が考えられる。

べき乗根関数形式・べき乗関数形式: S(x) = a(x + b)1 / M + c
逆数(反比例)関数形式: S(x) = a / (x + b) + c
対数関数形式: S(x) = a log(x + b) + c

実は、逆数関数形式以外は「初等的に解けない」「最終的な式が複雑過ぎて実用的でない」などの理由により未採用とした。以降、逆数関数形式S(x) = a / (x + b) + cを考える。

特性3-*より

a, b, cについて解いて(結構、大変)

ゆえに

整理して

よって、x個の点を描画するときの個々の点の描画面積s(x)は、xで割って以下となる。

上式が最も汎用的であるが、複雑で実用的でない。以下で簡単な式にしていく。

まず、D1= S1とする。∵数式的には、D1はx=1(点1個)における総描画面積の微分係数であり、x=1(点1個)における総描画面積はS1としているので、x=2(点2個)のときの総描画面積はS1+D1-δとなることを意味する。一方、直感的には、x=2(点2個)のときの総描画面積は1個の点の2倍、即ち2*S1-δと考えるのが自然である。

次にm → ∞とする。∵有限のm個の点のときの総描画面積Smをパラメータで指定するか、無限に点を打ったときの総描画面積Sをパラメータで指定するかの違いである。

さらにS >> S1とする。∵ほとんどのケースにおいて、1個の点による総描画面積S1と無限個の点による総描画面積Sとの間には大きな差があるだろう。

整理して最終的に点のサイズは次式となる。

活用時の注意として、導出時にS >> S1と仮定したことに起因して、S1とSに大差ないケースにおいては適切な結果とはならないであろう。

あとがき:

業務で元々はS(x)ではなく、直接s(x)を今流行り?のランプ関数形式@wikipedia(e.g. s(x) = max(36 - x/100, 0.1))で求めていました。しかし、データ数が多くなったときに対応できず、問題の根源となる"点の重なりの程度"から導出してみたかったのが本記事の背景です。重なりの程度をどう数式で表現するかは、本記事では逆数関数形式としましたが、上述通り色々な形式を試しています。対数関数形式のパラメータを限定した解では、ランベルトのW関数@wikipediaΩ定数@wikipediaが登場したり、解き甲斐がありました。

コメント
コメントする









 
トラックバック
この記事のトラックバックURL
http://blog.graviness.com/trackback/949270
 

(C) 2018 ブログ JUGEM Some Rights Reserved.