2016-07-27 20 views
2

Ich habe ein DataFrame, die wie folgt aussieht:Pandas Histogramm (Counts) auf gruppiert (von) Werte

>>> df 
    type  value 
0  1 0.698791 
1  3 0.228529 
2  3 0.560907 
3  1 0.982690 
4  1 0.997881 
5  1 0.301664 
6  1 0.877495 
7  2 0.561545 
8  1 0.167920 
9  1 0.928918 
10  2 0.212339 
11  2 0.092313 
12  4 0.039266 
13  2 0.998929 
14  4 0.476712 
15  4 0.631202 
16  1 0.918277 
17  3 0.509352 
18  1 0.769203 
19  3 0.994378 

ich auf der type Spalte Gruppe möchten und Histogramm-Bins für die Spalte value in 10 neue erhalten Spalten, z so ähnlich:

 1 3 9 6 8 10 5 4 7 2 
type 
1  0 1 0 0 0 2 1 1 0 1 
2  2 1 1 0 0 1 1 0 0 0 
3  2 0 0 0 0 1 1 0 0 0 
4  1 1 0 0 0 1 0 0 0 1 

Wo Spalte 1 die Zählung für das erste Fach ist (0.0 zu 0.1) und so weiter ...

Mit numpy.histogram, kann ich nur folgendes erhalten:

>>> df.groupby('type')['value'].agg(lambda x: numpy.histogram(x, bins=10, range=(0, 1))) 
    type 
1  ([0, 1, 1, 1, 1, 0, 0, 0, 0, 2], [0.0, 0.1, 0.... 
2  ([2, 0, 1, 0, 1, 0, 0, 0, 1, 1], [0.0, 0.1, 0.... 
3  ([2, 0, 0, 0, 1, 0, 0, 0, 0, 1], [0.0, 0.1, 0.... 
4  ([1, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0.0, 0.1, 0.... 
Name: value, dtype: object 

Das schaffe ich nicht im richtigen Format (zumindest nicht auf einfache Weise).

fand ich einen Trick zu tun, was ich will, aber es ist sehr hässlich:

>>> d = {str(k): lambda x, _k = k: ((x >= (_k - 1)/10) & (x < _k/10)).sum() for k in range(1, 11)} 
>>> df.groupby('type')['value'].agg(d) 
     1 3 9 6 8 10 5 4 7 2 
type 
1  0 1 0 0 0 2 1 1 0 1 
2  2 1 1 0 0 1 1 0 0 0 
3  2 0 0 0 0 1 1 0 0 0 
4  1 1 0 0 0 1 0 0 0 1 

Gibt es eine bessere Art und Weise, was zu tun ich will? Ich weiß, dass in R, kann die aggregate Methode eine DataFrame zurückgeben, aber nicht in Python ...

Antwort

1

ist das, was Sie wollen?

In [98]: %paste 
bins = np.linspace(0, 1.0, 11) 
labels = list(range(1,11)) 

(df.assign(q=pd.cut(df.value, bins=bins, labels=labels, right=False)) 
    .pivot_table(index='type', columns='q', aggfunc='size', fill_value=0) 
) 
## -- End pasted text -- 
Out[98]: 
q  1 2 3 4 5 6 7 8 9 10 
type 
1  0 1 0 1 0 0 1 1 1 4 
2  1 0 1 0 0 1 0 0 0 1 
3  0 0 1 0 0 2 0 0 0 1 
4  1 0 0 0 1 0 1 0 0 0 
+0

Es kann den Trick tun - ich habe nicht 'DataFrame.assign', ich werde sehen, ob ich meine' pandas' Version aktualisieren kann (ich kann nicht möglich sein, ...). Ist es möglich, dies zu verwenden, wenn ich auf zwei Spalten gruppieren möchte, z.B. 'type' und' version'? – Holt

+0

@Holt, ich habe '.assign()' verwendet, um es zu einem Einzeiler zu machen. Sie können diese Spalte zuerst hinzufügen und sie dann als zweiten Befehl verwenden. Für die 'Version' - ich denke, dass Sie Ihre Probe und erwartete DFs in der Frage aktualisieren sollten, weil es nicht ganz klar ist – MaxU

+1

Ich schaffte es, es mit' df ['bin'] = pd.cut (...) '. Ich war besorgt, dass '.pivot_table' nicht mit zwei Indizes funktionieren könnte, aber es tut (' index = ('col1', 'col2') '), und dass ich viele Spalten löschen müsste (mein realer Datenrahmen hat eine viele Spalten), aber anscheinend ist der "Tropfen" nicht notwendig, um es zum Laufen zu bringen. Ich füge auch hinzu, um ein extra Bins von '1.0' zu' 1.1' hinzuzufügen, um eine bestimmte Bin zu bekommen, wenn 'value == 1' (aber ich habe das in meiner Frage vergessen, so dass du es nicht erraten kannst ...). Vielen Dank. – Holt