在Python中使用any()

在Python中使用any(),python,pandas,dataframe,data-cleaning,Python,Pandas,Dataframe,Data Cleaning,在以下数据框中,我想删除对具有相同项_ID和值的行,但其中一个类型为'outbound'的类型=='O',另一个类型为'inbound'的类型=='I',后面会出现: Date ITEM_ID TYPE VALUE 236656 2012-02-28 ECE240 O 1.0 242962 2012-03-02 ECE240 O 1.0 248720 2012-03-06 ECE240 O 1.0 (remove - out) 2

在以下数据框中,我想删除对具有相同项_ID和值的行,但其中一个类型为'outbound'的类型=='O',另一个类型为'inbound'的类型=='I',后面会出现:

        Date        ITEM_ID TYPE VALUE
236656  2012-02-28  ECE240  O    1.0
242962  2012-03-02  ECE240  O    1.0
248720  2012-03-06  ECE240  O    1.0 (remove - out)
226194  2012-03-19  ECE240  I    1.0 (remove - in)
263320  2012-03-20  ECE240  O    1.0 (remove - out)
242977  2012-03-24  ECE240  I    1.0 (remove - in)
209713  2012-03-31  ECE240  O    1.0
279806  2012-04-06  ECE240  O    1.0
277213  2012-04-08  ECE240  O    1.0
288865  2012-04-17  ECE240  O    3.0
290041  2012-04-20  ECE240  O    2.0 (remove - out)
136730  2012-04-22  ECE240  I    2.0 (remove - in)
295236  2012-04-24  ECE240  O    1.0
292597  2012-04-30  ECE240  O    1.0
313503  2012-05-14  ECE240  O    1.0
314786  2012-05-15  ECE240  O    2.0
318277  2012-05-20  ECE240  O    1.0 (remove - out)
328787  2012-06-01  ECE240  O    2.0
2134    2012-06-16  ECE240  I    1.0 (remove - in)
343138  2012-06-17  ECE240  O    2.0
343139  2012-06-22  ECE240  O    1.0
346935  2012-06-29  ECE240  O    1.0
215777  2012-07-06  ECE240  O    1.0
356292  2012-07-06  ECE240  O    2.0
261989  2012-07-21  ECE240  O    2.0
代码:

它返回:

        Date        ITEM_ID TYPE    VALUE
288865  2012-04-17  ECE240  O       3.0
这不是我想要的,因为我只希望在上面的df中删除4对标签。 预期产出:

        Date        ITEM_ID TYPE VALUE
236656  2012-02-28  ECE240  O    1.0
242962  2012-03-02  ECE240  O    1.0


209713  2012-03-31  ECE240  O    1.0
279806  2012-04-06  ECE240  O    1.0
277213  2012-04-08  ECE240  O    1.0
288865  2012-04-17  ECE240  O    3.0
 

295236  2012-04-24  ECE240  O    1.0
292597  2012-04-30  ECE240  O    1.0
313503  2012-05-14  ECE240  O    1.0
314786  2012-05-15  ECE240  O    2.0

328787  2012-06-01  ECE240  O    2.0

343138  2012-06-17  ECE240  O    2.0
343139  2012-06-22  ECE240  O    1.0
346935  2012-06-29  ECE240  O    1.0
215777  2012-07-06  ECE240  O    1.0
356292  2012-07-06  ECE240  O    2.0
261989  2012-07-21  ECE240  O    2.0
在Python文档中,它表示任何:

如果iterable的任何元素为True,则返回True。如果iterable为空,则返回False

我认为它删除了一行中TYPE==I的所有行组,以及值相同且TYPE==O的所有其他行。我如何才能为每个组只删除一对,即,对于TYPE==I的每一行,前面只有一行TYPE==O

[编辑1]

我还尝试:

df  = df.sort_values(by = ['ITEM_ID', 'Date'])
df1 = df.groupby(['ITEM_ID','VALUE']).filter(lambda x : ~(x['TYPE'].eq('I') & (x['TYPE'].shift().eq('O'))))
df1
哪个捕获到错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-935-65eda184ce24> in <module>
      1 df= df.sort_values(by = ['ITEM_ID', 'Date'])
----> 2 df1= df.groupby(['ITEM_ID','VALUE']).filter(lambda x : ~(x['TYPE'].eq('I') & (x['TYPE'].shift().eq('O'))))
      3 df1

