はじめに
アドベントカレンダー7日目の記事です
HRBrainでバックエンドエンジニアをやっている入中です。
OSSにissueを立てようと思った経緯、実際にissueを立てるまでに行ったことを書きます。
誰に向けた記事
- OSSを使ったプロダクト開発を行っているエンジニア
OSSを使用していて、あれこの機能まだ実装されていないんだ...や
期待挙動が返ってこないな...という経験があった場合にissueをあげてみたいんだけど...
と思って躊躇している方の参考になればと思います。
経緯
HRBrainでは現在goban
というOSS開発を行っています。
(詳しくはHRBrainアドベントカレンダー1の1日目の@yuonodaさんの記事を御覧ください!)
そのOSS開発のContributorとなることを決意しました。
そこであてられたgood first issue
が集計関数Median(中央値)
を返すメソッド追加するtaskでした。
goban
では、Gonumライブラリを一部使用しています。
今回のMedianメソッドも、Gonumを用いて実装しようと考えました。
ですが、引数として渡す値の数が偶数の場合に、期待している中央値の値が返ってきませんでした。
実装したmedianメソッド
func median() {
xs := []float64{2, 3, 5, 9}
median := stat.Quantile(0.5, stat.LinInterp, xs, nil)
fmt.Println(median)
// 3
}
この例では、データが偶数個なので中央の2つの数字の平均値(3 + 5) / 2 = 4
が中央値として返ってくる想定でした。
issueを立てるまでに行ったこと
ライブラリの中身・ドキュメントを読む
最初medianを実装をしようとしたときに参照したドキュメント
median := stat.Quantile(0.5, stat.Empirical, xs, nil)
medianの実装例が記載されており、そのとおりに動かしたのですがやはり期待挙動ではないことを確認しました。
- 使用したQuantileメソッドのコードを確認
gonum/stat/stat.go
stat.Quantileの実装を見ると、第2引数で渡している値で挙動が変わる仕様だったので、引数を変えてみてtry。
median := stat.Quantile(0.5, stat.LinInterp, xs, nil)
期待値が返ってこないことを確認しました。
※ LinInterp
とEmpirical
の違いはこの記事の下部に記載
Go Playgroundで挙動の確認
自分の開発環境や利用ライブラリが事象原因である可能性を排除し、再現性がある挙動を確認した上でissueに投稿するため下記の確認をしました。
- stat.Empiricalの挙動確認
- stat.LinInterpの挙動確認
Playground上でも、期待挙動とは違う動きをすることを確認しました。
GitHubレポジトリ内に同じ内容のissueが立っていないかの確認
※キャプチャの上から1つめのissue(#1836)は私が今回あげたissue
同じ内容のissueがあがっているかもしれないので確認したところ、
2022年11月中旬時点で、Quantileメソッドで中央値の値が取得できないというissueは立っていませんでした。
issueを立てる
いろいろと調べた結果、やはり期待挙動とは違う動きをしていたのでissueを立てることにしました。
issueにはBug Report
Feature request
Proposal
Question
の4つの分類がされており、それぞれ
-
Bug Report
: バグ報告 -
Feature request
: 既存のパッケージに対して機能を追加する要望をあげる -
Proposal
: 新しいパッケージや、機能の仕様追加等の提案 -
Question
: 質問
今回は、期待挙動ではない動きをしていたのでBug Report
として上げました。
issue
stat.Quantile returns wrong value when dataset is even size
issueを立ててからわかったこと
今回、バグとしてissueをあげたのですが、Contributorの方と話をする中で以下のことがわかりました。
- 四分位数には複数の定義が存在し、定義によって導出される値が異なる
- gonumのQuantileメソッドはR上の定義でいえば9種類の四分位計算のうち、type1(Empirical)およびtype4(LinInterp)の2種のみを現時点でサポートしている
- 今回私が期待した値は中央値(50percentile)は、type5~type9で四分位計算すると求められる
つまり、今回はContributorの方がissue内で言っているように、GonumのQuantileメソッドのバグではなく、四分位計算可能な定義がメソッドに定義されていなかったということでした。
上記添付画像で提示されたRのquantileメソッドの挙動
まとめ
issueを上げてから数時間後にContributorの方々から連絡がきました。
時差があるにも関わらず、返答は1日以内で、Gonumの開発が活発なことをが実感できました。
そして、すぐに挙動確認をしてくれたり、実装にtryしてくれたりととても感激しました...
自分自身もContributorとして今回のissueに対してプルリクを上げたいなと思ったのですが、Quantile
やEmpirical
等初めて聞く言葉ばかり且つ、統計学の知識がないためライブラリの思想等を理解してContributeするのはかなり難易度が高いと思い今回は断念しました...(統計学勉強して、Contributeできるように努めよう...)
ぜひ、統計学や数学等に強い方...Gonumでmedianメソッドの実装を試していただければ嬉しいです!
issueの会話等ででてきた言葉のまとめ
Median
データを大きい順(または小さい順)に並べたとき、真ん中の値を中央値(メディアン)
と言います。データの数が偶数のときは「真ん中の値」が2つ登場するのでそれらを足して2で割ったものを中央値とします。
引用: 高校数学の美しい物語
Quantile
データの値を小さいものから並べてq等分したときのそれぞれのグループの境界となる値
参考: 統計学「分位数」Quantile
Empirical
経験過程は関数空間に値をとる確率変数を確率過程と呼びます。
参考: 経験過程とはなんですか
LinInterp
線形補間
関数$\ y=f(x)\ $が2点$\ (x_1,x_2),\ (x_2,y_2)\ $を通ることがわかっているとする。
このとき関数$\ f(x)\ $を2点を通る線分:
y = y_1 + \frac{y_2-y_1}{x_2-x_1}(x-x_1)
で近似する手法を線形補間と言う。
引用: 高校数学の美しい物語
R
オープンソースで利用可能な統計やデータ解析に特化したプログラミング言語
引用: 【初学者向け】「R」言語とは?R言語に関してわかりやすく解説!
HRBrainではエンジニアを募集しています
弊社に興味を持っていただいた方はぜひ、以下サイトからご応募ください!
https://www.hrbrain.co.jp/recruit