我知道如何根据this stack overflow question,中的简单条件删除行,但是,我需要使用更复杂的条件删除行。
我的情况:我有数据行,其中每行有四列包含数字代码。我需要删除所有没有至少一个前导数字少于5的代码的行。我目前有一个函数,我可以使用dataframe.apply创建一个新列,'keep',和如果它是要保留的行,则用1填充它。然后,我使用该简单的保留列进行第二次传递,以删除不需要的行。我正在寻找的是一种方法,只需一次通过,而无需创建新列。
示例数据:
a | b | c | d
0 145|567|999|876
1 999|876|543|543
在那个数据中,我想保留第一行,因为在'a'列中,前导数字小于5.第二行没有前导数字小于5的列,因此需要删除该行
答案 0 :(得分:4)
这应该有效:
In [31]:
df[(df.apply(lambda x: x.str[0].astype(int))).lt(5).any(axis=1)]
Out[31]:
a b c d
0 145 567 999 876
所以基本上这会使用向量化str
方法获取每列的第一个字符,我们将其转换为int,然后我们调用lt
,它小于行方式以生成布尔值df然后,我们在df行上调用any
以在索引上生成一个布尔掩码,用于掩盖df。所以打破了上面的内容:
In [34]:
df.apply(lambda x: x.str[0].astype(int))
Out[34]:
a b c d
0 1 5 9 8
1 9 8 5 5
In [35]:
df.apply(lambda x: x.str[0].astype(int)).lt(5)
Out[35]:
a b c d
0 True False False False
1 False False False False
In [37]:
df.apply(lambda x: x.str[0].astype(int)).lt(5).any(axis=1)
Out[37]:
0 True
1 False
dtype: bool
修改强>
要处理NaN
值,请添加对dropna
的调用:
In [39]:
t="""a,b,c,d
0,145,567,999,876
1,999,876,543,543
2,,324,344"""
df = pd.read_csv(io.StringIO(t),dtype=str)
df
Out[39]:
a b c d
0 145 567 999 876
1 999 876 543 543
2 NaN 324 344 NaN
In [44]:
df[(df.apply(lambda x: x.dropna().str[0].astype(int))).lt(5,axis=0).any(axis=1)]
Out[44]:
a b c d
0 145 567 999 876
2 NaN 324 344 NaN