Pandas:在创建新列时合并具有相同索引的行

时间:2016-12-12 13:40:06

标签: python pandas

我刚刚开始使用Pandas并且拥有一个包含多个具有相同索引的行的数据框,表明变量具有某些特征,例如

ItemID       Property    Numerical_value
A1           'Red'       10     
A1           'Fruit'     0
B1           'Red'       25
C1           'Liquid'    0

我的数据的假设是; 只有属性为' Red'有一个数值。和 如果某件商品具有“Fruit'它还有Red酒店。

我面临的问题是将此日期框架转换为遵循每个itemID的单热编码方案,同时还保存数值(如果它存在),例如;

ItemID       Red&Fruit   Just_red  Other  Numerical_value
A1           1           0         0      10         
B1           0           1         0      25
C1           0           0         1      0

目前,我已经编写了以下代码;

def read_report:
    fp = 'file_path'
    df = (pd.read_csv(fp))
    group = df.groupby('ItemID')['Property','Numerical_value'].apply(test_function)

def test_function(df):
    if 'Fruit' in df.values:
       num_val = df[df['Property'] == 'Red']['Numerical_value'].values[0]
       return pd.Series({'Red&Fruit': '1', 'Num_val': num_val})
    elif 'Red' in df.values:
       num_val= df[df['Property'] == 'Red']['Num_val'].values[0]
       return pd.Series({'Just_red': '1', 'Num_val': num_val})
    else:
       return pd.Series({'Other': '1', 'Num_val': 0})

这似乎不是最优的,尤其是获取每个汇总行的数值的方式感觉相当苛刻。

有更好的方法可以达到相同的效果吗?

1 个答案:

答案 0 :(得分:3)

我建议按组获取属性集:

df.groupby('ItemID')['Property'].apply(set)
Out[15]: 
ItemID
A1    {'Red', 'Fruit'}
B1             {'Red'}
C1          {'Liquid'}

然后您可以使用get_dummies

 df.groupby('ItemID')['Property'].apply(set).str.get_dummies()
Out[17]: 
        {"'Liquid'"}  {"'Red'", "'Fruit'"}  {"'Red'"}
ItemID                                               
A1                 0                     1          0
B1                 0                     0          1
C1                 1                     0          0

在您的示例中,您只需要重命名列。但是,您可能希望replace操作后groupby值。

最后,合并数值:

pd.concat([df.groupby('ItemID')['Property'].apply(set).str.get_dummies(),
           df.groupby('ItemID')['Numerical_value'].first()], axis=1)
Out[21]: 
        {"'Liquid'"}  {"'Red'", "'Fruit'"}  {"'Red'"}  Numerical_value
ItemID                                                                
A1                 0                     1          0               10
B1                 0                     0          1               25
C1                 1                     0          0                0

这里我取第一个数值,如你的例子所示。