วิธีการนับความถี่ขององค์ประกอบในรายการเรียงลำดับ?


237

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

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

output->

b = [4,4,2,1,2]

นอกจากนี้ฉันต้องการลบรายการที่ซ้ำออกจาก

a = [1,2,3,4,5]

พวกเขามักจะสั่งเหมือนในตัวอย่างที่?
Farinha

@ Peter ใช่คุณได้จัดเรียงรายการเพื่อวัตถุประสงค์ในการโพสต์ รายการจะถูกจัดเรียงเสมอหรือไม่
S.Lott

2
ไม่รายการจะไม่ถูกจัดเรียงเสมอ นี่ไม่ใช่การบ้าน
Bruce

ฉันกำลังพยายามพล็อตกราฟของการกระจายระดับของเครือข่าย
Bruce

5
@Peter: โปรดอัปเดตคำถามของคุณด้วยข้อมูลที่เป็นประโยชน์ โปรดอย่าเพิ่มความคิดเห็นให้กับคำถามของคุณ - คุณเป็นเจ้าของคำถามคุณสามารถแก้ไขให้สมบูรณ์และชัดเจนได้
S.Lott

คำตอบ:


147

หมายเหตุ: groupbyคุณควรเรียงลำดับรายชื่อก่อนที่จะใช้

คุณสามารถใช้groupbyจากitertoolsแพ็คเกจหากรายการนั้นเป็นรายการสั่งซื้อ

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
from itertools import groupby
[len(list(group)) for key, group in groupby(a)]

เอาท์พุท:

[4, 4, 2, 1, 2]

groupbyดีใช้ ฉันสงสัยเกี่ยวกับประสิทธิภาพของมันเทียบกับวิธี dict แต่
Eli Bendersky

32
หลาม groupby สร้างกลุ่มใหม่เมื่อค่าที่เห็นการเปลี่ยนแปลง ในกรณีนี้ 1,1,1,2,1,1,1] จะกลับมา [3,1,3] หากคุณคาดหวัง [6,1] ให้แน่ใจว่าได้เรียงลำดับข้อมูลก่อนที่จะใช้ groupby
Evan

4
sum(1 for _ in group)@CristianCiupitu:
Martijn Pieters

6
นี่ไม่ใช่วิธีแก้ปัญหา เอาท์พุทไม่ได้บอกสิ่งที่นับ
buhtz

8
[(key, len(list(group))) for key, group in groupby(a)]หรือ{key: len(list(group)) for key, group in groupby(a)}@buhtz
Eric Pauley

532

ใน Python 2.7 (หรือใหม่กว่า) คุณสามารถใช้collections.Counter:

import collections
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
counter=collections.Counter(a)
print(counter)
# Counter({1: 4, 2: 4, 3: 2, 5: 2, 4: 1})
print(counter.values())
# [4, 4, 2, 1, 2]
print(counter.keys())
# [1, 2, 3, 4, 5]
print(counter.most_common(3))
# [(1, 4), (2, 4), (3, 2)]

หากคุณกำลังใช้งูหลาม 2.6 หรือเก่าคุณสามารถดาวน์โหลดได้ที่นี่


1
@unutbu: ถ้าฉันมีสามรายการคือ a, b, c ซึ่ง a และ b ยังคงเหมือนเดิม แต่ c เปลี่ยน? จะนับค่าของ c ที่ a และ c เหมือนกันได้อย่างไร?
ThePredator

@Srivatsan: ฉันไม่เข้าใจสถานการณ์ กรุณาโพสต์คำถามใหม่ที่คุณสามารถทำอย่างละเอียด
unutbu

1
มีวิธีการแยกพจนานุกรม {1: 4, 2: 4, 3: 2, 5: 2, 4: 1} ออกจากวัตถุตัวนับหรือไม่?
Pavan

7
@Pavan: collections.Counterเป็น subclass dictของ คุณสามารถใช้งานได้ในลักษณะเดียวกับที่คุณใช้ในการเขียนตามปกติ หากคุณต้องการ Dict จริงๆ แต่คุณสามารถแปลงเป็น Dict dict(counter)โดยใช้
unutbu

