2017-06-20 61 views
2

我有以下範圍和一個數據幀大熊貓:熊貓:分配類別基於其中值落在範圍

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

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

我想基於它們落入所定義的,其中在數據幀進行分類的值範圍。所以我想最終的DF看起來是這樣的:

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

我使用category數據類型的嘗試,但它似乎沒有我可以在任何地方定義範圍。

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

我可以使用category數據類型嗎?如果沒有,我能在這裏做什麼?

回答

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

鋸後您的回答,我總是知道更多關於蟒蛇〜謝謝(upvoted) – Wen

0

下面是這種類型的事情三元方法。

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

您可以使用熊貓cut,但你需要通過列應用它的列(只是因爲該函數運行在1-d輸入):

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 

所以,你可以這樣做:

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

您可以編寫一個小函數,然後使用apply將各個系列傳遞給函數:

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

你可以使用assign來創建新列。對於每個新列使用適用於過濾該系列。

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

將導致

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