複雑性のないコルモゴロフ(-Smirnov)


12

統計では、2つのデータサンプルが同じ基礎分布からのものかどうかを知ることが役立つ場合があります。これを行う1つの方法は、2サンプルのKolmogorov-Smirnov検定を使用することです。

あなたの仕事は、ソートされていない2つの非負整数配列を読み取り、テストで使用される主な統計を計算するプログラムを作成することです。


配列を指定Aし、実数x、分布関数を定義するFことにより、

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

与えられた2つの配列A1A2を定義します

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

2サンプルのコルモゴロフ-スミルノフ統計は、Dすべての実数の最大値ですx

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

次に:

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

2つの配列のKS統計は1/2、の最大値ですD

テストケース

[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

ルール

  • 関数または完全なプログラムを作成できます。入力はSTDINまたは関数引数を介して行われ、出力はSTDOUTまたは戻り値を介して行われます。
  • 両方の配列で一貫している限り、入力に対して明確なリストまたは文字列形式を想定できます。
  • あなたの言語がこのために組み込まれているという偶然に、あなたはそれを使わないかもしれません。
  • 回答は少なくとも3つの有効数字に対して正しい必要があります
  • これはなので、最小バイトのプログラムが勝ちます

すべての入力は整数配列になりますか、または浮動小数点を含むことができますか?
ケニー

@KennyTMちょうど非負の整数。私は物事をシンプルにすると思った。
Sp3000

配列に想定できる最大値はありますか?(たとえば、すべてのエントリAは以下length(A)ですか?)
flawr

@flawrいいえ、最大値を想定することはできません
Sp3000

タイトルが好きです。私はコルモゴロフの複雑さをターゲットにしていますが、今回はそうではありません。
edc65

回答:


10

APL(29 24)

(追加のインスピレーションをくれたZgarbに感謝します。)

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

これは、配列を左右の引数としてとる関数です。

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

説明:

{⌈/                                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
                          }

あなたができるとは知りませんでした⍺⍵!それは便利です。
ズガーブ

1
また、⍳⌈/最大値は配列値の1つで正確に取得されるため、不要だと思います。
ズガルブ

@Zgarb:もちろん、あなたは正しい、私はそれぞれの可能な配列値をテストするだけです。つまり0,、配列に含まれているかどうかをテストするので、これも取り除くことができます。ありがとう!(そして、特別な場合に追加する必要がある場合、通常、アルゴリズムが十分に単純ではないことを意味するように、それは私に教えてくれます。)
マリナス

2
これはまさに魔法です。
スティーブンルー

@ Sp3000:1要素配列を正しく記述しましたか?を書くことはできません1。スカラーになるからです。(,1)代わりに書く必要があります。それをすれば、それははたらきます。
マリヌス

4

J-39

もっと短くできると確信しています

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

使用法

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

これは関数を作成しますか、それともstdin / stdoutを使用しますか?第二部は正確に何をしますか?(関数呼び出しに少し時間が
かかり

@flawr APLと同様の機能、
スウィッシュ

fようなものを使用する場合、明示的に定義することを避けることができると思いますが>./@:|@({.-{:)f"1@,、私はよくわかりません。
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)

入力は、関数への2つのリストです。 g

おかげで:Sp3000、xnor、undergroundmonorail

2行目、f「fax」のような読み取りの最初の呼び出し。少しおもしろいことがわかりました


2
プロパティを満たすリストの要素の数を数えるには、doのほうが短いですsum(n>x for n in a)。また、を使用していないようですs=filter。またmax、リストブラケットは実際には必要ありません。Pythonでは、関数parensを内包括弧として二重にできます。
xnor

ありがとう!filter以前のバージョンで使用しましたが、削除するのを忘れていました。悲しいことに、角括弧の最初のペアを削除することはできませんlen
クロルタン

不要ですlen、もう一度コメントをお読みください:P
undergroundmonorail

3

JavaScriptの(ES6)99 119 128

多かれ少なかれ簡単なJavaScript実装で、おそらくよりゴルフに適しています。F関数では、abs(F(a)-F(b))=== abs((1-F(a))-(1-F(b)))のように、<=の代わりに>を使用します

この最後の編集では、デフォルトパラメータとしての関数定義はありません。

私が言ったように、それは簡単です。F関数はF関数、D関数は2行目で使用される名前のない関数allです。実数の最大値はこれらのいずれかでなければならないため、2つの配列に存在する各値に対して.mapを使用して評価されます。最後に、スプレッド演算子(...)を使用して、D値配列をパラメーターリストとしてmax関数に渡します。

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コンソールでテストする

;[[[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)))

出力

[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

私はあなたの関数に興味がありますKF,D引数リストで他の関数を定義するのは正しいですか?これはいくつかのオプション引数などのように動作しますか?
flawr

@flawrはい、これらはデフォルト値を持つオプションの引数です。そのため、グローバル変数空間の汚染を回避します(コードゴルフでは問題ではありませんが、とにかく...)
edc65

1
さらに、関数には既に2つの変数(かっこ)が必要であるため、これらの変数をオプションvarリストから関数本体の内部に移動するには、余分な2バイトが必要です。
オプティマイザー


2

Matlab (121)(119)

これは、stdinを介して2つのリストを取得し、結果をstdoutに出力するプログラムです。それはstrightfwdの承認者であり、できる限りゴルフをしようとしました。を計算K(a)する関数を返しますx -> F(a,x)。次に、関数@(x)abs(g(x)-h(x))に対応する匿名関数がD可能なすべての整数に適用され0:max([a,b])、結果の最大値が表示されます。(他の言語arrayfunと同じmap:配列のすべての要素に関数を適用します)

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

アーラン、96バイト

edc65のJavaScriptソリューションがErlangに移植されました。

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]).

テスト:

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]]]).

