ดัชนีความหลากหลายของซิมป์สัน


19

ดัชนีซิมป์สันเป็นตัวชี้วัดของความหลากหลายของคอลเลกชันของรายการที่มีซ้ำกันได้ มันเป็นความน่าจะเป็นที่จะวาดสองรายการที่แตกต่างกันเมื่อหยิบโดยไม่ต้องเปลี่ยนอย่างสม่ำเสมอ

ด้วยnรายการในกลุ่มของn_1, ..., n_kรายการที่เหมือนกันความน่าจะเป็นของสองรายการที่แตกต่างคือ

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

ตัวอย่างเช่นหากคุณมีแอปเปิ้ล 3 ตัว, กล้วย 2 ลูกและแครอท 1 ตัวดัชนีความหลากหลายคือ

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

อีกวิธีหนึ่งคือจำนวนคู่เรียงลำดับของรายการที่แตกต่างกัน3*2 + 3*1 + 2*1 = 11ออกไปจาก 15 11/15 = 0.7333คู่โดยรวมและ

การป้อนข้อมูล:

สตริงของตัวละครที่จะA Zหรือรายการของตัวละครดังกล่าว ความยาวของมันจะน้อยกว่า 2 คุณอาจไม่คิดว่ามันจะถูกจัดเรียง

เอาท์พุท:

ดัชนีความหลากหลายของซิมป์สันของตัวละครในสายนั้นคือความน่าจะเป็นที่ตัวละครสองตัวที่ถูกสุ่มจับมาแทนที่มีความแตกต่างกัน นี่คือตัวเลขระหว่าง 0 ถึง 1

เมื่อแสดงผลแบบลอยแสดงตัวเลขอย่างน้อย 4 หลักแม้ว่าจะยกเลิกผลลัพธ์ที่แน่นอนเช่น1หรือ1.0หรือ0.375ตกลง

คุณไม่สามารถใช้บิวด์อินที่คำนวณดัชนีความหลากหลายหรือมาตรการเอนโทรปีได้โดยเฉพาะ การสุ่มแบบสุ่มที่แท้จริงนั้นใช้ได้ตราบใดที่คุณได้รับความถูกต้องเพียงพอในกรณีทดสอบ

กรณีทดสอบ

AAABBC 0.73333
ACBABA 0.73333
WWW 0.0
CODE 1.0
PROGRAMMING 0.94545

ลีดเดอร์บอร์ด

นี่เป็นลีดเดอร์โดยภาษามารยาทของมาร์ตินBüttner

เพื่อให้แน่ใจว่าคำตอบของคุณปรากฏขึ้นโปรดเริ่มคำตอบด้วยหัวข้อโดยใช้เทมเพลต Markdown ต่อไปนี้:

# Language Name, N bytes

ที่Nมีขนาดของส่งของคุณ หากคุณปรับปรุงคะแนนของคุณคุณสามารถเก็บคะแนนเก่าไว้ในพาดหัว ตัวอย่างเช่น

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


คุณกำลังใช้ดัชนี Gini-Simpson เมื่อมีการวัดที่ดีกว่าการใช้มากขึ้นก็คือดัชนี Simpson แบบกลับกันหรือที่รู้จักกันว่าจำนวนที่มีประสิทธิภาพ
Joe Z.

1
โดยทั่วไปแทน1/ 1-[หมวกนักสถิติมือสมัครเล่นปิด]
Joe Z.

คำตอบ:


5

Python 2, 72

อินพุตอาจเป็นสตริงหรือรายการ

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

ฉันรู้แล้วว่ามันจะสั้นกว่า 2 ไบต์ใน Python 3 ดังนั้นโปรดอย่าแนะนำฉัน :)


วงเล็บมุม<>ทำอะไรที่ตำแหน่ง 36 ฉันไม่เคยเห็นไวยากรณ์นั้นมาก่อน
ApproachDarknessFish

@TuttiFruttiJacuzzi: !=มันเป็นคำพ้องความหมายสำหรับ
RemcoGerlich

1
@TuttiFruttiJacuzzi เป็นเพียง 2 ไพ ธ อนเว้นแต่คุณfrom __future__ import barry_as_FLUFL
matsjoyce

@ Vioz- ไม่l=len(s);อยู่ในนั้น
Sp3000

@ Sp3000 ใช่ไม่ได้สังเกตว่ามีการใช้งานกี่ครั้ง
Kade

4

Pyth - 19 13 12 11 ไบต์

ขอบคุณ @isaacg ที่บอกฉันเกี่ยวกับ n

ใช้วิธีเดรัจฉานแรงพร้อม.cฟังก์ชันการรวมกัน

csnMK.cz2lK

ลองมันนี่เกมออนไลน์

ชุดทดสอบ

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

