我有几个数据集,如果列子集中的所有值都等于0或N(取决于列),我需要丢弃观察值。例如:
df = pd.DataFrame({'one':[0,0,1,2,0], 'two':[0,0,0,0,0], 'three':['N','Y','N','Y','N']})
drop_subset = ['one', 'three']
In [4]: df
Out[4]:
one three two
0 0 N 0
1 0 Y 0
2 1 N 0
3 2 Y 0
4 0 N 0
我只需要查看列one
和three
,然后只删除第0行和第4行。如果它只是一个值而不是两个或更多,我会用它:
df[~(df[drop_subset] == 0).all(axis=1)]
它会正常工作。但是当我试图扩展它时:
df[~(df[drop_subset] == 0 or df[drop_subset] == 'N').all(axis=1)]
我感到害怕:
ValueError:DataFrame的真值是不明确的。使用a.empty,a.bool(),a.item(),a.any()或a.all()。
我原本以为使用any
或all
运算符来处理每个内部条件......除了逻辑没有那样工作。我不需要知道任何或所有值是否为0,或者单独是否任何或所有值都是N.我需要知道所有值是否为N或那就是说,我无能为力:
In [71]: (df[drop_subset] == 0)
Out[71]:
one three
0 True False
1 True False
2 False False
3 False False
4 True False
没有同时测试N' N'价值也。虽然在这个小型数据框架上似乎很明显,我可以测试列one
为0,列three
为' N'另外,实际上我的drop_subset
包含了近100列,这些列在三个不同的数据集中有所不同,并且没有手动编码所有这些列,我不知道哪些列会有0,哪些列会有' N& #39 ;. 我肯定知道的是,如果一个观察结果 all 0或者N' N'在这个子集中,我需要删除它。
我的最后一种方法是使用带有lambda的apply,但由于数据的大小,它会很慢。另外我觉得必须有一种矢量化的方式来表达Panadas中的这种逻辑,而这正是我所寻找的。 p>
答案 0 :(得分:3)
IIUC您可以使用DataFrame.isin()方法:
In [68]: df[df[drop_subset].isin([0,'N']).all(1)]
Out[68]:
one three two
0 0 N 0
4 0 N 0
In [69]: df[~df[drop_subset].isin([0,'N']).all(1)]
Out[69]:
one three two
1 0 Y 0
2 1 N 0
3 2 Y 0
答案 1 :(得分:1)
我认为Max在他的回答中钉了它,isin
当然是你应该使用的。
事实上,这是必须使用的内容,因为df[drop_subset] == 'N'
无论如何都不会工作,你会得到:
TypeError: Could not compare ['N'] with block values
你需要isin()来完成这项工作。
我特别想指出你得到的错误," [DataFrame / Series]的真值是模棱两可的"事实上,您应始终使用&
代替and
,|
代替or
。
二元运算符&
和|
将返回逐元素比较,因此将返回一个数组。
and
和or
尝试将其转换为单个布尔值进行比较,但不存在。