복잡성이없는 Kolmogorov (-Smirnov)


12

통계 상, 때로는 두 개의 데이터 샘플이 동일한 기본 분포에서 나온 것인지 아는 것이 유용합니다. 이를 수행하는 한 가지 방법은 2- 표본 Kolmogorov-Smirnov 검정 을 사용하는 것 입니다.

당신의 임무는 두 개의 정렬되지 않은 음이 아닌 정수 배열을 읽고 테스트에 사용되는 주요 통계를 계산하는 프로그램을 작성하는 것입니다.


배열 A과 실수가 주어지면 x분포 함수 F를 다음 과 같이 정의하십시오.

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

두 배열을 감안 A1하고 A2, 정의

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

2- 표본 Kolmogorov-Smirnov 통계량은 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

두 배열의 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

@KennyTM 음이 아닌 정수입니다. 나는 일을 단순하게 유지할 것이라고 생각했다.
Sp3000

배열에 대해 가정 할 수있는 최대 값이 있습니까? (예 : 모든 항목 A이 아래에 length(A)있습니까?)
flawr

@flawr 아니요 최대 값을 가정 할 수 없습니다
Sp3000

나는 제목을 좋아한다. 나는 kolmogorov의 복잡성 bagde를 목표로하고 있지만 이번에는 아닙니다.
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
                          }

당신이 할 수있는 줄 몰랐어요 ⍺⍵! 편리합니다.
Zgarb

1
또한 ⍳⌈/최대 값이 배열 값 중 하나에서 정확하게 얻어지기 때문에 불필요 하다고 생각 합니다.
Zgarb

@ Zgarb : 물론 맞습니다. 가능한 각 배열 값을 테스트해야합니다. 즉 0,, 배열에 포함되어 있으면 테스트 할 것이므로 제거 할 수도 있습니다 . 감사! (그리고 그것은 특별한 경우에 추가해야하는 것처럼, 알고리즘이 간단하지 않다는 것을 의미합니다.)
marinus

2
이것이 바로 진정한 마법입니다.
Steven Lu

@ Sp3000 : 단일 요소 배열을 올바르게 작성 했습니까? 1스칼라 일 것이므로 쓸 수는 없습니다 . (,1)대신 써야 합니다. 그렇게하면 작동합니다.
marinus

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과 비슷한 기능
swish

나는 당신이 f같은 것을 사용한다면 명시 적으로 정의하는 것을 피할 수 있다고 생각 >./@:|@({.-{:)f"1@,하지만 확실하지 않습니다.
FUZxxl

4

파이썬 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
속성을 만족하는 목록의 요소 수를 계산하려면 수행하는 것이 더 짧습니다 sum(n>x for n in a). 또한 사용하지 않는 것 같습니다 s=filter. 그리고 max에는 실제로 목록 괄호가 필요하지 않습니다. 파이썬은이 함수가 이해력이있는 두배로 두배가되도록합니다.
xnor

감사! filter이전 버전에서 사용 했는데 제거하는 것을 잊었습니다. 슬프게도 대괄호의 첫 번째 쌍을 제거 할 수 없으므로 그 이후에는 발전기가 없습니다 len.
Kroltan

당신은 필요하지 않습니다 lenP : 다시 코멘트를 읽기
undergroundmonorail

3

자바 스크립트 (ES6) 99 119 128

다소 간단한 자바 스크립트 구현 , 아마도 더 골프화가 가능할 것이다. F 함수에서 abs (F (a) -F (b)) === abs ((1-F (a))-(1-F (b))로 <= 대신>를 사용합니다.

이 마지막 편집에서 더 이상 함수 정의를 기본 매개 변수로 정의하지 않습니다.

내가 말했듯이, 그것은 간단합니다. F 함수는 F 함수이고 D 함수는 2 행에 사용 된 이름이없는 함수입니다. all실수 의 최대 값 은이 중 하나 여야하므로 두 배열에있는 각 값에 대해 .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

나는 당신의 함수에 대해 소중 합니다. 인수 목록에서 K다른 함수를 정의하는 것이 맞 F,D습니까? 이것은 선택적인 인수처럼 행동합니까?
flawr

@flawr 예, 기본값이있는 선택적 인수입니다. 따라서 전역 가변 공간의 오염을 피하십시오 (코드 골프에서는 문제가되지 않지만 어쨌든 ...)
edc65

1
또한 함수에는 이미 2 개의 변수 (따라서 대괄호)가 필요했기 때문에 변수 var 옵션에서 함수 본문 내부로 변수를 이동하는 데 2 ​​바이트가 더 필요합니다.
Optimizer


2

MATLAB (121) (119)

이것은 stdin stdin을 통해 두 목록을 가져 와서 결과를 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

스타 타 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)))}

이 함수는 두 벡터를 인수로 사용하여 경험적 누적 분포 함수의 최대 차이를 반환합니다.

내장이 허용 된 경우 12 바이트로 줄어 듭니다.

ks.test(a,b)

1

매스 매 티카, 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)의 최대 값을 찾는 것입니다. 문제 사양을 준수하십시오.
Optimizer

1
어서 오십시오! Optimizer가 말했듯이 작업은 함수로 D구현 D하는 것이 아니라 의 최대 값을 찾는 것 입니다. 또한, 나는 분명 아니었다면 미안하지만, 당신은을지지 않습니다 A1A2이미 (당신은 비록 람다 예에 넣을 수있는 변수를 정의 lambda x,A1,A2:- 괜찮아)
SP3000

또한 구문 강조를 추가했습니다. 더 예쁘게 보일 것 같습니다. :)
Sp3000

그것에 대해 죄송합니다, 나는 여기에 처음입니다.
Kapten

문제 없음 :) 확실하지 않은 사항이 있으면 의견을 요청할 수 있습니다. 그러나 다시 한번, 환영합니다!
Sp3000

0

자바 - 633 622 바이트

좋아, 먼저, 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;}}

당신이 옳았. 업데이트.
Bryan Devaney

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

(!)는 두 가지 목록을 취하는 kolmogorov-smirnov 함수입니다.


1
몇몇 빠른 골프 : map오히려 사용 fmap; maximum오히려 사용하십시오 foldr1 max; 정의 l=fromIntegral.length당신은 제거 할 수 i, 그리고 당신은 줄일 수 있습니다 %l(filter(<=x)a)/l a. 84로 줄입니다!
MtnViewMark 2019

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.