~\Anaconda3\lib\site-packages\pandas\core\groupby\generic.py in filter(self, func, dropna, *args, **kwargs)
   1594                 # non scalars aren't allowed
   1595                 raise TypeError(
-> 1596                     f"filter function returned a {type(res).__name__}, "
   1597                     "but expected a scalar bool"
   1598                 )

TypeError: filter function returned a Series, but expected a scalar bool
一些也满足条件的行不会被删除,请参见上面的dataframe,因为它们不直接位于TYPE==I行的前面。要清除包括这些行在内的所有行,我想我可以反复运行代码,直到这些行用完为止。我想知道是否还有其他方法可以做到这一点?

将筛选器与groupby一起使用不起作用的原因是pandas希望每个组都有一个布尔返回值。如果该值为true,则将删除整个组

相反,这里要做的是删除组中的单个行。一种可能的解决方案是简单地使用创建布尔掩码:

mask = df.sort_values('Date')\
  .groupby(['ITEM_ID', 'VALUE'])['TYPE']\
  .apply(lambda x: ((x == 'O') & (x.shift(-1) == 'I')) | (x == 'I') & (x.shift(1) == 'O'))
df.loc[~mask]
这将返回预期结果。

将筛选器与groupby一起使用不起作用的原因是pandas希望每个组都有一个布尔返回值。如果该值为true,则将删除整个组

相反,这里要做的是删除组中的单个行。一种可能的解决方案是简单地使用创建布尔掩码:

mask = df.sort_values('Date')\
  .groupby(['ITEM_ID', 'VALUE'])['TYPE']\
  .apply(lambda x: ((x == 'O') & (x.shift(-1) == 'I')) | (x == 'I') & (x.shift(1) == 'O'))
df.loc[~mask]


这将返回预期的结果。

可能尝试将iterable放在any函数中,而不是将any链接到它捕获的ITI@SGolds的末尾。错误类型错误:filter函数返回了一个int,但需要一个标量boolIf,如果TYPE='O'行排在第一位,TYPE='I'排在第二位,是否应该删除?或者你的意思是保证订单永远不会发生?对于下面的3行,你想删除其中的2行吗?236656 2012-02-28 ECE240 O 1.0 242962 2012-03-02 ECE240 O 1.0 248720 2012-03-06 ECE240 O 1.0删除-删除还是仅删除标记为remove outHi@JoeFerndz I的一个要删除这对248720 2012-03-06 ECE240 O 1.0删除-删除226194 2012-03-19 ECE240 I 1.0删除-输入。因此,每个类型==I都应该与之前发生的类型==O匹配。也许可以尝试将iterable放在any函数中,而不是将any链接到它捕获的错误的ITI@SGolds的末尾TypeError:filter函数返回了一个int,但需要一个标量boolIf,如果类型=='O'行排在第一位,类型=='I'排在第二位,该不该放弃?或者你的意思是保证订单永远不会发生?对于下面的3行,你想删除其中的2行吗?236656 2012-02-28 ECE240 O 1.0 242962 2012-03-02 ECE240 O 1.0 248720 2012-03-06 ECE240 O 1.0删除-删除还是仅删除标记为remove outHi@JoeFerndz I的一个要删除这对248720 2012-03-06 ECE240 O 1.0删除-删除226194 2012-03-19 ECE240 I 1.0删除-输入。因此,每种类型==我都应该与之前出现的类型==O匹配。感谢您提供了漂亮的答案-这正是我想要的。@nilsinelabore:很乐意帮助=@nilsinelabore,因为您是按日期对数据进行排序的,所以数据将直接位于它上面。你不是已经得到你想要的了吗?你还有别的东西要找吗?如果是这样的话,你能分享你想要的输出作为例子,这样我们就可以尝试解决它了。感谢您的帮助:@nilsinelabore:很好,很高兴您能解决它:谢谢您给出了漂亮的答案-这正是我想要的。@nilsinelabore:高兴帮助=@nilsinelabore,由于您按日期对数据进行排序,因此数据将直接位于其上方。你不是已经得到你想要的了吗?你还有别的东西要找吗?如果是这样的话,你能分享你想要的输出作为例子,这样我们就可以尝试解决它了。谢谢你的帮助:@nilsinelabore:很好,很高兴你解决了这个问题:
mask = df.sort_values('Date')\
  .groupby(['ITEM_ID', 'VALUE'])['TYPE']\
  .apply(lambda x: ((x == 'O') & (x.shift(-1) == 'I')) | (x == 'I') & (x.shift(1) == 'O'))
df.loc[~mask]