1
ใช้งานได้ใน 3.6 เช่นกันดังนั้นสมมติว่ามีอะไรมากกว่า 2.7
kpierce8

108

Python 2.7+ แนะนำพจนานุกรมความเข้าใจ การสร้างพจนานุกรมจากรายการจะช่วยให้คุณได้รับการนับรวมถึงกำจัดการซ้ำซ้อน

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> d = {x:a.count(x) for x in a}
>>> d
{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}
>>> a, b = d.keys(), d.values()
>>> a
[1, 2, 3, 4, 5]
>>> b
[4, 4, 2, 1, 2]

วิธีนี้ใช้ได้ดีกับรายการสตริงเมื่อเทียบกับจำนวนเต็มเหมือนคำถามเดิมที่ถาม
เกลน Selle

15
มันเร็วกว่าเมื่อใช้ชุด:{x:a.count(x) for x in set(a)}
stenci

45
นี้จะไม่มีประสิทธิภาพอย่างมหาศาล a.count()ทำการสำรวจแบบเต็มสำหรับแต่ละองค์ประกอบในaทำให้เป็นวิธีการ quadradic O (N ^ 2) collections.Counter()มีประสิทธิภาพมากขึ้นเนื่องจากนับเป็นเวลาเชิงเส้น (O (N)) ในตัวเลขนั่นหมายถึงวิธีการนี้จะดำเนินการ 1 ล้านขั้นตอนสำหรับรายการความยาว 1,000 เทียบกับเพียง 1,000 ขั้นตอนกับCounter()10 ^ 12 ขั้นตอนที่เคาน์เตอร์ต้องการเพียง 10 ^ 6 สำหรับรายการนับล้านรายการในรายการเป็นต้น
Martijn Pieters

3
@stenci: แน่นอน แต่ความน่ากลัวของการใช้a.count()ดาวแคระอย่างสมบูรณ์มีประสิทธิภาพในการใช้ชุดที่นั่น
Martijn Pieters

2
@MartijnPieters อีกเหตุผลหนึ่งที่จะใช้เวลาน้อยลง :)
stenci

48

วิธีนับจำนวนภาพ:

from collections import defaultdict

appearances = defaultdict(int)

for curr in a:
    appearances[curr] += 1

หากต้องการลบรายการซ้ำ:

a = set(a) 

1
+1 สำหรับคอลเล็กชัน นอกจากนี้ใน python 3.x ค้นหาคอลเล็กชันตัวนับ มันเหมือนกับ collection.defaultdict (int)
hughdbrown

2
@hughdbrown จริงCounterสามารถใช้ชนิดของตัวเลขหลายแห่งรวมถึงfloatหรือไม่เพียงDecimal int
Cristian Ciupitu

28

ใน Python 2.7+ คุณสามารถใช้คอลเล็กชันตัวนับเพื่อนับรายการ

>>> a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>>
>>> from collections import Counter
>>> c=Counter(a)
>>>
>>> c.values()
[4, 4, 2, 1, 2]
>>>
>>> c.keys()
[1, 2, 3, 4, 5]

1
ตัวนับนั้นช้ากว่า dict เริ่มต้นและ dict เริ่มต้นนั้นช้ากว่าการใช้ dict แบบแมนนวลมาก
Jonathan Ray

@JonathanRay ไม่ได้อีกต่อไปstackoverflow.com/a/27802189/1382487
wsaleem

25

การนับความถี่ขององค์ประกอบน่าจะทำได้ดีที่สุดกับพจนานุกรม:

b = {}
for item in a:
    b[item] = b.get(item, 0) + 1

หากต้องการลบรายการซ้ำให้ใช้ชุด:

a = list(set(a))

3
@phkahler: ของฉันจะดีขึ้นเล็กน้อยกว่านี้ มันแทบจะไม่คุ้มค่าที่ฉันจะโพสต์คำตอบแยกต่างหากเมื่อสิ่งนี้สามารถปรับปรุงได้ด้วยการเปลี่ยนแปลงเล็กน้อย ประเด็นของ SO คือการได้รับคำตอบที่ดีที่สุด ฉันสามารถแก้ไขสิ่งนี้ได้ แต่ฉันต้องการอนุญาตให้ผู้เขียนต้นฉบับมีโอกาสปรับปรุงตนเอง
S.Lott

