在Python中使用any()
在以下数据框中,我想删除对具有相同项_ID和值的行,但其中一个类型为'outbound'的类型=='O',另一个类型为'inbound'的类型=='I',后面会出现:在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
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]