为何Pandas中lambda x: all(x[x == 0])无法得到预期结果?
问题:筛选DataFrame中Week列全为0的行失败原因及解决方法
样本DataFrame
ID Date Week_1 Week_2 Week_3 Week_4 Week_5 Week_6 Week_7 Week_8 Week_9 0 A 2022-01-01 0 0 0 1 0 0 0 1 1 1 A 2022-01-02 0 0 0 1 0 0 0 1 1 2 B 2022-01-01 0 0 0 0 0 1 1 1 1 3 A 2022-02-03 0 0 0 1 0 0 0 1 1 4 B 2022-01-04 0 0 0 0 0 1 1 1 1 5 B 2022-01-15 0 0 0 0 0 1 1 1 1 6 C 2022-01-02 0 0 0 0 0 0 0 1 1 7 C 2022-01-02 0 0 0 0 0 0 0 1 1 8 D 2022-01-02 0 0 0 0 0 0 0 1 1 9 D 2022-01-01 0 0 0 0 0 0 0 1 1 10 E 2022-03-01 0 0 0 0 0 0 0 0 0
问题描述
使用以下代码能正确筛选出Week列中存在1的行:
df.loc[df.iloc[:, 2:].apply(lambda x : any(x[x == 1]), axis = 1), :]
但尝试用以下代码筛选Week列全为0的行时,得到空结果(预期应获取ID为E的第10行):
df.loc[df.iloc[:, 2:].apply(lambda x : all(x[x == 0]), axis = 1), :]
另外两种尝试写法也未得到预期结果:
df.loc[df.iloc[:, 2:].apply(lambda x : all(x[x != 1]), axis = 1), :] df.loc[df.iloc[:, 2:].apply(lambda x : all(x[x < 1]), axis = 1), :]
错误原因
你写的x[x == 0]是先从行数据中过滤出等于0的元素,再对这个过滤后的子集执行all()判断。但Python中0等价于布尔值False,所以all([0,0,...])会返回False——哪怕原行全是0,这个判断也会失败。
另外两种写法x[x !=1]或x[x <1]也是同样的逻辑错误:过滤后的子集元素是0,all()判断的是这些元素是否为布尔真,而非原行所有元素是否满足全0的条件。
正确写法
方法1:直接遍历行内元素判断
df.loc[df.iloc[:, 2:].apply(lambda x: all(val == 0 for val in x), axis=1)]
方法2:向量化操作(效率更高,推荐)
无需使用apply,直接利用DataFrame的向量化方法:
df.loc[(df.iloc[:, 2:] == 0).all(axis=1)]
方法3:利用已有正确逻辑取反
既然能筛选出含1的行,全0行就是它的补集:
df.loc[~df.iloc[:, 2:].apply(lambda x: any(x == 1), axis=1)]
内容的提问来源于stack exchange,提问作者Karthik S
相关产品推荐
相关产品推荐

