2009-12-06 54 views
13

我們有一個相對較小的表,我們希望根據評級進行排序,使用Wilson interval或合理的等價表。我是一個相當聰明的人,但我的數學福是隔靴搔癢強大到足以明白這一點:在SQL中實現Wilson得分

Wilson Score http://www.evanmiller.org/images/rating-equation.png

上述公式中,有人告訴我,計算正/負比分(大拇指/大拇指朝下)投票系統。我從來沒有參加過統計課程,而且我已經完成了任何一種高級數學已經15年了。我不知道該戴的那個小帽子是什麼意思,或者是什麼後面的耶穌魚在z表示。

我想知道兩件事情:

  1. 可以此公式改變,以適應一個5星評級系統?我發現this,但作者對他的公式的準確性表示懷疑。

  2. 這個公式如何在SQL函數中表達?請注意,我不需要實時計算和排序。得分可以每天計算和緩存。

  3. 我可以忽略內置於Microsoft SQL Server的內容嗎?

+0

p =帽子的隨機變量P的估計值。\ n 向後耶穌魚=α,這是你的意義截止 – twolfe18

+3

+1 「倒退耶穌魚」,好像魚有方向 – ash

回答

7

而不是試圖操縱威爾遜的算法來做5星評級系統。你爲什麼不看看不同的算法?這是什麼imdb使用他們的前250:Bayesian Estimate

至於說明在威爾遜的算法數學,下面是張貼在您的第一篇文章的鏈接。它是用Ruby編寫的。

require 'statistics2' 

def ci_lower_bound(pos, n, power) 
    if n == 0 
     return 0 
    end 
    z = Statistics2.pnormaldist(1-power/2) 
    phat = 1.0*pos/n 
    (phat + z*z/(2*n) - z * Math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n) 
end 

如果您想另一個例子,這裏是一個在PHP中: http://www.derivante.com/2009/09/01/php-content-rating-confidence/

編輯:似乎derivante.com不再身邊。您可以在archive.org - https://web.archive.org/web/20121018032822/http://derivante.com/2009/09/01/php-content-rating-confidence/上看到原始文章,並添加了以下文章中的代碼。

class Rating 
{ 
    public static function ratingAverage($positive, $total, $power = '0.05') 
    { 
    if ($total == 0) 
     return 0; 
    $z = Rating::pnormaldist(1-$power/2,0,1); 
    $p = 1.0 * $positive/$total; 
    $s = ($p + $z*$z/(2*$total) - $z * sqrt(($p*(1-$p)+$z*$z/(4*$total))/$total))/(1+$z*$z/$total); 
    return $s; 
    } 
    public static function pnormaldist($qn) 
    { 
    $b = array(
     1.570796288, 0.03706987906, -0.8364353589e-3, 
     -0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5, 
     -0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8, 
     0.3657763036e-10, 0.6936233982e-12); 
    if ($qn < 0.0 || 1.0 < $qn) 
     return 0.0; 
    if ($qn == 0.5) 
     return 0.0; 
    $w1 = $qn; 
    if ($qn > 0.5) 
     $w1 = 1.0 - $w1; 
    $w3 = - log(4.0 * $w1 * (1.0 - $w1)); 
    $w1 = $b[0]; 
    for ($i = 1;$i <= 10; $i++) 
     $w1 += $b[$i] * pow($w3,$i); 
    if ($qn > 0.5) 
     return sqrt($w1 * $w3); 
    return - sqrt($w1 * $w3); 
    } 
} 

至於在SQL中這樣做,SQL所有這些數學函數已經在它的庫中。如果我是你,我會在你的應用程序中這樣做。每隔一段時間(幾個小時?幾天),讓您的應用程序更新您的數據庫,而不是隨時進行此操作,否則您的應用程序將變得非常緩慢。

+0

不是'phat = 1.0 * pos/n' ==='phat = pos/n'? –

+2

不,將'pos'乘以'1.0'會將其作爲浮點數,這使得該分部成爲浮點分割。 – cbrauchli

+0

PHP示例的鏈接不再有效 –

2

把Williams鏈接到php的解決方案http://www.derivante.com/2009/09/01/php-content-rating-confidence/,並讓你的系統只是正面和負面(5星可能是2位,1啓動可能是2 neg),那麼將它轉換爲T相當容易-SQL,但你在服務器端邏輯中做得更好。

+3

要添加到Paul所說的內容中,我會在表中創建一個「分數」字段,然後執行一個cron任務,以每X小時(或幾天)更新數據庫中的分數。即時進行這種計算對於任何應用程序的性能都是非常不利的。 – William

+0

同意。我計劃每天計算一次值,然後根據緩存的值進行排序。 – dansays

4

關於你的第一個問題(調整公式到五星系統),我會同意Paul Creasey的看法。

轉換公式:[3 +/-我分 - >我上行/下行票](3分 - > 0)

例如:4分 - > 1贊成票,5星 - > +2,1 - > -2等等。

我要指出,雖然,代替下界兩個紅寶石和PHP函數計算間隔的,我也只是計算更簡單威爾遜中點:

(X +(Z^2)/2)/(N + Z^2)

其中:
N =總和(up_votes)+薩姆(| down_votes |)
X =(陽性投票)/ N =和數(up_votes)/ n
z = 1.96(固定值)

0

first link的作者最近在他的文章中添加了一個SQL實現。

這就是:

SELECT widget_id, ((positive + 1.9208)/(positive + negative) - 
       1.96 * SQRT((positive * negative)/(positive + negative) + 0.9604)/
         (positive + negative))/(1 + 3.8416/(positive + negative)) 
    AS ci_lower_bound FROM widgets WHERE positive + negative > 0 
    ORDER BY ci_lower_bound DESC; 

這是否可以容納一個5星評級系統是超越我了。

0

我已經上傳一個Oracle PL/SQL實施https://github.com/mattgrogan/stats_wilson_score

create or replace function stats_wilson_score(

/***************************************************************************************************************** 

Author  : Matthew Grogan 
Website  : https://github.com/mattgrogan 
Name  : stats_wilson_score.sql 
Description : Oracle PL/SQL function to return the Wilson Score Interval for the given proportion. 
Citation : Wilson E.B. J Am Stat Assoc 1927, 22, 209-212 

Example: 
    select 
    round(29/250, 4) point_estimate, 
    stats_wilson_score(29, 250, 0.10, 'LCL') lcl, 
    stats_wilson_score(29, 250, 0.10, 'UCL') ucl 
    from dual; 

******************************************************************************************************************/ 

    x integer, -- Number of successes 
    m integer, -- Number of trials 
    alpha number default 0.95, -- Probability of a Type I error 
    return_value varchar2 default 'LCL' -- LCL = Lower control limit, UCL = upper control limit 
) 

return number is 

    z float(10); 
    phat float(10) := 0.0; 
    lcl float(10) := 0.0; 
    ucl float(10) := 0.0; 

begin 

    if m = 0 then 
    return(0); 
    end if; 

    case alpha 
    when 0.10 then z := 1.644854; 
    when 0.05 then z := 1.959964; 
    when 0.01 then z := 2.575829; 
    else return(null); -- No Z value for this alpha 
    end case; 

    phat := x/m; 

    lcl := (phat + z*z/(2*m) - z * sqrt((phat * (1-phat))/m + z * z/(4 * (m * m))))/(1 + z * z/m); 
    ucl := (phat + z*z/(2*m) + z * sqrt((phat*(1-phat)+z*z/(4*m))/m))/(1+z*z/m); 

    case return_value 
    when 'LCL' then return(lcl); 
    when 'UCL' then return(ucl); 
    else return(null); 
    end case; 

end; 
/
grant execute on stats_wilson_score to public; 
+1

張貼在這裏太大了嗎?鏈接可能會中斷... – vonbrand