根据条件删除组中的最后一行

Drop the last row in a group, based on condition

我想根据条件删除组中的最后一行。我做了以下事情:

df=pd.read_csv('file')
grp = df.groupby('id')
for idx, i in grp:
   df= df[df['column2'].index[-1] == 'In']

     id     product   date
 0   220    in      2014-09-01 
 1   220    out     2014-09-03 
 2   220    in      2014-10-16
 3   826    in     2014-11-11
 4   826    out     2014-12-09
 5   826    out      2014-05-19
 6   901    in      2014-09-01
 7   901    out     2014-10-05
 8   901    out     2014-11-01

当我这样做时,我只是得到: 键错误:假

我想要的输出是:

     id     product   date
 0   220    in      2014-09-01 
 1   220    out     2014-09-03
 3   826    in     2014-11-11
 4   826    out     2014-12-09 
 6   901    in      2014-09-01
 7   901    out     2014-10-05

如果要删除最后一个 in 仅每个组链反转掩码 Series.duplicated by ~ with not equal in with Series.ne:

df = df[~df['id'].duplicated() | df['product'].ne('in')]
print (df)
    id product        date
0  220      in  2014-09-01
1  220     out  2014-09-03
3  826      in  2014-11-11
4  826     out  2014-12-09
5  826     out  2014-05-19
6  901      in  2014-09-01
7  901     out  2014-10-05
8  901     out  2014-11-01

编辑:

如果希望每个组的所有可能对 in-out 使用 ,则只需要通过 dict 将非数值 in-out 映射到数值,因为 rolling不使用字符串:

#more general solution
print (df)
     id product        date
0   220     out  2014-09-03
1   220     out  2014-09-03
2   220      in  2014-09-01
3   220     out  2014-09-03
4   220      in  2014-10-16
5   826      in  2014-11-11
6   826      in  2014-11-11
7   826     out  2014-12-09
8   826     out  2014-05-19
9   901      in  2014-09-01
10  901     out  2014-10-05
11  901      in  2014-09-01
12  901     out  2014-11-01

pat = np.asarray(['in','out'])
N = len(pat)

d = {'in':0, 'out':1}
ma  = (df['product'].map(d)
                   .groupby(df['id'])
                   .rolling(window=N , min_periods=N)
                   .apply(lambda x: (x==list(d.values())).all(), raw=False)
                   .mask(lambda x: x == 0) 
                   .bfill(limit=N-1)
                   .fillna(0)
                   .astype(bool)
                   .reset_index(level=0, drop=True)
             )
df = df[ma]
print (df)
     id product        date
2   220      in  2014-09-01
3   220     out  2014-09-03
6   826      in  2014-11-11
7   826     out  2014-12-09
9   901      in  2014-09-01
10  901     out  2014-10-05
11  901      in  2014-09-01
12  901     out  2014-11-01

一个简单的方法是在打开.csv文件时添加skipfooter=1

df = pd.read_csv(file, skipfooter=1, engine='python')