Simpson çeşitlilik endeksi


19

Simpson indeksi tekrarlar da öğelerin bir koleksiyon çeşitliliği bir ölçüsüdür. Rastlantısal olarak eşit bir şekilde değiştirmeden toplama yaparken iki farklı öğe çizme olasılığıdır.

İle ngruplar halinde öğeleri n_1, ..., n_kbenzer öğelerin, iki farklı öğeler olasılığıdır

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

Örneğin, 3 elma, 2 muz ve 1 havuçunuz varsa, çeşitlilik endeksi

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

Alternatif olarak, farklı öğelerin sıralanmamış çiftlerinin sayısı 3*2 + 3*1 + 2*1 = 11genel olarak 15 çiftten, ve 11/15 = 0.7333.

Giriş:

Karakter bir dize Akadar Z. Veya bu karakterlerin bir listesi. Uzunluğu en az 2 olacaktır. Sıralandığını farz edemezsiniz.

Çıktı:

Bu dizgideki karakterlerin Simpson çeşitlilik endeksi, yani iki karakterin yerine koyma ile rasgele alınmış olma olasılığı farklıdır. Bu 0 ile 1 arasında bir sayıdır.

Bir kayan nokta çıktısı verirken, 1veya 1.0veya gibi tam çıktıları sonlandırırken en az 4 basamak görüntüleyin 0.375.

Özellikle çeşitlilik indekslerini veya entropi önlemlerini hesaplayan yerleşik bileşenleri kullanamazsınız. Gerçek rastgele örnekleme, test senaryolarında yeterli doğruluk elde ettiğiniz sürece iyidir.

Test senaryoları

AAABBC 0.73333
ACBABA 0.73333
WWW 0.0
CODE 1.0
PROGRAMMING 0.94545

Liderler Sıralaması

İşte Martin Büttner'in izniyle bir dil tablosu .

Yanıtınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak yanıtınızı bir başlıkla başlatın:

# Language Name, N bytes

Ngönderiminizin büyüklüğü nerede . Puanınızı artırmak varsa, olabilir onları içinden vurarak, başlığa eski hesapları tutmak. Örneğin:

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


Gini-Simpson endeksini kullanıyorsunuz, kullanmak için çok daha iyi bir önlem, ters Simpson endeksi olarak adlandırılan etkili tip sayısı olduğunda.
Joe Z.

1
Temel 1/olarak 1-. [amatör istatistikçi rant hat kapalı]
Joe Z.

Yanıtlar:


5

Python 2, 72

Giriş bir dize veya bir liste olabilir.

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

Zaten Python 3'te 2 bayt daha kısa olacağını biliyorum, bu yüzden lütfen bana tavsiye etmeyin :)


<>36. konumda köşeli ayraçlar ne yapıyor? Bu sözdizimini daha önce hiç görmedim.
ApproachingDarknessFish

@TuttiFruttiJacuzzi: ile eşanlamlıdır !=.
RemcoGerlich

1
@TuttiFruttiJacuzzi Siz sürece sadece python 2from __future__ import barry_as_FLUFL
matsjoyce

@ Vioz- Değil ile l=len(s);orada
SP3000

@ Sp3000 Doğru, kaç kez kullanıldığını fark etmedi.
Kade

4

Pyth - 19 13 12 11 bayt

@İsaacg'a n hakkında bilgi verdiğiniz için teşekkürler

Komut .cfonksiyonu ile kaba kuvvet yaklaşımını kullanır .

csnMK.cz2lK

Burada çevrimiçi deneyin .

Test takı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

