按条件将值广播到数据框组

时间:2019-06-21 18:47:47

标签: python pandas

数据框:

STUD_ID   CLASS   GRADE  CATEGORY 
1         'Sci'    max  'Alpha' 
2         'Sci'    7    'Omega' 
3         'Sci'    9    'Alpha' 
4         'Sci'    3    'Alpha' 
5         'Sci'    9    'Alpha' 
7         'eng'    max  'Gamma' 
8         'eng'    5    'Gamma' 
9         'eng'    3    'Epsilon'
10        'Art'    3    'Lambda' 
11        'Art'    8    'Lambda' 
12        'Art'    max  undefined 
13        'Art'    1    undefined 
14        'Art'    5    undefined 

我想创建一个新列CATEGORY_1,该列将CATEGORY值(GRADE最大)广播到各自的CLASS组。参见下面的结果df。

STUD_ID   CLASS   GRADE  CATEGORY CATEGORY_1
1         'Sci'    max  'Alpha' .   'Alpha'
2         'Sci'    7    'Omega' .   'Alpha'
3         'Sci'    9    'Alpha' .   'Alpha'
4         'Sci'    3    'Alpha' .   'Alpha'
5         'Sci'    9    'Alpha' .   'Alpha'
7         'eng'    max  'Gamma' .   'Gamma'
8         'eng'    5    'Gamma' .   'Gamma'
9         'eng'    3    'Epsilon'   'Gamma'
10        'Art'    3    'Lambda' .  undefined
11        'Art'    8    'Lambda' .  undefined
12        'Art'    max  undefined . undefined
13        'Art'    1    undefined . undefined
14        'Art'    5    undefined . undefined

我尝试过使用groupby + transform,但无法弄清楚如何仅在GRADE最大的情况下广播CATEGORY值。

4 个答案:

答案 0 :(得分:4)

因为您提到了groupby + transform

这很困难,因为您的转换依赖于不止一列。这要求您的转换函数既要接受Series,也要接受整个DataFrame,然后可以将其子集到组内(基于Series索引)。您应该有一个唯一索引才能正常工作。

def get_max_cat(grade, df):
    s = grade=='max'
    return df.loc[s[s].index, 'CATEGORY'].item()  # Assumes always one max

df['Category_1'] = df.groupby('CLASS').GRADE.transform(get_max_cat, df=df)

答案 1 :(得分:3)

如果我理解正确,您可以使用字典映射来实现:

//rug.route.js
...
rugRoutes.route('/:id/delete', { useFindAndModify: false }).get(function (req, res) {
    let id = req.params.id;
    Rug.findOneAndDelete({ "id": id }, function (err) {
        if (err) { return res.json(err); }
        else { res.json('Successfully deleted'); }
    });
});

输出:

df['CATEGORY_1'] = df.CLASS.map(pd.Series(df[df.GRADE == 'max']['CATEGORY'].values,index=df[df.GRADE == 'max']['CLASS']).to_dict())

答案 2 :(得分:3)

您可以先在GRADE列中选择值“ max”的行,然后在CLASS上选择merge,例如:

df = df.merge( df[df.GRADE == 'max', ['CLASS','CATEGORY']], 
               on='CLASS, how='left',suffixes=('','_1'))

答案 3 :(得分:2)

另一种方法是使用whereCATEGORY中的GRADE而不是max变成NaN。然后,将ffillbfill应用于每组CLASS

df['CATEGORY_1'] = df.CATEGORY.where(df.GRADE.eq('max')) \
                     .groupby(df.CLASS).apply(lambda x: x.ffill().bfill())


Out[1493]:
    STUD_ID  CLASS GRADE   CATEGORY CATEGORY_1
0         1  'Sci'   max    'Alpha'    'Alpha'
1         2  'Sci'     7    'Omega'    'Alpha'
2         3  'Sci'     9    'Alpha'    'Alpha'
3         4  'Sci'     3    'Alpha'    'Alpha'
4         5  'Sci'     9    'Alpha'    'Alpha'
5         7  'eng'   max    'Gamma'    'Gamma'
6         8  'eng'     5    'Gamma'    'Gamma'
7         9  'eng'     3  'Epsilon'    'Gamma'
8        10  'Art'     3   'Lambda'  undefined
9        11  'Art'     8   'Lambda'  undefined
10       12  'Art'   max  undefined  undefined
11       13  'Art'     1  undefined  undefined
12       14  'Art'     5  undefined  undefined