Karmaşıklık içermeyen Kolmogorov (-Smirnov)


12

İstatistiklerde, bazen iki veri örneğinin aynı temel dağıtımdan gelip gelmediğini bilmek faydalıdır. Bunu yapmanın bir yolu, iki örnekli Kolmogorov-Smirnov testini kullanmaktır .

Göreviniz iki sıralanmamış negatif olmayan tamsayı dizilerini okuyan ve testte kullanılan ana istatistiği hesaplayan bir program yazmak olacaktır.


Bir dizi verilen Ave bir reel sayı x, dağılım fonksiyonunu tanımlamak Ftarafından

F(A,x) = (#number of elements in A less than or equal to x)/(#number of elements in A)

İki dizinin göz önüne alındığında A1ve A2tanımlamak

D(x) = |F(A1, x) - F(A2, x)|

İki örnek Kolmogorov-Smirnov istatistik maksimum değeridir Dtüm gerçek x.

Misal

A1 = [1, 2, 1, 4, 3, 6]
A2 = [3, 4, 5, 4]

Sonra:

D(1) = |2/6 - 0| = 1/3
D(2) = |3/6 - 0| = 1/2
D(3) = |4/6 - 1/4| = 5/12
D(4) = |5/6 - 3/4| = 1/12
D(5) = |5/6 - 4/4| = 1/6
D(6) = |6/6 - 4/4| = 0

İki dizinin KS istatistiği 1/2, maksimum değeri D.

Test senaryoları

[0] [0] -> 0.0
[0] [1] -> 1.0
[1, 2, 3, 4, 5] [2, 3, 4, 5, 6] -> 0.2
[3, 3, 3, 3, 3] [5, 4, 3, 2, 1] -> 0.4
[1, 2, 1, 4, 3, 6] [3, 4, 5, 4] -> 0.5
[8, 9, 9, 5, 5, 0, 3] [4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9] -> 0.175824
[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7] [7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8] -> 0.363636

kurallar

  • Bir işlev veya tam bir program yazabilirsiniz. Giriş STDIN veya işlev bağımsız değişkeni üzerinden olabilir ve çıkış STDOUT veya dönüş değeri üzerinden olabilir.
  • Her iki dizide de tutarlı olduğu sürece giriş için kesin bir liste veya dize biçimi olduğunu varsayabilirsiniz.
  • Dilinizin bunun için bir yerleşik olması ihtimaline karşı, onu kullanamayabilirsiniz.
  • Cevapların en az 3 anlamlı rakama doğru olması gerekir
  • Bu , bu yüzden en az bayttaki program kazanır

Tüm girdiler tamsayı diziler mi olacak yoksa kayan noktalar içerebilir mi?
kennytm

@KennyTM Sadece negatif olmayan tamsayılar. İşleri basit tutacağımı düşündüm.
Sp3000

Diziler için üstlenebileceğimiz maksimum bir değer var mı? (Örneğin, tüm girişler Aaşağıda length(A)mı?)
flawr

@flawr Hayır maksimum değer üstlenemezsiniz
Sp3000

Başlığı beğendim. Kolmogorov karmaşıklık torbasını hedef alıyorum ama bu sefer değil.
edc65

Yanıtlar:


10

APL ( 29 24)

(Ek ilham için Zgarb'a teşekkürler.)

{⌈/|-⌿⍺⍵∘.(+/≤÷(⍴⊣))∊⍺⍵}

Bu, dizileri sol ve sağ argümanları olarak alan bir işlevdir.

      8 9 9 5 5 0 3 {⌈/|-⌿⍺⍵∘.(+/≤÷(⍴⊣))∊⍺⍵} 4 9 0 5 5 0 4 6 9 10 4 0 9 
0.1758241758

Açıklama:

{⌈/                                maximum of
   |                               the absolute value of
    -⌿                             the difference between
      ⍺⍵∘.(         )∊⍺⍵          for both arrays, and each element in both arrays
            +/≤                    the amount of items in that array ≤ the element
               ÷                   divided by
                (⍴⊣)              the length of that array
                          }

Yapabileceğini bilmiyordum ⍺⍵! Çok kullanışlı.
Zgarb

1
Ayrıca, ⍳⌈/maksimum tam olarak dizi değerlerinden birinde elde edildiğinden, gereksiz olduğunu düşünüyorum .
Zgarb

@Zgarb: Tabii ki haklısın, sadece olası her dizi değeri için test yapmam gerekiyor. Bu 0,, dizi içeriyorsa test edeceği için ben de kurtulabilirim demektir . Teşekkürler! (Ve bu bana öğretir, genellikle özel bir durumda eklemeniz gerekiyorsa, bu algoritmanın yeterince basit olmadığı anlamına gelir.)
marinus

2
Bu gerçek büyücülük, tam burada.
Steven Lu

@ Sp3000: Tek elemanlı dizileri doğru yazdınız mı? Sadece 1bir skaler olacağı için yazamazsınız . Bunun (,1)yerine yazmalısınız . Bunu yaparsanız, işe yarıyor.
marinus

4

J - 39

Eminim çok daha kısa olabilir

f=:+/@|:@(>:/)%(]#)
>./@:|@((,f])-(,f[))

kullanım

2 10 10 10 1 6 7 2 10 4 7 >./@:|@((,f])-(,f[)) 7 7 9 9 6 6 5 2 7 2 8
0.363636

Bu bir işlev yaratıyor mu veya stdin / stdout kullanıyor mu? İkinci kısım tam olarak ne yapıyor? (Bir işlev çağrısı için biraz uzun görünüyor mu?)
flawr

@flawr APL benzeri bir işlev
swish

Sanırım böyle bir fşey kullanırsanız açıkça tanımlamaktan kaçınabilirsiniz >./@:|@({.-{:)f"1@,ama tam olarak emin değilim.
FUZxxl

4

Python 3, 132 108 95 88

f=lambda a,x:sum(n>x for n in a)/len(a)
g=lambda a,b:max(abs(f(a,x)-f(b,x))for x in a+b)

Giriş, fonksiyonun 2 listesidir g

Teşekkürler: Sp3000, xnor, yeraltı monoray

Satır 2, f"faks" gibi okumalara ilk çağrı . Hafif eğlenceli buldum


2
Bir listenin bir özelliği karşılayan öğe sayısını saymak daha kısa sürer sum(n>x for n in a). Ayrıca, kullanmadığınız anlaşılıyor s=filter. Ve maxaslında, liste köşeli parantezlerine ihtiyacınız yoktur; Python, fonksiyon parensinin anlama kavgası olarak iki katına çıkmasını sağlar.
xnor

Teşekkürler! Kullandığım filterbir önceki sürümde çıkarmak için unuttum. Ne yazık ki ilk köşeli parantez çiftini kaldıramıyorum çünkü o zaman hayır olan bir jeneratör olacak len.
Kroltan

gerek yok len, yorumu tekrar okuyun: P
undergroundmonorail

3

JavaScript (ES6) 99119 128

Muhtemelen daha fazla golf oynayabilen az çok basit JavaScript uygulaması . F işlevinde, abs = (F (a) -F (b)) === abs ((1-F (a)) - (1-F (b)) gibi <= yerine> kullanıyorum

Bu son düzenlemede varsayılan parametre olarak işlev tanımı yok.

Dediğim gibi, bu basit. F işlevi F işlevidir, D işlevi satır 2'de kullanılan adlandırılmamış işlevdir. allGerçekler için maksimum değer bunlardan biri olması gerektiğinden , iki dizide bulunan her değer için .map kullanılarak değerlendirilir . Sonunda, yayma işleci (...) D değerleri dizisini bir parametre listesi olarak max işlevine iletmek için kullanılır.

K=(a,b)=>Math.max(...a.concat(b).map(x=>
  Math.abs((F=a=>a.filter(v=>v>x).length/a.length)(a)-F(b))
))

FireFox / FireBug konsolunda test et

;[[[0],[0]], [[0],[1]],
[[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]],
[[3, 3, 3, 3, 3],[5, 4, 3, 2, 1]],
[[1, 2, 1, 4, 3, 6],[3, 4, 5, 4]],
[[8, 9, 9, 5, 5, 0, 3],[4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9]],
[[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7],[7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8]]]
.forEach(x=>console.log(x[0],x[1],K(x[0],x[1]).toFixed(6)))

Çıktı

[0] [0] 0.000000
[0] [1] 1.000000
[1, 2, 3, 4, 5] [2, 3, 4, 5, 6] 0.200000
[3, 3, 3, 3, 3] [5, 4, 3, 2, 1] 0.400000
[1, 2, 1, 4, 3, 6] [3, 4, 5, 4] 0.500000
[8, 9, 9, 5, 5, 0, 3] [4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9] 0.175824
[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7] [7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8] 0.363636

Ben senin fonksiyon hakkında curous K: F,Dargüman listesindeki diğer fonksiyonları tanımlamak doğru mu? Bu, bazı isteğe bağlı argümanlar gibi mi davranıyor?
flawr

@flawr evet, bunlar varsayılan değeri olan isteğe bağlı bağımsız değişkenlerdir. Yani küresel değişken alan kirliliğinden kaçınmak (bu kod golf bir sorun değil, ama yine de ...)
edc65

1
Ayrıca, işlev zaten 2 değişken (dolayısıyla köşeli ayraçlar) gerektirdiğinden, bu değişkenleri seçenek var listesinden işlev gövdesinin içine taşımak 2 bayt fazla olacaktır.
Doktor

2

CJam, 33 31 bayt

q~_:+f{\f{f<_:+\,d/}}z{~-z}%$W=

Giriş, iki dizinin CJam stil dizisidir.

Misal:

[[8 9 9 5 5 0 3] [4 9 0 5 5 0 4 6 9 10 4 0 9]]

Çıktı:

0.17582417582417587

Buradan çevrimiçi deneyin


2

Matlab (121) (119)

Bu, stu stdin ile iki liste alan ve sonucu stdout'a yazdıran bir programdır. Bu strightfwd bir yaklaşım ve mümkün olduğunca golf yapmaya çalıştım. hesaplayan K(a)bir işlev döndürür x -> F(a,x). Ardından, işleve @(x)abs(g(x)-h(x))karşılık gelen anonim işlev D, olası her tamsayıya uygulanır 0:max([a,b])ve sonuçların maksimumu görüntülenir. ( diğer dillerle arrayfunaynı şeyi yapar map: bir dizinin her öğesine bir işlev uygular)

a=input('');b=input('');
K=@(a)@(x)sum(a<=x)/numel(a);
g=K(a);h=K(b);
disp(max(arrayfun(@(x)abs(g(x)-h(x)),0:max([a,b]))))

2

Erlang, 96 Bayt

edc65'in JavaScript çözümü Erlang'a taşındı.

f(A,B)->F=fun(A,X)->length([V||V<-A,V>X])/length(A)end,lists:max([abs(F(A,X)-F(B,X))||X<-A++B]).

Ölçek:

lists:foreach(fun ([H,T] = L) -> io:format("~p ~p~n", [L, w:f(H, T)]) end, [[[0],[0]], [[0],[1]],
        [[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]],
        [[3, 3, 3, 3, 3],[5, 4, 3, 2, 1]],
        [[1, 2, 1, 4, 3, 6],[3, 4, 5, 4]],
        [[8, 9, 9, 5, 5, 0, 3],[4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9]],
        [[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7],[7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8]]]).

Çıktı:

[[0],[0]] 0.0
[[0],[1]] 1.0
[[1,2,3,4,5],[2,3,4,5,6]] 0.20000000000000007
[[3,3,3,3,3],[5,4,3,2,1]] 0.4
[[1,2,1,4,3,6],[3,4,5,4]] 0.5
[[8,9,9,5,5,0,3],[4,9,0,5,5,0,4,6,9,10,4,0,9]] 0.17582417582417587
[[2,10,10,10,1,6,7,2,10,4,7],[7,7,9,9,6,6,5,2,7,2,8]] 0.36363636363636365

2

STATA 215

% 90, STATA'nın zaten bir ksmirnov komutuna sahip olması nedeniyle girdiyi kullanılabilecek bir formata alıyor.

di _r(a)
di _r(b)
file open q using "b.c",w
forv x=1/wordcount($a){
file w q "1,"(word($a,`x'))_n
}
forv x=1/wordcount($b){
file w q "2,"(word($b,`x'))_n
}
file close q
insheet using "b.c"
ksmirnov v2,by(v1)
di r(D)

Vay canına, dillerin bunun için bir yerleşik olacağını sanmıyordum ... Sadece biraz araştırma yaptım ve bundan sonra yerleşiklere izin vermemenin en iyisi olduğuna karar verdim, ama bunu devam ettirebilirsin, çünkü kuraldan önce gönderildi değişim :)
Sp3000

2

R, 65 bayt

f=function(a,b){d=c(a,b);e=ecdf(a);g=ecdf(b);max(abs(e(d)-g(d)))}

Bu işlev iki vektörü bağımsız değişken olarak alır ve deneysel birikimli dağılım işlevlerinin maksimum farkını verir.

Yerleşik yapılara izin verilirse, yalnızca 12 bayta düşecektir:

ks.test(a,b)

1

Mathematica, 76 73 63

Mathematica'nın yerleşik işlevi vardır KolmogorovSmirnovTest, ancak burada kullanmayacağım.

k=N@MaxValue[Abs[#-#2]&@@(Tr@UnitStep[x-#]/Length@#&/@{##}),x]&

Kullanımı:

k[{1, 2, 1, 4, 3, 6}, {3, 4, 5, 4}]

0.5


0

Python 3.4.2'de hızlı uygulama (79 bayt):

F=lambda A,x:len([n for n in A if n<=x])/len(A)
D=lambda x:abs(F(A1,x)-F(A2,x))

Misal:

>>> A1 = [-5, 10, 8, -2, 9, 2, -3, -4, -4, 9]
>>> A2 = [-5, -3, -10, 8, -4, 1, -7, 6, 9, 5, -7]
>>> D(0)
0.045454545454545414

1
Gereksinim, x'in tüm tamsayı değerleri için maksimum D (x) değerini bulmaktır. Lütfen sorun özelliklerine uyun.
Optimizer

1
Hoşgeldiniz! Optimizer'ın dediği gibi, görev Dyalnızca Dbir işlev olarak uygulamak değil , maksimum değerini bulmaktır . Ayrıca, net olmadığım için üzgünüm, ancak bunu önceden tanımlayamazsınız A1ve A2zaten tanımlanmış değişkenlerdir (bunları lambda x,A1,A2:
lambda'ya

Ayrıca bazı sözdizimi vurgulama ekledim - Bence daha güzel görünmesini sağlar :)
Sp3000

Üzgünüm, burada yeniyim.
Kapten

Sorun yok :) Bir şey net değilse, yorumlarda sorabilirsiniz. Ama bir kez daha hoş geldiniz!
Sp3000

0

Java - 633 622 Bayt

Tamam, önce java'da daha iyi olmaya çalışıyorum, bu yüzden java'da denedim, asla iyi yapmayacağımı biliyorum, ama eğlenceli. İkincisi, dürüstçe ben bunu daha az şekilde yapabileceğini düşündüm, o zaman her yerde çiftler olduğu sahneye aldım ve yöntem bildirimleri yöntemleri kullanarak toplamda sadece 4-5 karakter kurtardı. Kısacası ben kötü bir golfçüyüm.

değiştir: kullanım biçimi> java K "2,10,10,10,1,6,7,2,10,4,7" "7,7,9,9,6,6,5,2,7,2 , 8"

import java.lang.*;
class K{public static void main(String[]a){double[]s1=m(a[0]);double[]s2=m(a[1]);
int h=0;if(H(s1)<H(s2))h=(int)H(s2);else h=(int)H(s1);double[]D=new double[h];
for(int i=0;i<h;i++){D[i]=Math.abs(F(s1,i)-F(s2,i));}System.out.println(H(D));}
static double[]m(String S){String[]b=S.split(",");double[]i=new double[b.length];
for(int j=0;j<b.length;j++){i[j]=new Integer(b[j]);}return i;}
static double H(double[]i){double t=0;for(int j=0;j<i.length;j++)
{if(i[j]>t)t=i[j];}return t;}
static double F(double[]A,int x){double t=0;double l=A.length;
for(int i=0;i<l;i++){if(A[i]<=x)t++;}return t/l;}}

haklıydın. güncellenmesi.
Bryan Devaney

0

Haskell 96 83

l=fromIntegral.length
a%x=l(filter(<=x)a)/l a
a!b=maximum$map(\x->abs$a%x-b%x)$a++b

(!) iki liste alan kolmogorov-smirnov işlevidir


1
bazı hızlı golf: kullanmak mapyerine fmap; kullanmak maximumyerine foldr1 max; tanımlamak l=fromIntegral.lengthve kurtulabilirsiniz ive sonra kısaltabilir %için l(filter(<=x)a)/l a. 84'e indirir!
MtnViewMark

0

R, 107 bayt

Farklı yaklaşım

f=function(a,b){e=0
d=sort(unique(c(a,b)))
for(i in d-min(diff(d))*0.8)e=max(abs(mean(a<i)-mean(b<i)),e)
e}

Ungolfed

f=function(a,b){
    e=0
    d=sort(unique(c(a,b)))
    d=d-min(diff(d))*0.8
    for(i in d) {
        f=mean(a<i)-mean(b<i)
        e=max(e,abs(f))
    }
    e
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.