如何简化Pandas代码 不使用for循环删除B、C列同时为空的行
Pandas 批量删除B、C列同时为空的行(无numpy、无循环实现)
你现有代码已经正确筛选出了所有需要删除的行索引,完全不需要逐行循环执行drop,以下是两种纯Pandas实现的简化方案,全程不依赖numpy:
方案1:最小改动版(复用你现有筛选逻辑)
df.drop() 原生支持直接传入索引列表批量删除行,不需要遍历索引逐个删除,只需要把你拿到的待删索引集合直接传给drop的index参数即可:
def drop_empty_line(df): # 筛选出B、C同时为空的行索引 drop_index = df[(df["B"].isna()) & (df["C"].isna())].index # 批量删除所有符合条件的行 return df.drop(index=drop_index)
这个方案和你原有逻辑完全一致,改动量最小,避免了逐行drop重复生成新DataFrame的性能开销。
方案2:布尔索引直接筛选保留行(更符合Pandas惯用写法)
删除逻辑反过来就是保留规则:只要B、C任意一列非空就保留,可以直接用布尔索引筛出符合保留条件的行,不需要调用drop方法,代码更简洁直观:
def drop_empty_line(df): # 保留B非空 或者 C非空的行 return df[(df["B"].notna()) | (df["C"].notna())]
注意:Pandas中做条件组合时,逻辑与
&、逻辑或|的优先级高于比较运算符,每个单独的判断条件必须用圆括号包裹,否则会报语法错误。
完整可运行代码
import pandas as pnd def drop_empty_line(df): # 两种写法二选一即可 # 写法1:批量drop # drop_index = df[(df["B"].isna()) & (df["C"].isna())].index # return df.drop(index=drop_index) # 写法2:直接筛选保留行 return df[(df["B"].notna()) | (df["C"].notna())] def main(): df = pnd.DataFrame({ "A": [5, 0, 4, 6, 5], "B": [pnd.NA, 4, pnd.NA, pnd.NA, 5], "C": [pnd.NA, pnd.NA, 9, pnd.NA, 8], "D": [5, 3, 8, 5, 2], "E": [pnd.NA, 4, 2, 0, 3] }) print(drop_empty_line(df)) if __name__ == '__main__': main()
运行后输出的结果和你原有循环写法完全一致,会删除索引为0、3的两行(这两行B、C列均为空值),其余行全部保留。
内容的提问来源于stack exchange,提问作者Jean-baptiste Briois
相关产品推荐
相关产品推荐