คุณสามารถแทนที่.{ด้วยn- มันเทียบเท่าได้ที่นี่
isaacg

@isaacg โอ้ไม่ทราบว่ามันจะ splats โดยอัตโนมัติเย็น
Maltysen

4

SQL (PostgreSQL), 182 ไบต์

ในฐานะที่เป็นฟังก์ชั่นใน 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

คำอธิบาย

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

การใช้งานและทดสอบการทำงาน

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 ไบต์

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

ส่วนที่เย็น

ฉันพบการนับของตัวละครแต่ละตัวโดย</.การป้อนสตริงกับตัวเอง ( ~สำหรับการสะท้อนกลับ) จากนั้นนับตัวอักษรของแต่ละกล่อง


1
(#&:>@</.~)สามารถ(#/.~)และสามารถ(<:*]) ถ้าคุณใช้ฟังก์ชั่นที่เหมาะสมนี้จะช่วยให้(*<:) (1-(#/.~)+/@:%&(*<:)#)เนื่องจากโดยทั่วไปการจัดฟันโดยรอบจะไม่ถูกนับที่นี่ (ออกจาก1-(#/.~)+/@:%&(*<:)#ร่างกายของฟังก์ชัน) ซึ่งจะให้ 20 ไบต์
randomra

4

Python 3, 66 58 Bytes

นี่คือการใช้สูตรนับอย่างง่ายที่ให้ไว้ในคำถามไม่มีอะไรซับซ้อนเกินไป มันเป็นฟังก์ชั่นแลมบ์ดานิรนามดังนั้นหากต้องการใช้งานคุณต้องตั้งชื่อให้

บันทึก 8 ไบต์ (!) ต้องขอบคุณ Sp3000

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

การใช้งาน:

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

หรือ

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

3

APL, 39 36 ไบต์

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

สิ่งนี้จะสร้าง monad ที่ไม่มีชื่อ

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

คุณสามารถลองออนไลน์ได้ !



2

CJam, 25 ไบต์

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

ลองออนไลน์

การใช้สูตรในคำถามโดยตรง

คำอธิบาย:

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 ไบต์

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

แต่ฉันเชื่อว่ามันยังสั้นลงได้

ตัวอย่าง

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

นี่เป็นเพียงฟังก์ชั่นต่อไปนี้โดยปริยาย:

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

หลังจากเล่นกอล์ฟเป็นพิเศษและทำให้ฟังก์ชั่นเหมาะสม: (1-(%&([:+/]*<:)+/)@(+/"1@=))ให้ 29 ไบต์ 27 ถ้าเราไม่นับวงเล็บปีกกาที่ล้อมรอบฟังก์ชั่น(1-(%&([:+/]*<:)+/)@(+/"1@=))เพราะมันเป็นเรื่องธรรมดาที่นี่ หมายเหตุ: =yถูกต้อง(~.=/])yและการผสมผสานการเขียน ( x u&v y= (v x) u (v y)) ก็มีประโยชน์มากเช่นกัน
randomra

ขอบคุณสำหรับคำแนะนำ! ฉันยังคงเรียนรู้ที่จะเขียนการแสดงออกโดยปริยายด้วยตัวเอง สำหรับตอนนี้ฉันใช้ 13: 0 เพื่อสร้างคำจำกัดความโดยปริยายโดยส่วนและรวม
gar

1

C 89

คะแนนสำหรับฟังก์ชั่นfเท่านั้นและไม่รวมช่องว่างที่ไม่จำเป็นซึ่งรวมไว้เพื่อความชัดเจนเท่านั้น mainฟังก์ชั่นเป็นเพียงสำหรับการทดสอบ

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

มันเปรียบเทียบตัวละครทุกตัวกับตัวละครอื่น ๆ แล้วหารด้วยจำนวนการเปรียบเทียบทั้งหมด


1

Python 3, 56

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

นับจำนวนคู่ขององค์ประกอบที่ไม่เท่ากันจากนั้นหารด้วยจำนวนของคู่ดังกล่าว


1

Haskell, 83 ไบต์

ฉันรู้ว่าฉันมาช้าพบสิ่งนี้ลืมโพสต์ Kinda ไม่เหมาะสมกับ Haskell ต้องการให้ฉันแปลงจำนวนเต็มเป็นตัวเลขที่คุณสามารถหารด้วยกันได้

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 ไบต์

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

Byte-wise นี่เป็นการปรับปรุงเล็กน้อยสำหรับคำตอบของ @ RetoKoradiแต่มันใช้กลอุบายที่ประณีต:

ผลรวมของจำนวนเต็ม n ที่ไม่เป็นลบแรกเท่ากับn (n - 1) / 2ซึ่งเราสามารถใช้ในการคำนวณเศษและส่วนซึ่งหารด้วย2ของเศษส่วนในสูตรของคำถาม

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

 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 ไบต์

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

คำอธิบาย:

  • ≢⍵: ได้รับความยาวของมิติครั้งแรกของ ระบุว่าควรจะเป็นสตริงนี้หมายถึงความยาวของสตริง
  • {⍴⍵}⌸⍵: สำหรับแต่ละองค์ประกอบที่ไม่ซ้ำกันในรับความยาวของแต่ละมิติของรายการที่เกิดขึ้น สิ่งนี้จะให้จำนวนครั้งที่รายการเกิดขึ้นสำหรับแต่ละรายการเป็น1×≢⍵เมทริกซ์
  • ,: เชื่อมทั้งสองเข้าด้วยกันตามแกนนอน เนื่องจาก≢⍵เป็นสเกลาร์และค่าอื่น ๆ คือคอลัมน์เราจะได้2×≢⍵เมทริกซ์โดยที่คอลัมน์แรกมีจำนวนครั้งที่รายการเกิดขึ้นสำหรับแต่ละรายการและคอลัมน์ที่สองมีจำนวนรายการทั้งหมด
  • {⍵×⍵-1}: สำหรับแต่ละเซลล์ในเมทริกซ์, N(N-1)การคำนวณ
  • ÷/: ลดแถวทีละส่วน สิ่งนี้หารค่าสำหรับแต่ละรายการด้วยค่าของผลรวม
  • +/: รวมผลลัพธ์สำหรับแต่ละแถว
  • 1-: ลบออกจาก 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.