Kolmogorov không phức tạp (-Smirnov)


12

Trong thống kê, đôi khi thật hữu ích khi biết liệu hai mẫu dữ liệu có đến từ cùng một phân phối cơ bản hay không. Một cách để làm điều này là sử dụng thử nghiệm Kolmogorov-Smirnov hai mẫu .

Nhiệm vụ của bạn sẽ là viết một chương trình đọc thành hai mảng số nguyên không âm không phân loại và tính toán thống kê chính được sử dụng trong bài kiểm tra.


Cho một mảng Avà một số thực x, xác định hàm phân phối Fbằng

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

Cho hai mảng A1A2, xác định

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

Thống kê Kolmogorov - Smirnov hai mẫu là giá trị tối đa của Dtất cả thựcx .

Thí dụ

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

Sau đó:

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

Thống kê KS cho hai mảng là 1/2, giá trị tối đa củaD .

Các trường hợp thử nghiệm

[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

Quy tắc

  • Bạn có thể viết một chức năng hoặc một chương trình đầy đủ. Đầu vào có thể thông qua STDIN hoặc đối số chức năng và đầu ra có thể thông qua STDOUT hoặc giá trị trả về.
  • Bạn có thể giả sử bất kỳ danh sách hoặc định dạng chuỗi rõ ràng nào cho đầu vào, miễn là nó phù hợp cho cả hai mảng
  • Nếu bạn không có khả năng sử dụng ngôn ngữ này, bạn không được sử dụng ngôn ngữ này.
  • Câu trả lời cần phải đúng với ít nhất 3 con số quan trọng
  • Đây là , vì vậy chương trình trong ít byte nhất sẽ thắng

Có phải tất cả các đầu vào sẽ là mảng số nguyên, hoặc chúng có thể chứa các dấu phẩy động?
kennytm 2/2/2015

@KennyTM Chỉ là số nguyên không âm. Tôi nghĩ tôi sẽ giữ mọi thứ đơn giản.
Sp3000 2/2/2015

Có một giá trị tối đa chúng ta có thể giả định cho các mảng? (Ví dụ: tất cả các mục Abên dưới length(A)?)
flawr 2/215

@flawr Không, bạn không thể giả sử giá trị tối đa
Sp3000

Tôi thích tiêu đề. Tôi đang nhắm mục tiêu vào bagde phức tạp kolmogorov, nhưng không phải lúc này.
edc65

Câu trả lời:


10

APL ( 29 24)

(Cảm ơn Zgarb vì đã truyền cảm hứng thêm.)

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

Đây là một hàm lấy các mảng làm đối số trái và phải của nó.

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

Giải trình:

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

Tôi không biết bạn có thể làm được ⍺⍵! Thật tiện dụng.
Zgarb 2/2/2015

1
Ngoài ra, tôi nghĩ ⍳⌈/là không cần thiết, vì tối đa thu được chính xác tại một trong các giá trị mảng.
Zgarb 2/2/2015

@Zgarb: tất nhiên bạn đúng, tôi chỉ phải kiểm tra từng giá trị mảng có thể. Điều đó có nghĩa là tôi cũng có thể thoát khỏi 0,, vì nó sẽ kiểm tra xem nếu mảng chứa nó. Cảm ơn! (Và điều đó sẽ dạy tôi, như thường lệ nếu bạn phải thêm vào một trường hợp đặc biệt, điều đó có nghĩa là thuật toán không đủ đơn giản.)
marinus

2
Đây là phép thuật thực sự, ngay tại đây.
Steven Lu

@ Sp3000: bạn đã viết đúng một phần tử chưa? Bạn không thể chỉ viết 1, vì đó sẽ là một vô hướng. Bạn nên viết (,1)thay thế. Nếu bạn làm điều đó, nó hoạt động.
bến tàu

4

J - 39

Tôi chắc chắn có thể rút ngắn hơn nhiều

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

Sử dụng

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

Điều này có tạo ra một chức năng hoặc sử dụng stdin / stdout? Phần thứ hai chính xác làm gì? (Có vẻ hơi dài cho một cuộc gọi chức năng?)
flawr 2/215

@flawr Một chức năng, tương tự như APL
swish

Tôi nghĩ rằng bạn có thể tránh xác định rõ ràng fnếu bạn sử dụng một cái gì đó như >./@:|@({.-{:)f"1@,nhưng tôi không chắc chắn lắm.
FUZxxl 2/2/2015

4

Trăn 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)

Đầu vào là 2 danh sách cho chức năng g

Cảm ơn: Sp3000, xnor, ngầmmonorail

Dòng 2, cuộc gọi đầu tiên để fđọc như "fax". Tôi thấy rằng thật thú vị


2
Để đếm số lượng phần tử của danh sách thỏa mãn thuộc tính, cần thực hiện ngắn hơn sum(n>x for n in a). Ngoài ra, có vẻ như bạn không sử dụng s=filter. Và đối với max, bạn không thực sự cần dấu ngoặc danh sách; Python cho phép hàm parens tăng gấp đôi khi parens hiểu.
xnor 2/2/2015

Cảm ơn! Tôi đã sử dụng filtertrong một phiên bản trước, quên loại bỏ nó. Đáng buồn là tôi không thể loại bỏ cặp ngoặc vuông đầu tiên kể từ đó nó sẽ là một trình tạo, không có len.
Kroltan 2/2/2015

bạn không cần len, hãy đọc lại bình luận: P
ngầmmonorail

3

JavaScript (ES6) 99 119 128

Việc triển khai JavaScript đơn giản hơn hoặc ít hơn , có thể dễ chơi hơn . Trong hàm F tôi sử dụng> thay vì <=, như abs (F (a) -F (b)) === abs ((1-F (a)) - (1-F (b)))

Không còn định nghĩa hàm như trình duyệt mặc định trong lần chỉnh sửa cuối cùng này.

Như tôi đã nói, nó đơn giản. Hàm F là hàm F, hàm D là hàm không tên được sử dụng trong dòng 2. Nó được đánh giá bằng cách sử dụng .map cho mỗi giá trị có trong hai mảng, vì giá trị tối đa cho các allsố thực phải là một trong số này. Cuối cùng, toán tử trải (...) được sử dụng để truyền mảng giá trị D dưới dạng danh sách tham số cho hàm 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))
))

