初歩的なことかもしれませんがハマったのでメモ。
statistics.median_grouped([1, 2.4])の値はなーんだ?
答えは1.9。
通常のメジアンmedian()は偶数個のデータがあるとき真ん中2つの中間値になります。
import statistics
print(statistics.median([1, 2.4]))
結果
1.7
しかし、**median_grouped()は補間メジアン**なのでこうなります。
import statistics
print(statistics.median_grouped([1, 2.4]))
結果
1.9
なぜ?
まず、次のように実際のデータから仮に「中央の値」をとってきて、
# Find the value at the midpoint. Remember this corresponds to the
# centre of the class interval.
x = data[n//2]
これを中点とする区間(メジアン区間と仮に呼ぶ)を考えます。幅はmedian_grouped(data, interval=1)の
intervalです。そして線形補間で算出です。
median_grouped([1, 2.4])の場合は、2.4を中央とする半開区間 [1.9, 2.9) をとり、
1.9と求まります((n+1)/2番目の値を考えるmedian()と違って、n/2個になる点を考えるところに注意)。
別の例
import statistics
print(statistics.median_grouped([1,2,2]))
結果
1.75
位置1を中点として区間[1.5, 2.5)を考えると、そこで累計データ数が1個から3個に増えているので、
1.5個になる点は、線形補間で、1.5+{1*(1.5-1)/(3-1)}=1.75です。**通常のメジアン(2)よりも"中央っぽい"**です。
注意点
ここでメジアン区間内には他の値が含まれないほどintervalが小さいことが想定されているようです。
Pythonドキュメントの例もそうですし、Wikipediaの計算式もそうなっています。
Pythonでも、もし他の値が含まれても存在しないかのように計算されます。
# Uses bisection search to search for x in data with log(n) time complexity
# Find the position of leftmost occurrence of x in data
l1 = _find_lteq(data, x)
# Find the position of rightmost occurrence of x in data[l1...len(data)]
# Assuming always l1 <= l2
l2 = _find_rteq(data, l1, x)
cf = l1
f = l2 - l1 + 1
return L + interval*(n/2 - cf)/f
しかしこの計算方式は唯一のものではなく、区間内の他の値も加味する定義もあるようです。
(何しろ、分位数には10種類もの定義があるそうで、Wolfram言語のQuantile[ ]にはどの計算法を用いるかを
指定する4つのパラメーターがあるそうですし、pandasのquantile()にもパラメーターがあるようです)
median_grouped()という名前は、データをいくつかの階級(class)にグループ分けした連続分布とみなす
というニュアンスを込め、あとはこういう関数を使う人には説明不要という判断での命名な気がしますが、
定義が混在していて計算が食い違ったりして統計に不慣れな人には少しややこしいかもしれません。