Chỉ số đa dạng Simpson


19

Các chỉ số Simpson là một thước đo của sự đa dạng của một tập hợp các mục có bản sao. Nó chỉ đơn giản là xác suất vẽ hai mặt hàng khác nhau khi chọn mà không thay thế đồng đều một cách ngẫu nhiên.

Với ncác mục trong nhóm các n_1, ..., n_kmục giống hệt nhau, xác suất của hai mục khác nhau là

$$ 1- \ sum_ {i = 1} ^ k \ frac {n_i (n_i-1)} {n (n -1)} $$

Ví dụ: nếu bạn có 3 quả táo, 2 quả chuối và 1 củ cà rốt, chỉ số đa dạng là

D = 1 - (6 + 2 + 0)/30 = 0.7333

Ngoài ra, số lượng các cặp khác nhau của các mặt hàng khác nhau nằm 3*2 + 3*1 + 2*1 = 11trong tổng số 15 cặp và 11/15 = 0.7333.

Đầu vào:

Một chuỗi các ký tự Ađể Z. Hoặc, một danh sách các nhân vật như vậy. Độ dài của nó sẽ ít nhất là 2. Bạn có thể không cho rằng nó được sắp xếp.

Đầu ra:

Chỉ số đa dạng Simpson của các ký tự trong chuỗi đó, nghĩa là xác suất hai ký tự được lấy ngẫu nhiên thay thế là khác nhau. Đây là một số từ 0 đến 1.

Khi xuất ra một dấu phẩy, hiển thị ít nhất 4 chữ số, mặc dù chấm dứt các đầu ra chính xác như 1hoặc 1.0hoặc 0.375OK.

Bạn không được sử dụng các phần tử tích hợp đặc biệt tính toán các chỉ số đa dạng hoặc các biện pháp entropy. Lấy mẫu ngẫu nhiên thực tế là tốt, miễn là bạn có đủ độ chính xác trong các trường hợp thử nghiệm.

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

AAABBC 0.73333
ACBABA 0.73333
WWW 0.0
CODE 1.0
PROGRAMMING 0.94545

Bảng xếp hạng

Đây là bảng xếp hạng ngôn ngữ, lịch sự của Martin Büttner .

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

# Ruby, <s>104</s> <s>101</s> 96 bytes


Bạn đang sử dụng chỉ số Gini-Simpson, khi một biện pháp tốt hơn để sử dụng là chỉ số Simpson nghịch đảo hay còn gọi là số loại hiệu quả.
Joe Z.

1
Về cơ bản 1/thay vì 1-. [mũ thống kê nghiệp dư rant hat]
Joe Z.

Câu trả lời:


5

Con trăn 2, 72

Đầu vào có thể là một chuỗi hoặc một danh sách.

def f(s):l=len(s);return sum(s[i%l]<>s[i/l]for i in range(l*l))/(l-1.)/l

Tôi đã biết rằng nó sẽ ngắn hơn 2 byte trong Python 3 vì vậy xin đừng tư vấn cho tôi :)


Các dấu ngoặc góc <>đang làm gì ở vị trí 36? Tôi chưa bao giờ thấy cú pháp đó trước đây.
Tiếp

@TuttiFruttiJiến: đó là từ đồng nghĩa với !=.
RemcoGerlich 21/07/2015

1
@TuttiFruttiJiến Đó chỉ là con trăn 2 trừ khi bạnfrom __future__ import barry_as_FLUFL
matjoyce 21/07/2015

@ Vioz- Không có l=len(s);trong đó
Sp3000

@ Sp3000 Đúng, không nhận thấy nó đã được sử dụng bao nhiêu lần.
Kade

4

Pyth - 19 13 12 11 byte

Cảm ơn @isaacg đã cho tôi biết về n

Sử dụng phương pháp vũ phu với .cchức năng kết hợp.

csnMK.cz2lK

Hãy thử nó ở đây trực tuyến .

Bộ thử nghiệm .

c                Float division
 s               Sum (works with True and False)
  nM             Map uniqueness
   K             Assign value to K and use value
    .c 2         Combinations of length 2
      z          Of input
 lK              Length of K

