2015-02-09 10 views
15

Mam listę ciągów:Jak zrobić histogram z listy ciągów w Pythonie?

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e'] 

chcę zrobić histogramu do wyświetlania rozkład częstotliwości występowania liter. Mogę utworzyć listę zawierającą liczbę liter za pomocą następujących kodów:

from itertools import groupby 
b = [len(list(group)) for key, group in groupby(a)] 

Jak utworzyć histogram? Mogę mieć milion takich elementów na liście a.

+6

'ze zbiorów importować Counter; histogram = Licznik (tekst) ' –

+0

Czym więc jest dla ciebie histogram? –

+0

przede wszystkim powinieneś użyć 'Counter' ...groupby zawiedzie w przypadku '['a', 'a', 'b', 'b', 'a']' (między innymi) –

Odpowiedz

24

Bardzo łatwe z Pandas.

import pandas 
from collections import Counter 
a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e'] 
letter_counts = Counter(a) 
df = pandas.DataFrame.from_dict(letter_counts, orient='index') 
df.plot(kind='bar') 

Uwaga, Counter czyni licznik częstotliwości, więc nasz Działka jest 'bar' nie 'hist'.

histogram of letter counts

+0

Cool, notconfusing! Ale jak zrobić ciągły histogram? Czy zmienię po prostu rodzaj = bar na kind = hist? – Gray

+0

Mam ponad 1 milion takich elementów na liście, więc myślę, że wykres słupkowy będzie miał trudności z wyświetlaniem częstotliwości. – Gray

+0

@Gray, jeśli chcesz wygładzić proponuję 'kind = 'area'' – notconfusing

1

Zapoznaj się z matplotlib.pyplot.bar. Istnieje również numpy.histogram, który jest bardziej elastyczny, jeśli chcesz szersze pojemniki.

5

Zamiast używać groupby() (wymagającego sortowania danych wejściowych), należy użyć collections.Counter(); nie trzeba tworzyć list pośrednich tylko do zliczania wejść:

from collections import Counter 

counts = Counter(a) 

Nie określiłeś naprawdę tego, co uważasz za "histogram". Załóżmy że chcesz to zrobić w terminalu:

width = 120 # Adjust to desired width 
longest_key = max(len(key) for key in counts) 
graph_width = width - longest_key - 2 
widest = counts.most_common(1)[0][1] 
scale = graph_width/float(widest) 

for key, size in sorted(counts.items()): 
    print('{}: {}'.format(key, int(size * scale) * '*')) 

Demo:

>>> from collections import Counter 
>>> a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e'] 
>>> counts = Counter(a) 
>>> width = 120 # Adjust to desired width 
>>> longest_key = max(len(key) for key in counts) 
>>> graph_width = width - longest_key - 2 
>>> widest = counts.most_common(1)[0][1] 
>>> scale = graph_width/float(widest) 
>>> for key, size in sorted(counts.items()): 
...  print('{}: {}'.format(key, int(size * scale) * '*')) 
... 
a: ********************************************************************************************* 
b: ********************************************** 
c: ********************************************************************** 
d: *********************** 
e: ********************************************************************************************************************* 

Bardziej zaawansowane narzędzia znajdują się w funkcjach numpy.histogram() i matplotlib.pyplot.hist(). Te sprawdzenia dla Ciebie, z matplotlib.pyplot.hist() również zapewnia wyjście wykresu.

+0

Dziękuję Martijin! To sprytny sposób, ale jak zrobić wykresy do druku? – Gray

+0

A jak użyć numpy.histogram(), aby rozwiązać ten problem? Przepraszam, nie jestem programistą. – Gray

+0

@Gray: Szczerze mówiąc, nie wiem ani nie mam czasu, aby dowiedzieć się. Są tutoriale dla bibliotek, proponuję pójść za nimi! :-) –

7

Jak wskazano powyżej @notconfusing ten może być rozwiązany z Pand i licznika. Jeśli dla jakikolwiek powód, trzeba, aby nie używać Pandy można dostać się z tylko matplotlib używając funkcji w poniższym kodzie:

from collections import Counter 
import numpy as np 
import matplotlib.pyplot as plt 

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e'] 
letter_counts = Counter(a) 

def plot_bar_from_counter(counter, ax=None): 
    """" 
    This function creates a bar plot from a counter. 

    :param counter: This is a counter object, a dictionary with the item as the key 
    and the frequency as the value 
    :param ax: an axis of matplotlib 
    :return: the axis wit the object in it 
    """ 

    if ax is None: 
     fig = plt.figure() 
     ax = fig.add_subplot(111) 

    frequencies = counter.values() 
    names = counter.keys() 

    x_coordinates = np.arange(len(counter)) 
    ax.bar(x_coordinates, frequencies, align='center') 

    ax.xaxis.set_major_locator(plt.FixedLocator(x_coordinates)) 
    ax.xaxis.set_major_formatter(plt.FixedFormatter(names)) 

    return ax 

plot_bar_from_counter(letter_counts) 
plt.show() 

która będzie produkować enter image description here

0

prosty i skuteczny sposób, aby znak histrogram w Pythonie

import numpy as np 
 

 
import matplotlib.pyplot as plt 
 

 
from collections import Counter 
 

 

 

 
a = [] 
 
count =0 
 
d = dict() 
 
filename = raw_input("Enter file name: ") 
 
with open(filename,'r') as f: 
 
    for word in f: 
 
     for letter in word: 
 
      if letter not in d: 
 
       d[letter] = 1 
 
      else: 
 
       d[letter] +=1 
 
num = Counter(d) 
 
x = list(num.values()) 
 
y = list(num.keys()) 
 

 
x_coordinates = np.arange(len(num.keys())) 
 
plt.bar(x_coordinates,x) 
 
plt.xticks(x_coordinates,y) 
 
plt.show() 
 
print x,y

1

oto zwięzły podejście all-pandy:

a = ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'e', 'e', 'e', 'e', 'e'] 
pd.Series(a).value_counts().plot('bar') 

barplot of counts

Powiązane problemy