1
@ S.Lott defaultdictรหัสทำความสะอาดมากได้โดยไม่ต้องนำเข้า
bstrauch24

ทำไมไม่ preinitialize b: b = {k:0 for k in a}?
DylanYoung

20

นี่เป็นอีกทางเลือกหนึ่งที่ใช้ประโยชน์itertools.groupbyได้ดีสำหรับการป้อนข้อมูลแบบไม่มีลำดับ

from itertools import groupby

items = [5, 1, 1, 2, 2, 1, 1, 2, 2, 3, 4, 3, 5]

results = {value: len(list(freq)) for value, freq in groupby(sorted(items))}

ผล

{1: 4, 2: 4, 3: 2, 4: 1, 5: 2}

16

คุณสามารถทำได้:

import numpy as np
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
np.unique(a, return_counts=True)

เอาท์พุท:

(array([1, 2, 3, 4, 5]), array([4, 4, 2, 1, 2], dtype=int64))

อาร์เรย์แรกคือค่าและอาร์เรย์ที่สองคือจำนวนองค์ประกอบที่มีค่าเหล่านี้

ดังนั้นถ้าคุณต้องการเรียงลำดับตัวเลขที่คุณควรใช้:

np.unique(a, return_counts=True)[1]

8
from collections import Counter
a=["E","D","C","G","B","A","B","F","D","D","C","A","G","A","C","B","F","C","B"]

counter=Counter(a)

kk=[list(counter.keys()),list(counter.values())]

pd.DataFrame(np.array(kk).T, columns=['Letter','Count'])

ในขณะที่ข้อมูลโค้ดนี้อาจเป็นโซลูชันรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพของโพสต์ของคุณ โปรดจำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและผู้คนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ
Rahul Gupta

ใช่จะทำเช่นนั้น Rahul Gupta
Anirban Lahiri

7
seta = set(a)
b = [a.count(el) for el in seta]
a = list(seta) #Only if you really want it.

4
การใช้รายการcountมีราคาแพงและไม่น่าเชื่อถือสำหรับสถานการณ์นี้
Idan K

@IdanK ทำไมการนับมีราคาแพง
Kritika Rajain

@KritikaRajain สำหรับแต่ละองค์ประกอบที่ไม่ซ้ำกันในรายการคุณวนซ้ำทั้งรายการเพื่อสร้างจำนวน (กำลังสองในจำนวนองค์ประกอบที่ไม่ซ้ำกันในรายการ) แต่คุณสามารถวนซ้ำในรายการหนึ่งครั้งและนับจำนวนขององค์ประกอบที่ไม่ซ้ำกันแต่ละรายการ (เป็นเส้นตรงในขนาดของรายการ) หากรายการของคุณมีองค์ประกอบที่ไม่ซ้ำกันเพียงหนึ่งรายการผลลัพธ์จะเหมือนกัน ยิ่งกว่านั้นวิธีนี้ต้องใช้ชุดระดับกลางเพิ่มเติม
DylanYoung


4

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

สำหรับคำถามที่สองของคุณเพียงใช้ตัวดำเนินการชุด


4
คุณช่วยอธิบายรายละเอียดของคำตอบแรกได้ไหม
Bruce

3

คำตอบนี้ชัดเจนยิ่งขึ้น

a = [1,1,1,1,2,2,2,2,3,3,3,4,4]

d = {}
for item in a:
    if item in d:
        d[item] = d.get(item)+1
    else:
        d[item] = 1

for k,v in d.items():
    print(str(k)+':'+str(v))

# output
#1:4
#2:4
#3:3
#4:2

#remove dups
d = set(a)
print(d)
#{1, 2, 3, 4}

3
def frequencyDistribution(data):
    return {i: data.count(i) for i in data}   

print frequencyDistribution([1,2,3,4])

