記事一覧

女の子の身長を一行で求める方法


\( f(x) = -0.36x^2 + 12.4x + 53 + \sqrt{ -2 log( R1 ) } \cdot sin( 2 \pi R2 ) \times 5.5 \)
 
この数式はいったい何か。



史上最下位の指名選手は第何位か?

▲PAGE TOP
正解は、18位だ。

数式の意義

▲PAGE TOP
ブログのタイトルが激しく「ネタばれ」になっているから想像がつくかもしれないが、これは\( x \)に「女の子の年齢」を、\( R1 \)、\( R2 \)に一様乱数を入力したとき、その年齢の女の子の身長をランダムで生成してくれる関数である。自作ゲームのキャラメイキングなどに使えるのではないかと思って作ってみたものだ。

\( x \)には6から20までの実数が、\( R1 \)と\( R2 \)には0~1までの乱数が入る。
21以上の\( x \)には対応していないが、身長が伸びるのは20歳ぐらいまでだ。
そのばあいは\( x = 20 \)を入力しておけばよい。

さて、この関数の特長は何といっても「18000人あまりの少女の身長の実測データ」から作られていることである。だから少なくとも平均値については、かなりリアルな結果が出力される。

では、この関数は具体的にどのようにして作られたのだろうか?
本稿はそれを解説するための記事だ。
長い記事になるので、まずは目次を置いておこう。

目次

▲PAGE TOP
 ・データソース
 ・数式の構造
 ・身長平均の近似値を求める式の作成
 ・散布図を作る
 ・近似曲線を求める
 ・正規乱数で数値をばらけさせる
 ・出力結果をテストする
 ・男の子の身長を求める関数
 ・終わりに

データソース

▲INDEX
先ほど実測と述べたが、そもそもその実測データはどこから持ってきたのかと疑問に思われるかもしれない。実はこれは厚生労働省の「平成26年度体力・運動能力調査」の結果を引用したものだ。リンク先のページから「年齢別体格測定の結果」のファイルをダウンロードして開けば日本人の性別・年齢別の身長・体重等のデータを入手できる。

数式の構造

▲INDEX
さて、数式の具体的な作成法を解説する前にまず、冒頭の数式の構造についてあらかじめ説明しておきたい。

\( f(x) = -0.36x^2 + 12.4x + 53 + \sqrt{ -2 log( R1 ) } \cdot sin( 2 \pi R2 ) \times 5.5 \)

実はこの数式の前半と後半は、それぞれ異なる役割をもっている。

前半部の
\( f-0.36x^2 + 12.4x + 53 \)
は、年齢が\( x \)の女の子の身長平均の近似値を求めるためのものだ。

一方、後半部の
\( \sqrt{ -2 log( R1 ) } \cdot sin( 2 \pi R2 ) \times 5.5 \)
は、正規乱数を用いて適当な範囲に数値をばらつかせるためのものである。

なお、正規乱数というのは「正規分布に従う母集団から数値をランダムに取り出すことで得られる乱数」のことをいう。人間の身長のようなデータは一般に正規分布に近い分布を取るため、平均値付近の人数が一番多く、平均値から離れるほど人数が少なくなる。だから正規乱数を使って平均から値をばらつかせれば、実データの身長分布に近い結果を得られる。

なお、数式の最後で5.5をかけているのは、この正規乱数の標準偏差を5.5に調整するためだ。
後で説明するが標準偏差が5.5であるのにもちゃんと理由がある。
Wikipedia記事へのリンク: 正規分布 正規乱数 標準偏差

身長平均の近似値を求める式の作成

