SQLiteのドキュメントを検索しましたが、何も見つかりませんでしたが、Googleでも検索したところ、いくつかの結果が表示されました。
SQLiteには標準偏差関数が組み込まれていますか?
ウェルフォードの方法 ( extension-functions.c
)SQLite UDFとして:
$db->sqliteCreateAggregate('stdev',
function (&$context, $row, $data) // step callback
{
if (isset($context) !== true) // $context is null at first
{
$context = array
(
'k' => 0,
'm' => 0,
's' => 0,
);
}
if (isset($data) === true) // the standard is non-NULL values only
{
$context['s'] += ($data - $context['m']) * ($data - ($context['m'] += ($data - $context['m']) / ++$context['k']));
}
return $context;
},
function (&$context, $row) // fini callback
{
if ($context['k'] > 0) // return NULL if no non-NULL values exist
{
return sqrt($context['s'] / $context['k']);
}
return null;
},
1);
それはPHP($db
はPDOオブジェクトです)が、別の言語に移植するのは簡単なはずです。
SQLiteはsooooかっこいいです。 <3
SQLで分散を計算できます。
create table t (row int);
insert into t values (1),(2),(3);
SELECT AVG((t.row - sub.a) * (t.row - sub.a)) as var from t,
(SELECT AVG(row) AS a FROM t) AS sub;
0.666666666666667
ただし、標準偏差を取得するには、平方根を計算する必要があります。
SQLiteでサポートされている集計関数は次のとおりです。
http://www.sqlite.org/lang_aggfunc.html
STDEVはリストにありません。
ただし、モジュールextension-functions.c
in このページ にはSTDEV関数が含まれています。
Sqliteにはまだ組み込みのstdev関数はありません。ただし、(Alixが行ったように)ユーザー定義のアグリゲーター関数を定義することはできます。 Pythonでの完全な例を次に示します。
import sqlite3
import math
class StdevFunc:
def __init__(self):
self.M = 0.0
self.S = 0.0
self.k = 1
def step(self, value):
if value is None:
return
tM = self.M
self.M += (value - tM) / self.k
self.S += (value - tM) * (value - self.M)
self.k += 1
def finalize(self):
if self.k < 3:
return None
return math.sqrt(self.S / (self.k-2))
with sqlite3.connect(':memory:') as con:
con.create_aggregate("stdev", 1, StdevFunc)
cur = con.cursor()
cur.execute("create table test(i)")
cur.executemany("insert into test(i) values (?)", [(1,), (2,), (3,), (4,), (5,)])
cur.execute("insert into test(i) values (null)")
cur.execute("select avg(i) from test")
print("avg: %f" % cur.fetchone()[0])
cur.execute("select stdev(i) from test")
print("stdev: %f" % cur.fetchone()[0])
これは印刷されます:
avg: 3.000000
stdev: 1.581139
MySQLと比較してください: http://sqlfiddle.com/#!2/ad42f3/3/
ちょっとしたトリック
select ((sum(value)*sum(value) - sum(value * value))/((count(*)-1)*(count(*))))
from the_table ;
残っているのは、外部のsqrtを計算することだけです。
いいえ、同じ問題を検索し、アプリケーション(PHP)で計算を行う必要がなくなりました。
分散式を使用V(X) = E(X ^ 2)-E(X)^2。SQLsqliteの場合
SELECT AVG(col*col) - AVG(col)*AVG(col) FROM table
標準偏差を取得するには、平方根V(X)^(1/2)を取る必要があります。
計算する標準偏差のバージョンは指定しませんが、sum()とcount()の集計関数の組み合わせを使用して、どちらのバージョンの分散(標準偏差の2乗)も計算できます。
select
(count(val)*sum(val*val) - (sum(val)*sum(val)))/((count(val)-1)*(count(val))) as sample_variance,
(count(val)*sum(val*val) - (sum(val)*sum(val)))/((count(val))*(count(val))) as population_variance
from ... ;
標準偏差を取得するには、これらの平方根をとる必要があります。
python関数にエラー検出を追加しました
class StdevFunc:
"""
For use as an aggregate function in SQLite
"""
def __init__(self):
self.M = 0.0
self.S = 0.0
self.k = 0
def step(self, value):
try:
# automatically convert text to float, like the rest of SQLite
val = float(value) # if fails, skips this iteration, which also ignores nulls
tM = self.M
self.k += 1
self.M += ((val - tM) / self.k)
self.S += ((val - tM) * (val - self.M))
except:
pass
def finalize(self):
if self.k <= 1: # avoid division by zero
return none
else:
return math.sqrt(self.S / (self.k-1))