Kiểm tra trong bảng điều khiển 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)))

Đầu ra

[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

Tôi tò mò về chức năng của bạn K: Có đúng không khi bạn xác định các chức năng khác F,Dtrong danh sách đối số? Điều này có hành xử như một số đối số tùy chọn hay không?
lỗ hổng

@flawr có, chúng là các đối số tùy chọn có giá trị mặc định. Vì vậy, tránh ô nhiễm không gian biến toàn cầu (đó không phải là vấn đề trong môn đánh gôn, nhưng dù sao thì ...)
edc65

1
Thêm vào đó, vì hàm đã yêu cầu 2 biến (do đó là ngoặc), nên sẽ có thêm 2 byte để di chuyển các biến đó ra khỏi danh sách var tùy chọn vào bên trong thân hàm.
Trình tối ưu hóa


2

Matlab (121) (119)

Đây là một chương trình có hai danh sách thông qua stdin và in kết quả ra thiết bị xuất chuẩn. Đó là một sự chấp thuận ổn định và tôi đã cố gắng đánh golf nó nhiều nhất có thể. K(a)trả về một hàm tính toán x -> F(a,x). Sau đó, hàm ẩn danh @(x)abs(g(x)-h(x))tương ứng với hàm Dđược áp dụng cho mọi số nguyên có thể 0:max([a,b])và tối đa của kết quả được hiển thị. ( arrayfunthực hiện giống như maptrong các ngôn ngữ khác: nó áp dụng một hàm cho mọi phần tử của mảng)

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 byte

Giải pháp JavaScript của edc65 được chuyển đến 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]).