Bạn có thể thay thế .{bằng n- chúng tương đương ở đây.
isaacg

@isaacg oh không biết nó tự động splat, tuyệt.
Maltysen

4

SQL (PostgreSQL), 182 byte

Là một chức năng trong postgres.

CREATE FUNCTION F(TEXT)RETURNS NUMERIC AS'SELECT 1-sum(d*(d-1))/(sum(d)*(sum(d)-1))FROM(SELECT COUNT(*)d FROM(SELECT*FROM regexp_split_to_table($1,''''))I(S)GROUP BY S)A'LANGUAGE SQL

Giải trình

CREATE FUNCTION F(TEXT) -- Create function f taking text parameter
RETURNS NUMERIC         -- declare return type
AS'                     -- return definition
    SELECT 1-sum(d*(d-1))/(sum(d)*(sum(d)-1)) -- Calculate simpson index
    FROM(
        SELECT COUNT(*)d  -- Count occurrences of each character
        FROM(             -- Split the string into characters
            SELECT*FROM regexp_split_to_table($1,'''')
            )I(S)
        GROUP BY S        -- group on the characters
        )A 
'
LANGUAGE SQL

Sử dụng và chạy thử

SELECT S, F(S)
FROM (
    VALUES
    ('AAABBC'),
    ('ACBABA'),
    ('WWW'),
    ('CODE'),
    ('PROGRAMMING')
   )I(S)

S              F
-------------- -----------------------
AAABBC         0.73333333333333333333
ACBABA         0.73333333333333333333
WWW            0.00000000000000000000
CODE           1.00000000000000000000
PROGRAMMING    0.94545454545454545455

4

J, 26 byte

1-+/((#&:>@</.~)%&(<:*])#)

phần mát mẻ

Tôi tìm thấy số đếm của từng ký tự bằng cách khóa </.chuỗi vào chính nó ( ~để theo phản xạ) sau đó đếm các chữ cái của mỗi hộp.


1
(#&:>@</.~)có thể (#/.~)(<:*])có thể (*<:). Nếu bạn sử dụng một chức năng thích hợp, điều này mang lại (1-(#/.~)+/@:%&(*<:)#). Vì các dấu ngoặc xung quanh thường không được tính ở đây (để lại 1-(#/.~)+/@:%&(*<:)#, phần thân của hàm), nên cung cấp 20 byte.
ngẫu nhiên

4

Python 3, 66 58 byte

Đây là sử dụng công thức đếm đơn giản được cung cấp trong câu hỏi, không có gì quá phức tạp. Đây là một hàm lambda ẩn danh, vì vậy để sử dụng nó, bạn cần đặt tên cho nó.

Đã lưu 8 byte (!) Nhờ Sp3000.

lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s)

Sử dụng:

>>> f=lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s)
>>> f("PROGRAMMING")
0.945454

hoặc là

>>> (lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s))("PROGRAMMING")
0.945454

3

APL, 39 36 byte

{n←{≢⍵}⌸⍵⋄N←≢⍵⋄1-(N-⍨N×N)÷⍨+/n-⍨n×n}

Điều này tạo ra một đơn nguyên không tên.

{
  n ← {≢⍵}⌸⍵               ⍝ Number of occurrences of each letter
  N ← ≢⍵                   ⍝ Number of characters in the input
  1-(N-⍨N×N)÷⍨+/n-⍨n×n     ⍝ Return 1 - sum((n*n-n)/(N*N-N))
}

Bạn có thể thử trực tuyến !


2

Bình thường, 13 byte

csnM*zz*lztlz

Khá nhiều bản dịch nghĩa đen của giải pháp @ frageum.


2

CJam, 25 byte

l$_e`0f=_:(.*:+\,_(*d/1\-

Dùng thử trực tuyến

Khá trực tiếp thực hiện các công thức trong câu hỏi.

Giải trình:

l     Get input.
$     Sort it.
_     Copy for evaluation of denominator towards the end.
e`    Run-length encoding of string.
0f=   Map letter/length pairs from RLE to only length.
      We now have a list of letter counts.
