nil*_*ore 1 python dataframe pandas data-cleaning
在以下数据框中,我想删除具有相同值的行对ITEM_ID和VALUE,但其中一个具有TYPE == 'O'(对于“出站”)而另一个具有TYPE == '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
Run Code Online (Sandbox Code Playgroud)
代码:
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
Run Code Online (Sandbox Code Playgroud)
返回:
Date ITEM_ID TYPE VALUE
288865 2012-04-17 ECE240 O 3.0
Run Code Online (Sandbox Code Playgroud)
这不是我想要的,因为我期望只移除 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
Run Code Online (Sandbox Code Playgroud)
在 Python 文档中,它声明为any():
如果可迭代对象的任何元素为真,则返回 True。如果可迭代对象为空,则返回 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
Run Code Online (Sandbox Code Playgroud)
捕获错误:
---------------------------------------------------------------------------
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
Run Code Online (Sandbox Code Playgroud)
[编辑 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
Run Code Online (Sandbox Code Playgroud)
一些也满足条件的行不会被删除(参见上面的数据框),因为它们不是紧邻TYPE==I行的前面。为了清除包括这些行在内的所有行,我想我可以重复运行代码,直到这些行用完为止。我想知道是否有其他方法可以做到?
使用filterwithgroupby不起作用的原因是 Pandas 期望每个组有一个布尔返回值。如果该值为真,则整个组将被删除。
相反,您在这里要做的是删除组中的单个行。一个可能的解决方案是简单地使用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]
Run Code Online (Sandbox Code Playgroud)
这将返回预期的结果。
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |