2014-01-18 32 views
10

假設我將6面模具捲成60次,並分別爲數字1至6分別獲得16,5,9,7,6,15個角色。數字1和6顯示太多,並且there's only about a 1.8% chance of that being random。如果我使用Statistics::ChiSquare,它打印出:對Perl更好的卡方檢驗?

There's a >1% chance, and a <5% chance, that this data is random. 

所以它不僅是一個糟糕的界面(我不能讓這些數字直接返回),但舍入誤差是顯著。

更糟的是,如果我滾動2個六方骰子怎麼辦?獲得任何特定數字的機率爲:

Sum Frequency Relative Frequency 
2 1   1/36 
3 2   2/36                                                    
4 3   3/36 
5 4   4/36 
6 5   5/36 
7 6   6/36 
8 5   5/36 
9 4   4/36 
10 3   3/36 
11 2   2/36 
12 1   1/36 

Statistics::ChiSquare used to have a chisquare_nonuniform() function,但它被刪除。

所以數字四捨五入,我不能用它來分配不均勻。給出一個實際頻率的列表和一個預期的頻率列表,在Perl中計算卡方檢驗的最佳方法是什麼?我在CPAN上找到的各種模塊並不能幫助我,所以我猜我錯過了一些明顯的東西。

+1

卡方檢驗是很簡單的數學直接,也許20行代碼來實現,我希望大多數人想要更直接的控制將做到這一點。對於1%,5%等的誤差範圍更難以計算,所以簡單的utils可能只是硬編碼P <0.01,P <0.05等值。我不會感到驚訝的是,在http://search.cpan.org/~mikek/Statistics-Distributions-1.02/Distributions.pm –

回答

13

自己實現這個過程非常簡單,我不想爲此僅上傳Yet Another Statistics模塊。

use Carp qw<croak>; 
use List::Util qw<sum>; 
use Statistics::Distributions qw<chisqrprob>; 

sub chi_squared_test { 
    my %args = @_; 
    my $observed = delete $args{observed} // croak q(Argument "observed" required); 
    my $expected = delete $args{expected} // croak q(Argument "expected" required); 
    @$observed == @$expected or croak q(Input arrays must have same length); 

    my $chi_squared = sum map { 
    ($observed->[$_] - $expected->[$_])**2/$expected->[$_]; 
    } 0 .. $#$observed; 
    my $degrees_of_freedom = @$observed - 1; 
    my $probability = chisqrprob($degrees_of_freedom, $chi_squared); 
    return $probability; 
} 

say chi_squared_test 
    observed => [16, 5, 9, 7, 6, 17], 
    expected => [(10) x 6]; 

輸出:0.018360

+1

amon等通用統計模塊中找到更好的卡方檢驗,謝謝。那很完美。我曾嘗試過自己實現,但是我發現在計算'$ chi_squared'時我犯了一個小數學錯誤。我感謝您的幫助! – Ovid

+3

如果你好奇,這是我的寫作:http://blogs.perl.org/users/ovid/2014/01/testing-random-dice-rolls.html – Ovid

+0

@amon:我還沒見過之前的'delete x // croak'聲明。在'//'上的[docs](http://perldoc.perl.org/perlop.html#Logical-Defined-Or)表示它返回一個不能用作左值的值。那麼'delete'在這裏如何正確工作,因爲它在技術上只應該在這裏運行一個值而不是一個左值? –