出力:

[[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

STATAにはすでにksmirnovコマンドがあるため、これは入力を使用可能な形式に変換する90%です。

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)

ああ、言語にはこれが組み込まれているとは思いませんでした...いくつかの調査を行っただけで、今後は組み込みを禁止するのが最善だと判断しましたが、ルールの前に投稿されているのでこれを保持できます変更:)
Sp3000

2

R、65バイト

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

この関数は、引数として2つのベクトルを取り、それらの経験的累積分布関数の最大差を返します。

組み込みが許可されている場合、それはわずか12バイトに減少します。

ks.test(a,b)

1

Mathematica、76 73 63

Mathematicaには組み込み関数KolmogorovSmirnovTestがありますが、ここでは使用しません。

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

使用法:

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

0.5


0

Python 3.4.2での迅速な実装(79バイト):

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))

例:

>>> 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
要件は、xのすべての整数値に対してD(x)の最大値を見つけることです。問題の仕様に従ってください。
オプティマイザー

1
ようこそ!オプティマイザーが言うように、タスクは関数としてD実装するだけでなく、の最大値を見つけることDです。また、私は明確ではなかった場合、私は申し訳ありませんが、しかし、あなたがいると仮定することはできませんA1とは、A2すでに定義された変数(あなたががラムダでそれらを置くことができ、例えばlambda x,A1,A2:-大丈夫です)
SP3000

また、いくつかの構文の強調表示を追加しました-見た目がきれいになったと思います:)
Sp3000

それについてすみません、私はここに新しいです。
カプテン

問題ありません:)不明な点がある場合は、コメントでお尋ねください。しかし、もう一度、ようこそ!
Sp3000

0

Java- 633 622バイト

OK、最初に、Javaで良くしようとするので、私はJavaでそれを試したので、私は決してうまくいかないことを知っていますが、それは楽しいです。第二に、私は正直にこれをもっと少なくできると思ったので、どこにでもダブルがあり、メソッドの宣言はメソッドを使用することを意味し、合計で4-5文字しか保存しませんでした。要するに、私は悪いゴルファーです。

編集:使用形式> 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;}}

君は正しかった。更新しています。
ブライアンデヴァニー

0

ハスケル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

(!)は2つのリストを取るkolmogorov-smirnov関数です


1
いくつかのクイックゴルフ:使用するmapよりもfmap; 使用するmaximumよりもfoldr1 max; 定義しl=fromIntegral.length、あなたは取り除くことができますi、そしてあなたはに短縮%することができますl(filter(<=x)a)/l a。84まで下げます!
MtnViewMark

0

R、107バイト

異なるアプローチ

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}

非ゴルフ

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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.