...

 {1: 1, 2: 1, 3: 1, 4: 1}   # originalNumber: count

3

ฉันค่อนข้างช้า แต่ก็ใช้งานได้และจะช่วยเหลือผู้อื่น:

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
freq_list = []
a_l = list(set(a))

for x in a_l:
    freq_list.append(a.count(x))


print 'Freq',freq_list
print 'number',a_l

จะผลิตสิ่งนี้ ..

Freq  [4, 4, 2, 1, 2]
number[1, 2, 3, 4, 5]

2
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

# 1. Get counts and store in another list
output = []
for i in set(a):
    output.append(a.count(i))
print(output)

# 2. Remove duplicates using set constructor
a = list(set(a))
print(a)
  1. ชุดคอลเลกชันไม่อนุญาตให้มีการซ้ำซ้อนการส่งรายการไปยังตัวสร้าง set () จะให้วัตถุที่ซ้ำกันโดยสิ้นเชิง count () ฟังก์ชั่นส่งกลับจำนวนเต็มเมื่อวัตถุที่อยู่ในรายการถูกส่งผ่าน เมื่อมีการนับวัตถุที่ไม่ซ้ำกันและแต่ละค่าการนับจะถูกเก็บไว้โดยผนวกเข้ากับรายการที่ว่างเปล่า
  2. list () คอนสตรัคเตอร์ใช้ในการแปลงชุด (a) เป็นลิสต์และอ้างอิงโดยตัวแปรเดียวกัน a

เอาท์พุต

D:\MLrec\venv\Scripts\python.exe D:/MLrec/listgroup.py
[4, 4, 2, 1, 2]
[1, 2, 3, 4, 5]

2

วิธีง่ายๆในการใช้พจนานุกรม

def frequency(l):
     d = {}
     for i in l:
        if i in d.keys():
           d[i] += 1
        else:
           d[i] = 1

     for k, v in d.iteritems():
        if v ==max (d.values()):
           return k,d.keys()

print(frequency([10,10,10,10,20,20,20,20,40,40,50,50,30]))

max(d.values())จะไม่เปลี่ยนแปลงในลูปสุดท้าย อย่าคำนวณในลูปคำนวณก่อนลูป
DylanYoung

1
#!usr/bin/python
def frq(words):
    freq = {}
    for w in words:
            if w in freq:
                    freq[w] = freq.get(w)+1
            else:
                    freq[w] =1
    return freq

fp = open("poem","r")
list = fp.read()
fp.close()
input = list.split()
print input
d = frq(input)
print "frequency of input\n: "
print d
fp1 = open("output.txt","w+")
for k,v in d.items():
fp1.write(str(k)+':'+str(v)+"\n")
fp1.close()

1
num=[3,2,3,5,5,3,7,6,4,6,7,2]
print ('\nelements are:\t',num)
count_dict={}
for elements in num:
    count_dict[elements]=num.count(elements)
print ('\nfrequency:\t',count_dict)

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

1
from collections import OrderedDict
a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
def get_count(lists):
    dictionary = OrderedDict()
    for val in lists:
        dictionary.setdefault(val,[]).append(1)
    return [sum(val) for val in dictionary.values()]
print(get_count(a))
>>>[4, 4, 2, 1, 2]

หากต้องการลบรายการที่ซ้ำกันและรักษาลำดับ:

list(dict.fromkeys(get_count(a)))
>>>[4, 2, 1]

1

ฉันใช้เคาน์เตอร์เพื่อสร้างความถี่ dict จากคำไฟล์ข้อความในรหัส 1 บรรทัด

def _fileIndex(fh):
''' create a dict using Counter of a
flat list of words (re.findall(re.compile(r"[a-zA-Z]+"), lines)) in (lines in file->for lines in fh)
'''
return Counter(
    [wrd.lower() for wrdList in
     [words for words in
      [re.findall(re.compile(r'[a-zA-Z]+'), lines) for lines in fh]]
     for wrd in wrdList])

1

อีกวิธีหนึ่งในการทำเช่นนี้ถึงแม้ว่าจะใช้ไลบรารีที่หนัก แต่ทรงพลัง - NLTK

