在 Python 中使用 any()
Using any() in Python
在下面的数据框中,我想删除 ITEM_ID
和 VALUE
具有相同值的行对,但其中一个具有 TYPE == 'O'
(对于 'outbound'),另一个有 TYPE == 'I'
(对于 'inbound',稍后出现):
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
代码:
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')).any())
df1
返回:
Date ITEM_ID TYPE VALUE
288865 2012-04-17 ECE240 O 3.0
这不是我想要的,因为我只希望删除 4 对(在上面的 df
中标记)。
预期输出:
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 文档中指出 any()
:
Return True if any element of the iterable is true. If the iterable is empty, return False.
我认为它删除了行的所有“组”,其中 TYPE==I
行和所有其他行 VALUE
相同且 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
[编辑 2]
对于以下数据框:
Date ITEM_ID TYPE VALUE
342874 2012-06-18 ECE240 O 1.0 (not removed - out)
342415 2012-06-18 ECE240 O 25.0
325718 2012-06-18 ECE240 O 1.0 (not removed - out)
334488 2012-06-18 ECE240 O 1.0 (not removed - out)
342412 2012-06-18 ECE240 O 25.0
341634 2012-06-18 ECE240 O 9.0
341996 2012-06-19 ECE240 O 2.0 (remove - out)
341747 2012-06-19 ECE240 O 1.0 (remove - out)
272185 2012-06-24 ECE240 I 1.0 (remove - in)
219 2012-06-24 ECE240 I 1.0 (not removed - in)
6896 2012-06-24 ECE240 I 2.0 (remove - in)
351560 2012-06-24 ECE240 O 1.0 (remove - out)
312636 2012-06-26 ECE240 I 1.0 (remove - in)
2376 2012-06-30 ECE240 I 1.0 (not removed - in)
350922 2012-07-02 ECE240 O 1.0 (remove - out)
270589 2012-07-09 ECE240 I 4.0
331689 2012-07-15 ECE240 I 1.0 (remove - in)
299912 2012-07-23 ECE240 I 1.0 (not removed - in)
212418 2012-07-23 ECE240 I 3.0
3992 2012-07-24 ECE240 I 2.0
388937 2012-08-10 ECE240 O 10.0
124596 2012-08-18 ECE240 I 1.0
368945 2012-08-19 ECE240 O 12.0
368944 2012-08-19 ECE240 O 6.0
239581 2012-08-24 ECE240 I 4.0
一些也满足条件的行没有被删除(见上面的数据框),因为它们不在 TYPE==I
行的正前方。要清除包括这些行在内的所有行,我想我可以重复 运行 代码,直到这些行用完为止。我想知道是否有其他方法可以做到这一点?
使用 filter
和 groupby
不起作用的原因是 pandas 期望每个组有一个布尔值 return。如果该值为真,则 whoel 组将被删除。
相反,您在这里要做的是删除组中的个别行。一个可能的解决方案是简单地使用 apply
创建一个布尔掩码:
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]
这将 return 预期的结果。
在下面的数据框中,我想删除 ITEM_ID
和 VALUE
具有相同值的行对,但其中一个具有 TYPE == 'O'
(对于 'outbound'),另一个有 TYPE == 'I'
(对于 'inbound',稍后出现):
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
代码:
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')).any())
df1
返回:
Date ITEM_ID TYPE VALUE
288865 2012-04-17 ECE240 O 3.0
这不是我想要的,因为我只希望删除 4 对(在上面的 df
中标记)。
预期输出:
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 文档中指出 any()
:
Return True if any element of the iterable is true. If the iterable is empty, return False.
我认为它删除了行的所有“组”,其中 TYPE==I
行和所有其他行 VALUE
相同且 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
[编辑 2]
对于以下数据框:
Date ITEM_ID TYPE VALUE
342874 2012-06-18 ECE240 O 1.0 (not removed - out)
342415 2012-06-18 ECE240 O 25.0
325718 2012-06-18 ECE240 O 1.0 (not removed - out)
334488 2012-06-18 ECE240 O 1.0 (not removed - out)
342412 2012-06-18 ECE240 O 25.0
341634 2012-06-18 ECE240 O 9.0
341996 2012-06-19 ECE240 O 2.0 (remove - out)
341747 2012-06-19 ECE240 O 1.0 (remove - out)
272185 2012-06-24 ECE240 I 1.0 (remove - in)
219 2012-06-24 ECE240 I 1.0 (not removed - in)
6896 2012-06-24 ECE240 I 2.0 (remove - in)
351560 2012-06-24 ECE240 O 1.0 (remove - out)
312636 2012-06-26 ECE240 I 1.0 (remove - in)
2376 2012-06-30 ECE240 I 1.0 (not removed - in)
350922 2012-07-02 ECE240 O 1.0 (remove - out)
270589 2012-07-09 ECE240 I 4.0
331689 2012-07-15 ECE240 I 1.0 (remove - in)
299912 2012-07-23 ECE240 I 1.0 (not removed - in)
212418 2012-07-23 ECE240 I 3.0
3992 2012-07-24 ECE240 I 2.0
388937 2012-08-10 ECE240 O 10.0
124596 2012-08-18 ECE240 I 1.0
368945 2012-08-19 ECE240 O 12.0
368944 2012-08-19 ECE240 O 6.0
239581 2012-08-24 ECE240 I 4.0
一些也满足条件的行没有被删除(见上面的数据框),因为它们不在 TYPE==I
行的正前方。要清除包括这些行在内的所有行,我想我可以重复 运行 代码,直到这些行用完为止。我想知道是否有其他方法可以做到这一点?
使用 filter
和 groupby
不起作用的原因是 pandas 期望每个组有一个布尔值 return。如果该值为真,则 whoel 组将被删除。
相反,您在这里要做的是删除组中的个别行。一个可能的解决方案是简单地使用 apply
创建一个布尔掩码:
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]
这将 return 预期的结果。