▲INDEX
先述したように、冒頭の数式の前半部である
\( f'(x) = -0.36x^2 + 12.4x + 53 \)
という数式は、\( x \) に6~20の値を入力したとき、その年齢の女の子の身長平均の近似値が得られるものである。

そして実は、この数式は表計算ソフトを使えば簡単に求められるものだ。

具体的には、

 ・女の子の身長と年齢の関係をプロットした散布図を作る
 ・散布図上に引いた近似曲線を求める

という手順で求められた近似曲線の数式が、その「身長平均の近似値を求める数式」となる。

なお、本稿を執筆するにあたって筆者が使用している表計算ソフトは2007年度版のMicrosoft Excelである。
以下の手順はこのエクセル上で行った。

散布図を作る

▲INDEX
近似曲線の式を求めるためには、まず散布図を作る必要がある。
この散布図は、以下のような手順で作成した。

1. 「平成26年度体力・運動能力調査」のページから、「年齢別体格測定の結果」のファイルをダウンロードし、ファイルをエクセルで開く。


2. 新しいシートを作ってA1-A15のセルに6~20までの数字を入力する。
3. 測定結果のシートから6歳~20歳までの「平均値」のデータをコピーして、これを新規シートのB1-B15のセルにペーストする。


4. A1-B15を範囲選択する。
5. 「挿入-グラフ-散布図-平滑線」を選択する。

この手順が終われば以下のようなグラフが画面上に表示されているだろう。 (※凡例は消去した)


近似曲線を求める

▲INDEX
散布図が表示されたら、次は近似曲線の式を求める。

1. グラフ上の線を選択して右クリックし、「近似曲線の追加」を選択。
2. 近似曲線の書式設定ダイアログが出たら、近似の種類について「多項式近似」を選択。
3. 「グラフに数式を表示する」にチェックを入れて閉じる。

この作業が終わればグラフ上に近似曲線とその数式が表示されているはずだ。


グラフを見れば分かるように、近似曲線のラインはxが6~20の範囲において概ね散布図の平滑線と一致していることが分かるだろう。つまり、この数式の\( x \)に6~20までの数値を代入すれば、だいたいその年齢の「日本人女子の平均に等しい数」が出力されることになる。

数式の端数を四者五入するなどして得られた
\( f'(x) = -0.36x^2 + 12.4x + 53 \)
のグラフも、おおむね散布図と一致する。
つまりこれが前頁の数式の前半部である。

下記に示すグラフの赤線はこの数式の出力結果である。 

散布図の平滑線とだいたい重なっているのが分かる。

正規乱数で数値をばらけさせる

▲INDEX
ところで先述した「年齢別体格測定の結果」には標準偏差のデータも付記されている。
年齢ごとにばらつきが大きいものの、6歳~20歳の平均値をとると5.49だ。

つまり、だいたい5.5の偏差を持つ正規乱数によって平均から値を分散させれば、数式は適切なばらけかたで値を返してくれるはずだ。

正規乱数を発生させる手段としては「ボックス=ミュラー法」という一般的な方法がある。
たとえば\(R1\), \(R2\)がそれぞれ独立した0~1までの乱数であるとするとき、

\(N1 = \sqrt{ -2log( R1 ) } \cdot sin( 2 \pi R2) \)
\(N1 = \sqrt{ -2log( R1 ) } \cdot sin( 2 \pi R2) \)

の式で得られる\(N1\), \(N2\)は、それぞれ平均0分散1」の正規分布に従う乱数となる。
Wikipedia記事へのリンク: ボックス=ミュラー法

つまり、上記の\(N1\), \(N2\)のどちらかを計算することで正規乱数を得ることができ、これに標準偏差5.5をかけた値を使えば数式を適切な範囲でばらけさせることができるというわけだ。

出力結果をテストする

▲INDEX
この関数の出力結果をテストするため、javaで以下のようなコードを組んだ。

このコードの出力結果は以下のようになる。
【06歳】 try1: 110.1cm  try2: 110.9cm  try3: 113.7cm  try4: 111.7cm  try5: 104.9cm  
【07歳】 try1: 120.1cm  try2: 118.5cm  try3: 125.2cm  try4: 110.7cm  try5: 126.1cm  
【08歳】 try1: 123.9cm  try2: 141.8cm  try3: 132.9cm  try4: 129.7cm  try5: 131.4cm  
【09歳】 try1: 141.3cm  try2: 131.1cm  try3: 126.1cm  try4: 129.6cm  try5: 133.0cm  
【10歳】 try1: 138.2cm  try2: 145.7cm  try3: 147.6cm  try4: 136.9cm  try5: 158.3cm  
【11歳】 try1: 142.8cm  try2: 148.2cm  try3: 147.5cm  try4: 140.3cm  try5: 144.6cm  
【12歳】 try1: 153.3cm  try2: 141.7cm  try3: 146.1cm  try4: 147.9cm  try5: 143.8cm  
【13歳】 try1: 156.6cm  try2: 161.6cm  try3: 155.3cm  try4: 159.3cm  try5: 153.5cm  
【14歳】 try1: 154.9cm  try2: 157.3cm  try3: 156.4cm  try4: 160.6cm  try5: 159.2cm  
【15歳】 try1: 158.9cm  try2: 150.2cm  try3: 150.8cm  try4: 158.3cm  try5: 151.4cm  
【16歳】 try1: 161.4cm  try2: 157.0cm  try3: 162.7cm  try4: 161.9cm  try5: 166.8cm  
【17歳】 try1: 157.5cm  try2: 163.2cm  try3: 172.7cm  try4: 164.3cm  try5: 154.8cm  
【18歳】 try1: 158.7cm  try2: 153.6cm  try3: 162.3cm  try4: 158.9cm  try5: 169.1cm  
【19歳】 try1: 162.9cm  try2: 157.9cm  try3: 150.9cm  try4: 162.0cm  try5: 155.2cm  
【20歳】 try1: 158.0cm  try2: 158.3cm  try3: 162.7cm  try4: 157.5cm  try5: 156.1cm


また以下のようなコードで各年齢につき100万回ずつの計算を行い、出力の最大・最小値を求めてみた。

その出力結果は以下のようになった。
【06歳】  最大値:141.2cm  最小値:088.0cm
【07歳】  最大値:147.9cm  最小値:094.0cm
【08歳】  最大値:156.1cm  最小値:103.0cm
【09歳】  最大値:161.0cm  最小値:109.8cm
【10歳】  最大値:167.5cm  最小値:114.1cm
【11歳】  最大値:174.2cm  最小値:120.4cm
【12歳】  最大値:178.8cm  最小値:122.6cm
【13歳】  最大値:177.6cm  最小値:126.1cm
【14歳】  最大値:183.2cm  最小値:129.9cm
【15歳】  最大値:184.4cm  最小値:133.3cm
【16歳】  最大値:187.0cm  最小値:133.3cm
【17歳】  最大値:185.2cm  最小値:133.8cm
【18歳】  最大値:187.7cm  最小値:133.4cm
【19歳】  最大値:185.5cm  最小値:126.9cm
【20歳】  最大値:185.7cm  最小値:129.6cm

この結果からすれば、100万人に一人ぐらいは「身長130cm以下のハタチ」が存在しているのかも知れない。

男の子の身長を求める関数

▲INDEX
なお、男性版の関数も一応作成してあるので、最後に紹介しておく。
\( f(x) = -0.31x^2 + 12.3x + 51 + \sqrt{ -2 log( R1 ) } \cdot sin( 2 \pi R2 ) \times 6 \)

女性の場合と同様、\( x \)に6から20までの実数を、\( R1 \)と\( R2 \)には0~1までの乱数を入れれば、その年齢の男性の身長をランダムで出力してくれるだろう。

終わりに

▲INDEX
今回使用した「統計から近似曲線を求め、それを関数にフィードバックする」という手法には他にも有益な応用手段があるかもしれない。 方法論の一つとしてご記憶いただけたら幸いである。
スポンサーサイト

コメント

コメントの投稿

非公開コメント