2015-02-09 7 views
15

Ich habe eine Liste von Strings:Wie erstellt man ein Histogramm aus einer Liste von Strings in Python?

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

Ich möchte ein Histogramm machen für die Häufigkeitsverteilung der Buchstaben anzeigt. Ich kann eine Liste erstellen, die die Anzahl der einzelnen Buchstaben mit folgenden Codes enthält:

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

Wie mache ich das Histogramm? Ich kann eine Million solcher Elemente in der Liste a haben.

+6

'aus Sammlungen importieren Zähler; histogram = Zähler (Text) ' –

+0

Was ist Histogramm für Sie? –

+0

Zuerst sollten Sie 'Counter' verwenden ...groupby wird Sie für '['a', 'a', 'b', 'b', 'a']' (unter anderem) –

Antwort

24

Sehr einfach mit 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') 

Beachten Sie, dass Counter wird eine Frequenzzählung zu machen, so dass unser Plottyp 'bar' nicht 'hist' ist.

histogram of letter counts

+0

Cool, nicht confusing! Aber wie macht man ein kontinuierliches Histogramm? Ändere ich einfach art = bar zu art = hist? – Gray

+0

Ich habe mehr als 1 Million solcher Elemente in der Liste, also denke ich, dass Balkenplot einige Schwierigkeiten haben wird, Frequenzen anzuzeigen. – Gray

+0

@Gray, wenn Sie es glätten möchten, empfehle ich 'kind = 'Bereich'' – notconfusing

1

Auschecken matplotlib.pyplot.bar. Es gibt auch numpy.histogram, die flexibler ist, wenn Sie breitere Behälter wünschen.

5

Anstatt groupby() zu verwenden (was erfordert, dass Ihre Eingabe sortiert wird), verwenden Sie collections.Counter(); dies muss nicht Vermittler Listen erstellen, Eingänge zählen:

from collections import Counter 

counts = Counter(a) 

Sie haben nicht wirklich festgelegt, was Sie als ein ‚Histogramm‘ sein. Nehmen wir an, Sie dies auf dem Terminal tun wollte:

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: ********************************************************************************************************************* 

Komplexere Werkzeuge finden sich in den numpy.histogram() und matplotlib.pyplot.hist() Funktionen. Diese machen das Tallying für Sie, mit matplotlib.pyplot.hist() Ihnen auch mit Diagrammausgabe.

+0

Danke Martijin! Das ist ein kluger Weg, aber wie mache ich druckbare Graphen? – Gray

+0

Und wie numpy.histogram() verwenden, um dieses Problem zu lösen? Entschuldigung, ich bin kein Programmierer. – Gray

+0

@Gray: um ehrlich zu sein, ich weiß nicht, noch habe ich gerade die Zeit, es herauszufinden. Es gibt Tutorials für die Bibliotheken, ich schlage vor, dass Sie ihnen folgen! :-) –

7

Wie @notconfusing darauf hinaus kann mit Pandas und Zähler gelöst werden. Wenn für irgendeinem Grund müssen Sie Pandas nicht verwenden Sie nur mit erhalten, indem können matplotlib die Funktion in den folgenden Code:

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() 

Welche produzieren enter image description here

0

einfache und effektive Möglichkeit, Charakter zu machen Histrogramm in python

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

hier ist ein kurzer All-Pandas Ansatz:

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