Sen yerini alabilir .{ile n- burada eşdeğerdir.
isaacg

@isaacg oh otomatik olarak uyarıları bilmiyordum, serin.
Maltysen

4

SQL (PostgreSQL), 182 Bayt

Postgres bir fonksiyon olarak.

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

açıklama

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

Kullanım ve Test Çalışması

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 bayt

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

havalı kısım

Her bir karakterin sayılarını </.dizeyi kendisine karşı ( ~refleksif olarak) tuşlayıp her bir kutunun harflerini sayarak buldum .


1
(#&:>@</.~)olabilir (#/.~)ve (<:*])olabilir (*<:). Eğer uygun bir fonksiyon kullanırsanız, bu verir (1-(#/.~)+/@:%&(*<:)#). Çevredeki parantezler genellikle burada sayılmadığından (ayrılır 1-(#/.~)+/@:%&(*<:)#, fonksiyonun gövdesi) bu 20 bayt verir.
randomra

4

Python 3, 66 58 Bayt

Bu, soruda verilen basit sayma formülünü kullanıyor, çok karmaşık bir şey yok. Anonim bir lambda işlevi, bu yüzden kullanmak için bir ad vermeniz gerekiyor.

Sp3000 sayesinde 8 bayt (!) Kaydedildi.

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

Kullanımı:

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

veya

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

3

APL, 39 36 bayt

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

Bu isimsiz bir monad yaratır.

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

Şunları yapabilirsiniz çevrimiçi denemek !


2

Pyth, 13 bayt

csnM*zz*lztlz

@ Feersum'un çözümünün kelimenin tam anlamıyla çevirisi.


2

CJam, 25 bayt

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

Çevrimiçi deneyin

Söz konusu formülün oldukça doğrudan uygulanması.

Açıklama:

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 bayt

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

ama yine de kısaltılabileceğine inanıyorum.

Misal

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

Bu sadece aşağıdaki fonksiyonun örtük bir versiyonudur:

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

Bazı ekstra golf ve uygun bir işlev yaptıktan sonra: (1-(%&([:+/]*<:)+/)@(+/"1@=))29 bayt verir. 27 (1-(%&([:+/]*<:)+/)@(+/"1@=))burada yaygın olduğu için işlevi çevreleyen parantezleri saymazsak . Notlar: =ytam olarak (~.=/])yve oluşturma işlemi ( x u&v y= (v x) u (v y)) de çok yardımcı oldu.
randomra

Önerileriniz için teşekkürler! Hala kendimi örtük ifadeler yazmayı öğreniyorum. Şimdilik, 13: 0 kullanarak kısmen tanımları kısmen oluşturup birleştiriyorum.
gar

1

Cı-89

Puan fyalnızca işlev içindir ve yalnızca netlik için dahil edilen gereksiz boşlukları hariç tutar. mainfonksiyonu sadece test etmek içindir.

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]));
}

Her karakteri diğer karakterlerle karşılaştırır, sonra toplam karşılaştırma sayısına böler.


1

Python 3, 56

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

Eşit olmayan eleman çiftlerini sayar, ardından bu çiftlerin sayısına böler.


1

Haskell, 83 bayt

Biliyorum geç kaldım, buldum, göndermeyi unutmuştu. Haskell ile tamsayı, tamsayıları birbirinize bölebileceğiniz sayılara dönüştürmemi gerektiriyor.

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 bayt

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

Byte-wise, bu @ RetoKoradi'nin cevabı üzerinde çok küçük bir gelişme , ancak düzgün bir hile kullanıyor:

İlk n negatif olmayan tamsayıların toplamı , sorunun formülündeki kesirin payını ve paydasını 2'ye bölerek hesaplamak için kullanabileceğimiz n (n - 1) / 2'ye eşittir .

CJam yorumlayıcısında çevrimiçi deneyin .

Nasıl çalışır

 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 bayt

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

Açıklama:

  • ≢⍵: ilk boyutunun uzunluğunu al . Bunun bir dize olması gerekiyorsa, bu dize uzunluğu anlamına gelir.
  • {⍴⍵}⌸⍵: içindeki her benzersiz öğe için , olaylar listesinin her boyutunun uzunluklarını alın. Bu, bir öğenin 1×≢⍵matris olarak her öğe için kaç kez gerçekleştiğini verir .
  • ,: yatay eksen boyunca ikisini birleştirin. Yana ≢⍵bir skaler ve diğer değer bir sütundur, bir olsun 2×≢⍵ilk sütun bir öğe her öğe için oluşur kez miktarda vardır matrisi ve ikinci sütun öğelerin toplam miktarda vardır.
  • {⍵×⍵-1}: matristeki her hücre için hesaplayın N(N-1).
  • ÷/: bölünme ile satırları azaltma. Bu, her öğenin değerini toplam değerine böler.
  • +/: her satır için sonucu topla.
  • 1-: 1'den çıkarın
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.