_     Copy list.
:(    Map with decrement operator. Copy now contains letter counts minus 1.
.*    Vectorized multiply. Results in list of n*(n-1) for each letter.
:+    Sum vector. This is the numerator.
\     Bring copy of input string to top.
,     Calculate length.
_(    Copy and decrement.
*     Multiply. This is the denominator, n*(n-1) for the entire string.
d     Convert to double, otherwise we would get integer division.
/     Divide.
1\-   Calculate one minus result of division to get final result.

1

J, 37 byte

(1-([:+/]*<:)%+/*[:<:+/)([:+/"1~.=/])

nhưng tôi tin rằng nó vẫn có thể được rút ngắn.

Thí dụ

(1-([:+/]*<:)%+/*[:<:+/)([:+/"1~.=/]) 'AAABBC'

Đây chỉ là một phiên bản ngầm của chức năng sau:

   fun =: 3 : 0
a1=.+/"1 (~.y)=/y
N=.(+/a1)*(<:+/a1)
n=.a1*a1-1
1-(+/n)%N
)

Sau một số hoạt động chơi gôn bổ sung và biến nó thành một chức năng phù hợp: (1-(%&([:+/]*<:)+/)@(+/"1@=))cung cấp 29 byte. 27 nếu chúng ta không đếm các dấu ngoặc xung quanh hàm (1-(%&([:+/]*<:)+/)@(+/"1@=))vì nó phổ biến ở đây. Ghi chú: =ylà chính xác (~.=/])yvà kết hợp soạn thảo ( x u&v y= (v x) u (v y)) cũng rất hữu ích.
ngẫu nhiên

Cảm ơn những lời đề nghị! Tôi vẫn đang học cách tự viết các biểu thức ngầm. Hiện tại, tôi sử dụng 13: 0 để tạo từng phần định nghĩa ngầm và kết hợp.
gar

1

C, 89

Điểm chỉ dành cho chức năng fvà loại trừ khoảng trắng không cần thiết, chỉ bao gồm cho rõ ràng. các mainchức năng là chỉ để thử nghiệm.

i,c,n;
float f(char*v){
  n=strlen(v);
  for(i=n*n;i--;)c+=v[i%n]!=v[i/n]; 
  return 1.0*c/(n*n-n);
}

main(int C,char**V){
  printf("%f",f(V[1]));
}

Nó chỉ đơn giản là so sánh mọi nhân vật với mọi nhân vật khác, sau đó chia cho tổng số so sánh.


1

Trăn 3, 56

lambda s:sum(a!=b for a in s for b in s)/len(s)/~-len(s)

Đếm các cặp phần tử không bằng nhau, sau đó chia cho số lượng các cặp như vậy.


1

Haskell, 83 byte

Tôi biết tôi đến muộn, tìm thấy cái này, đã quên đăng. Loại không phù hợp với Haskell yêu cầu tôi chuyển đổi số nguyên thành số mà bạn có thể chia cho nhau.

s z=(l(filter id p)-l z)/(l p-l z) where p=[c==d|c<-z,d<-z]
l=fromIntegral.length

0

CJam, 23 byte

1r$e`{0=,~}%_:+\,,:+d/-

Byte-khôn ngoan, đây là một cải tiến rất nhỏ so với câu trả lời của @ RetoKoradi , nhưng nó sử dụng một mẹo nhỏ gọn:

Tổng của n số nguyên không âm đầu tiên bằng n (n - 1) / 2 , chúng ta có thể sử dụng để tính tử số và mẫu số, cả hai chia cho 2 , của phân số trong công thức của câu hỏi.

Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

 r$                     e# Read a token from STDIN and sort it.
   e`                   e# Perform run-length encoding.
     {    }%            e# For each [length character] pair:
      0=                e#   Retrieve the length of the run (L).
        ,~              e#   Push 0 1 2 ... L-1.
                        e# Collect all results in an array.
            _:+         e# Push the sum of the entries of a copy.
               \,       e# Push the length of the array (L).
                 ,:+    e# Push 0 + 1 + 2 + ... + L-1 = L(L-1)/2.
                    d/  e# Cast to Double and divide.
1                     - e# Subtract the result from 1.

0

APL, 26 byte

{1-+/÷/{⍵×⍵-1}({⍴⍵}⌸⍵),≢⍵}

Giải trình:

  • ≢⍵: lấy chiều dài của chiều thứ nhất của . Cho rằng đó được coi là một chuỗi, điều này có nghĩa là độ dài của chuỗi.
  • {⍴⍵}⌸⍵: cho mỗi phần tử duy nhất trong , lấy độ dài của mỗi thứ nguyên của danh sách các lần xuất hiện. Điều này đưa ra số lần một mục xuất hiện cho mỗi mục, dưới dạng 1×≢⍵ma trận.
  • ,: nối hai cái dọc theo trục hoành. Vì ≢⍵là vô hướng và giá trị khác là một cột, chúng ta có một 2×≢⍵ma trận trong đó cột đầu tiên có số lần một mục xuất hiện cho mỗi mục và cột thứ hai có tổng số lượng mục.
  • {⍵×⍵-1}: cho mỗi ô trong ma trận, tính toán N(N-1).
  • ÷/: giảm hàng theo cách chia. Điều này chia giá trị cho mỗi mục cho giá trị cho tổng số.
  • +/: tổng kết quả cho mỗi hàng.
  • 1-: trừ nó từ 1
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.