■CALENDAR■
    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    
<<前月 2020年09月 次月>>
■LOGIN■
現在のモード: ゲストモード
USER ID:
USER PW:
■ADMIN■
ADMIN ID:
ADMIN PW:
■NEW ENTRIES■
■RECENT COMMENTS■
■RECENT TRACKBACK■
  • 吉本隆明の死去に寄せて - 反「反核」ということ
  • 2010 年の釣り - 2010~11 シーズン開幕! 肝和えの素(カワハギ)
  • 震災後の復興を考える
  • 夏本番ですが ・・・ 水の事故を防ぐために
  • 2011 年の釣り - 遅ればせながらシーズン開幕 東京湾のマゴチ
■CATEGORIES■
■ARCHIVES■
■PROFILE■
■POWERED BY■
BLOGN(ぶろぐん)
BLOGNPLUS(ぶろぐん+)
■OTHER■

PL/pgSQL で、第xN分位数を得る集約関数を定義する(その1)
 わきたは、仕事柄、統計量を扱う機会が多々あります。 典型的には、毎年の春闘時に要求案を検討する際、賃金の産別水準/自組織内水準 双方の代表値(=要約的統計量)を算出して比較する、という作業が欠かせません。

 この賃金水準比較、22歳(新卒入社者)~59歳(定年直前)までの1歳刻みの年齢ごとに双方の代表値を比較するのですが、その代表値として何を使うべきでしょうか。
 すぐに思いつくのは「平均値」ですね。 「産別の35歳の平均賃金は○○万円。 これに対してウチの平均は××万円だから、ウチの35歳の賃金はちょっと低いね」なんて分析は、容易に想像できると思います。
 しかし、これだとちょっとまずい場合があります。

 
 産別には50万人以上の組合員がいますから、例えば「基幹職種35歳」だけを取り出しても数万人の母数があります。 この場合、平均値は、その集団を代表する値として充分に意味を持つでしょう。
 いっぽう、わきたの組織の組合員数は総勢300人程度。 ここから職種と年齢を限定して取り出すと、実在者が数人しかいないことがあります。 この場合、平均値はこの集団の水準を必ずしも的確には表わしません。 1人だけ、何か特別な理由で、賃金が他に較べて跳び抜けて高い(低い)人間が混ざっていたとすると、母数が数人しかいない場合には、平均値がこの人の賃金額(特異値)に引っ張られてしまうからです。
 このようなとき、平均値に代えてよく使われるのが第xN分位数です。 「第1四分位(だいいちしぶんい)」や「第9十分位(だいきゅうじゅうぶんい)」などという言葉、聞いた憶えはありませんか?
 代表値を得ようとするある集団の個々の要素の値を、小さいほうから順に並べます。 次に要素の並びをN等分し、小さいほうから数えてx番目の区切りにあたる要素の値を取り出すと、これが第xN分位数。 例えば「第1四分位」は、その集団の下から25%の位置にいる要素の値であり、「第3四分位」は下から75%(すなわち上から25%)の位置にいる要素の値、ということになります。
 第1四分位数は下位25%の値であり、これより低い値を持つ要素数は全体の25%、同様に第3四分位数は上位25%の値であり、これより高い値を持つ要素数は全体の25%。 ということは、第1四分位数と第3四分位数との間に下位25%/上位25%を除いた残り「中位50%」の要素の値が含まれることとなり、これは「ゾーンとして」この集団を充分に代表しているとみなすことができ、また跳び抜けて高い(低い)特異値の影響も排除できます。
 第1四分位と第3四分位で挟まれた中位50%のゾーンが、比較基準(先の例で言えば、産別の職種・年齢別平均賃金額)と較べてどうなのか、というような分析に重宝するのです。

 わきたは昔、第1および第3四分位を算出する Excel VBA の Function を作成して、使っていました。 その後、全組合員の賃金データを PostgreSQL でデータベース化しましたが、しばらくの間は、賃金データをクライアントPCにダウンロードして、Excel で算出していました。
 手間を省くために、これを PostgreSQL 上でダイレクトに求めたいと思うのは、人情でしょう。
 複数レコードにわたるデータからそれらの代表値を求めるためには「集約関数」を使いますが、PostgreSQL ではこの集約関数をユーザが手続き言語を使って定義することができるのです(PostgreSQL のドキュメントによれば、組み込み済みの集約関数である min()・max() なども、このしくみにより定義されているというから驚き!)。
 そこで、PostgreSQL のこのしくみを利用して、第xN分位数を求める集約関数を作成することにしたのです。

 手続き言語としては、使い慣れた PL/pgSQL を使用することとしました。 関数の仕様について、どうせ作るなら第x四分位数でも第x十分位数にでも対応したい。 そこで、0~1の実数を引数として与え、全体のどの位置の値でも取り出せるようにしました。 この引数に 0.25 を与えれば第1四分位、0.9 を与えれば第9十分位になります。 ちなみに、0.5 を与えることで中央値(中位数、メジアン)が、0.0 で最小値(min)、1.0 で最大値(max)が、それぞれ得られます。

 当初は、この仕様をそのまま集約関数とすることを考えていました。 しかし、実装を検討していくうちに、複数レコードにわたるデータを扱う部分(集約演算部分)は、単にレコード毎に投入されるデータをソートして配列に格納し保持する処理のみで良い、ということに気付きました。 複数レコードにわたるデータが集約関数によりソートされて配列に格納されれば、そこから第xN分位数を取り出す演算は後処理で行えば良く、従って集約関数である必要はありません。
 これによる副次効果として、同じくソートされたデータをもとに算出する「ジニ係数」を求める関数も、簡単に実装することができました。

 後日、そのソースリストを載せます。 後の記事に載せました。
| http://blog.wakita.cc/index.php?e=84 |
| サーバ・Linux::PostgreSQL | 06:58 PM | comments (0) | trackback (0) |










http://blog.wakita.cc/tb.php/84
PAGE TOP ↑