import nltk

fdist = nltk.FreqDist(a)
fdist.values()
fdist.most_common()

0

อีกโซลูชันหนึ่งที่มีอัลกอริธึมอื่นโดยไม่ใช้คอลเล็กชัน:

def countFreq(A):
   n=len(A)
   count=[0]*n                     # Create a new list initialized with '0'
   for i in range(n):
      count[A[i]]+= 1              # increase occurrence for value A[i]
   return [x for x in count if x]  # return non-zero count

0

คุณสามารถใช้ฟังก์ชั่นที่สร้างขึ้นใน python

l.count(l[i])


  d=[]
  for i in range(len(l)):
        if l[i] not in d:
             d.append(l[i])
             print(l.count(l[i])

โค้ดด้านบนจะลบรายการที่ซ้ำกันออกจากรายการโดยอัตโนมัติและพิมพ์ความถี่ของแต่ละองค์ประกอบในรายการดั้งเดิมและรายการที่ไม่มีรายการซ้ำ

นกสองตัวสำหรับนัดเดียว! XD


0

สามารถลองวิธีนี้ได้หากคุณไม่ต้องการใช้ห้องสมุดใด ๆ และทำให้ง่ายและสั้น!

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
marked = []
b = [(a.count(i), marked.append(i))[0] for i in a if i not in marked]
print(b)

o / p

[4, 4, 2, 1, 2]

0

สำหรับการบันทึกคำตอบการทำงาน:

>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]

มันสะอาดกว่าถ้าคุณนับเลขศูนย์ด้วย:

>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]

คำอธิบาย:

  • เราเริ่มต้นด้วยaccรายการที่ว่างเปล่า
  • หากองค์ประกอบถัดไปeของLต่ำกว่าขนาดของaccเราเพียงแค่อัปเดตองค์ประกอบนี้: v+(i==e)หมายถึงv+1ถ้าดัชนีiของaccเป็นองค์ประกอบปัจจุบันeมิฉะนั้นค่าก่อนหน้าv;
  • ถ้าองค์ประกอบถัดไปeของLมากกว่าหรือเท่ากับขนาดของaccเราจะต้องขยายให้เป็นเจ้าภาพจัดการใหม่acc1

องค์ประกอบไม่จำเป็นต้องเรียง ( itertools.groupby) คุณจะได้ผลลัพธ์แปลก ๆ ถ้าคุณมีตัวเลขติดลบ


0

พบวิธีอื่นในการทำเช่นนี้โดยใช้ชุด

#ar is the list of elements
#convert ar to set to get unique elements
sock_set = set(ar)

#create dictionary of frequency of socks
sock_dict = {}

for sock in sock_set:
    sock_dict[sock] = ar.count(sock)

0

เพื่อหาองค์ประกอบที่ไม่ซ้ำกันในรายการ

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]
a = list(set(a))

เพื่อค้นหาการนับองค์ประกอบที่ไม่ซ้ำกันในอาร์เรย์ที่เรียงลำดับโดยใช้พจนานุกรม

def CountFrequency(my_list): 
# Creating an empty dictionary  
freq = {} 
for item in my_list: 
    if (item in freq): 
        freq[item] += 1
    else: 
        freq[item] = 1

for key, value in freq.items(): 
    print ("% d : % d"%(key, value))

# Driver function 
if __name__ == "__main__":  
my_list =[1, 1, 1, 5, 5, 3, 1, 3, 3, 1, 4, 4, 4, 2, 2, 2, 2] 

CountFrequency(my_list)

อ้างอิง GeeksforGeeks


-1

อีกวิธีหนึ่งคือการใช้พจนานุกรมและ list.count ใต้วิธีไร้เดียงสาที่จะทำ

dicio = dict()

a = [1,1,1,1,2,2,2,2,3,3,4,5,5]

b = list()

c = list()

for i in a:

   if i in dicio: continue 

   else:

      dicio[i] = a.count(i)

      b.append(a.count(i))

      c.append(i)

print (b)

print (c)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.