2017-06-20 1 views
2

Ich habe folgende Bereiche und Pandas Datenrahmen:Pandas: assign Kategorie, basierend auf dem Wert fällt in Bereich

x >= 0  # success 
-10 <= x < 0 # warning 
X < -10  # danger 

df = pd.DataFrame({'x': [2, 1], 'y': [-7, -5], 'z': [-30, -20]}) 

Ich möchte die Werte in den Datenrahmen kategorisieren, basierend auf, wo sie innerhalb des definierten fallen Bereiche. Also würde ich das letzte DF mag so etwas wie folgt aussehen:

x y z x_cat y_cat z_cat 
0 2 -7 -30 success warning danger 
1 1 -5 -20 success warning danger 

Ich habe versucht, mit dem category Datentyp, aber es scheint nicht, kann ich eine Reihe überall definieren.

for category_column, value_column in zip(['x_cat', 'y_cat', 'z_cat'], ['x', 'y', 'z']): 
    df[category_column] = df[value_column].astype('category') 

Kann ich den category Datentyp verwenden? Wenn nicht, was kann ich hier tun?

Antwort

4

pandas.cut

c = pd.cut(
    df.stack(), 
    [-np.inf, -10, 0, np.inf], 
    labels=['danger', 'warning', 'success'] 
) 
df.join(c.unstack().add_suffix('_cat')) 

    x y z x_cat y_cat z_cat 
0 2 -7 -30 success warning danger 
1 1 -5 -20 success warning danger 

numpy

v = df.values 
cats = np.array(['danger', 'warning', 'success']) 
code = np.searchsorted([-10, 0], v.ravel()).reshape(v.shape) 
cdf = pd.DataFrame(cats[code], df.index, df.columns) 
df.join(cdf.add_suffix('_cat')) 

    x y z x_cat y_cat z_cat 
0 2 -7 -30 success warning danger 
1 1 -5 -20 success warning danger 
+1

Nach Säge Ihre Antwort zur Folge haben wird, ich weiß mehr über Python immer ~ Danke (upvoted) – Wen

0

Hier ist ein ternäres Methode für diese Art der Sache.

filter_method = lambda x: 'success' if x >= 0 else 'warning' if (x < 0 and x >= -10) else 'danger' if x < -10 else None 
df[category_column] = df[value_column].apply(filter_method) 
0

Sie können Pandas verwenden cut, aber Sie müssen es anwenden Spalte für Spalte (nur, weil die Funktion auf 1-d arbeitet Eingang):

labels = df.apply(lambda x: pd.cut(x, [-np.inf, -10, 0, np.inf], labels = ['danger', 'warning', 'success'])) 

      x  y  z 
0 success warning danger 
1 success warning danger 

So können Sie tun:

pd.concat([df, labels.add_prefix('_cat')], axis = 1) 

    x y z  cat_x  cat_y cat_z 
0 2 -7 -30 success warning danger 
1 1 -5 -20 success warning danger 
0

Sie könnten eine kleine Funktion schreiben und dann jede Serie an die Funktion übergeben Verwendung gelten:

df = pd.DataFrame({'x': [2, 1], 'y': [-7, -5], 'z': [-30, -20]}) 

def cat(x): 
    if x <-10: 
     return "Danger" 
    if x < 0: 
     return "Warning" 
    return "Success" 

for col in df.columns: 
    df[col] = df[col].apply(lambda x: cat(x)) 
0

können Sie zuweisen, um neue Spalten zu erstellen. Verwenden Sie für jede neue Spalte die Option zum Filtern der Serie.

df.assign(x_cat = lambda v: v.x.apply(lambda x: 'Sucess' if x>=0 else None), 
     y_cat = lambda v: v.y.apply(lambda x: 'warning' if -10<=x<0 else None), 
     z_cat = lambda v: v.z.apply(lambda x: 'danger' if x<=-10 else None),) 

in

x y z x_cat y_cat z_cat 
0 2 -7 -30 Sucess warning danger 
1 1 -5 -20 Sucess warning danger 
Verwandte Themen