2017-04-08 6 views
1

ich Pandas Datenrahmen haben wie folgt:Wie funktioniert das Binning mit Pandas DataFrame?

import pandas as pd 
import numpy as np 

data = {"first_column": ["item1", "item2", "item3", "item4", "item5", "item6", "item7"], 
     "second_column": ["cat1", "cat1", "cat1", "cat2", "cat2", "cat2", "cat2"], 
     "third_column": [5, 1, 8, 3, 731, 189, 9]} 

df = pd.DataFrame(data) 

df 
    first_column second_column third_column 
0  item1   cat1    5 
1  item2   cat1    1 
2  item3   cat1    8 
3  item4   cat2    3 
4  item5   cat2   731 
5  item6   cat2   189 
6  item7   cat2    9 

Nun lassen Sie uns sagen, dass ich mit pandas.cut() eine vierte Spalte zeigt die Klassifizierung der dritten Spalte schaffen wollte. Hier beschreibe ich jede Zeile, ob das Element in third_column kleiner oder gleich zehn ist, <=10.

df["less_than_ten"]= pd.cut(df.third_column, [-np.inf, 10, np.inf], labels=(1,0)) 

und die daraus resultierende Datenrahmen ist jetzt:

 first_column second_column third_column less_than_ten 
0  item1   cat1    5    1 
1  item2   cat1    1    1 
2  item3   cat1    8    1 
3  item4   cat2    3    1 
4  item5   cat2   731    0 
5  item6   cat2   189    0 
6  item7   cat2    9    1 

Frage: Beachten Sie die zweite Spalte second_column, mit Kategorien cat1 und cat2. Wie würde ich pandas.cut() verwenden, um diese Werte basierend auf der "Klasse" in second_column neu zu klassifizieren?

Noch wichtiger, sagen wir, ich wollte komplexere Intervalle, z.B. kleiner oder gleich 500 le (500) und größer oder gleich 20 ge (20)? Wie würde das gemacht werden? In diesem Fall sollte es ein 1 durch Gruppierung markiert sein:

 first_column second_column third_column less_than_ten 
0  item1   cat1    5    1 
1  item2   cat1    1    1 
2  item3   cat1    8    1 
3  item4   cat2    3    1 
4  item5   cat2   731    0 
5  item6   cat2   189    1 
6  item7   cat2    9    1 

Antwort

1

würde ich nicht pd.cut in diesem Fall benutzen:

df['less_than_ten'] = df.third_column.le(10).astype(np.uint8) 
df.loc[df.second_column=='cat2','less_than_ten'] = \ 
    df.loc[df.second_column=='cat2','third_column'].le(10).astype(np.uint8) + 2 

Ergebnis:

In [99]: df 
Out[99]: 
    first_column second_column third_column less_than_ten 
0  item1   cat1    5    1 
1  item2   cat1    1    1 
2  item3   cat1    8    1 
3  item4   cat2    3    3 
4  item5   cat2   731    2 
5  item6   cat2   189    2 
6  item7   cat2    9    3 
+0

Dies funktioniert sehr gut mit "weniger als 10". Was ist mit "weniger als 1000 und mehr als 20"? – ShanZhengYang

+0

@ShanZhengYang, könnten Sie bitte Ihre Frage entsprechend aktualisieren? Es ist jetzt nicht ganz klar ... – MaxU

1

voll Verständnis Während der meine vorgeschlagene Lösung sieht aus wie ein Hack und gibt Zahlen, die anders sind als Ihre, ich biete es immer noch hier:

df['less_than_ten'] = (df.second_column=='cat1').astype(int) +\ 
         (df.third_column<10).astype(int) 
# first_column second_column third_column less_than_ten 
#0  item1   cat1    5    2 
#1  item2   cat1    1    2 
#2  item3   cat1    8    2 
#3  item4   cat2    3    1 
#4  item5   cat2   731    0 
#5  item6   cat2   189    0 
#6  item7   cat2    9    1 

Sie können die Bedingungen in den Klammern beliebig komplex machen, solange sie boolesch sind().

+0

Das funktioniert! Aber wenn nur für einzelne Werte von 'df.second_column' funktioniert, richtig? Ich müsste das für 'df.second_column == 'cat1'',' df.second_column ==' cat2'' usw. wiederholen. – ShanZhengYang