Kiểm tra:

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

Đầu ra:

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

SỐ LIỆU 215

Đây là 90% nhận đầu vào thành một định dạng có thể được sử dụng vì STATA đã có lệnh ksmirnov.

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)

Ôi chà, tôi không nghĩ rằng các ngôn ngữ sẽ có nội dung cho việc này ... Tôi mới thực hiện một số nghiên cứu và tôi quyết định tốt nhất là không cho phép các nội dung từ bây giờ, nhưng bạn có thể giữ điều này vì nó đã được đăng trước quy tắc thay đổi :)
Sp3000

2

R, 65 byte

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

Hàm này lấy hai vectơ làm đối số và trả về chênh lệch tối đa của các hàm phân phối tích lũy theo kinh nghiệm của chúng.

Nếu tích hợp được cho phép, nó sẽ giảm xuống chỉ còn 12 byte:

ks.test(a,b)

1

Toán học, 76 73 63

Mathematica có chức năng tích hợp sẵn KolmogorovSmirnovTest, nhưng tôi sẽ không sử dụng nó ở đây.

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

Sử dụng:

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

0,5


0

Triển khai nhanh trong Python 3.4.2 (79 byte):

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

Thí dụ:

>>> 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
Yêu cầu là tìm giá trị tối đa của D (x) cho tất cả các giá trị số nguyên của x. Hãy tuân thủ các thông số kỹ thuật.
Trình tối ưu hóa

1
Chào mừng bạn Như Trình tối ưu hóa nói, nhiệm vụ là tìm giá trị tối đa D, không chỉ thực hiện Dnhư một hàm. Ngoài ra, tôi xin lỗi nếu tôi đã không rõ ràng, nhưng bạn không thể giả định rằng A1A2đã được định nghĩa các biến (bạn có thể đặt chúng trong lambda tuy nhiên, ví dụ lambda x,A1,A2:- đó là okay)
Sp3000

Ngoài ra tôi đã thêm một số cú pháp tô sáng - Tôi nghĩ rằng nó làm cho nó trông đẹp hơn :)
Sp3000

Xin lỗi về điều đó, tôi mới ở đây.
Kapten 2/2/2015

Không có vấn đề :) Nếu bất cứ điều gì không rõ ràng, bạn có thể hỏi trong các ý kiến. Nhưng một lần nữa, chào mừng!
Sp3000 2/2/2015

0

Java - 633 622 byte

Ok, đầu tiên, cố gắng cải thiện java vì vậy đó là lý do tại sao tôi đã thử nó trong java, tôi biết tôi sẽ không bao giờ làm tốt, nhưng eh, nó rất vui. Thứ hai, tôi thành thật nghĩ rằng tôi có thể làm điều này theo cách ít hơn, sau đó tôi đã đến giai đoạn có gấp đôi ở khắp mọi nơi, và các khai báo phương thức có nghĩa là sử dụng các phương thức chỉ lưu tổng cộng 4-5 ký tự. Nói tóm lại, tôi là một tay golf tồi.

chỉnh sửa: định dạng sử dụng> java K "2,10,10,10,1,6,7,2,10,4,7" "7,7,9,9,6,6,5,2,7,2 ,số 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;}}

bạn đa đung. đang cập nhật
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

(!) là hàm kolmogorov-smirnov có hai danh sách


1
một số golf nhanh: sử dụng mapchứ không phải fmap; sử dụng maximumchứ không phải foldr1 max; xác định l=fromIntegral.lengthvà bạn có thể thoát khỏi i, và sau đó bạn có thể rút ngắn %tới l(filter(<=x)a)/l a. Giảm xuống còn 84!
MtnViewMark

0

R, 107 byte

Phương pháp khác nhau

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}

Ung dung

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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.