熊猫:通过在行级应用自定义功能来创建列

时间:2020-05-18 14:01:41

标签: python pandas

我有一个如下的数据框df

ZMONTH    GROUP   ORDER_QTY
201907     A         25
201908     A         23
201909     A         24
201907     B         15
201908     B         0
201909     B         0

我要根据以下条件添加另一列ACTIVE

if ORDER_QTY of last two rows for each group is 0, then ACTIVE==0 else 1

因此,结果df_f看起来像

ZMONTH    GROUP   ORDER_QTY   ACTIVE
201907     A         25         1
201908     A         23         1
201909     A         24         1
201907     B         15         0
201908     B         0          0
201909     B         0          0

根据上述逻辑,我尝试了以下方法

def active_field(row):
   if row.loc[row['ZMONTH']=='201909','ORDER_QTY']==0:
      val=0
   elif row.loc[row['ZMONTH']=='201908','ORDER_QTY']==0:
      val=0
   else:
      val=1
   return val
df['ACTIVE'] = df.apply(active_field,axis=1)

以上代码给出了IndexingError: Too many indexers错误。

我在哪里想念?

3 个答案:

答案 0 :(得分:1)

您可以groupby并检查每组最后两行是否相等,然后对布尔结果取all。然后只需将生成的布尔数组视为int8并将它们分配给ACTIVE

df['ACTIVE'] = (df.groupby('GROUP').ORDER_QTY
                  .transform(lambda x: x.tail(2).ne(0).any())
                  .view('i1'))

print(df)

  ZMONTH GROUP  ORDER_QTY  ACTIVE
0  201907     A         25       1
1  201908     A         23       1
2  201909     A         24       1
3  201907     B         15       0
4  201908     B          0       0
5  201909     B          0       0

答案 1 :(得分:1)

如果所有值都是numpy.where0,则使用Series.all来测试每组最后2个值:

s = df.groupby('GROUP')['ORDER_QTY'].transform(lambda x: x.tail(2).eq(0).all())
df['ACTIVE'] = np.where(s, 0, 1)
print (df)
   ZMONTH GROUP  ORDER_QTY  ACTIVE
0  201907     A         25       1
1  201908     A         23       1
2  201909     A         24       1
3  201907     B         15       0
4  201908     B          0       0
5  201909     B          0       0

答案 2 :(得分:1)

我们也可以使用DataFrame.pivot

df['ACTIVE'] = (df['GROUP'].map(df.pivot(*df)[::-1].cumsum().iloc[1].ne(0))
                           .astype('int'))
print(df)

   ZMONTH GROUP  ORDER_QTY  ACTIVE
0  201907     A         25       1
1  201908     A         23       1
2  201909     A         24       1
3  201907     B         15       0
4  201908     B          0       0
5  201909     B          0       0