You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas如何删除含缺失值或取值不在0-1区间的DataFrame列

解决方案

要实现按规则过滤列的需求,不用写循环或自定义apply函数,用pandas内置向量化方法就能高效完成,数据量越大性能优势越明显。
你需要保留同时满足以下两个条件的列:

  • 列中不存在缺失值
  • 列中所有取值都落在[0,1]闭区间内

核心实现

你原有代码里的organize_columns和get_data函数可以直接复用,删掉无效的自定义校验函数,替换prepare_data里的处理逻辑即可:

import pandas as pd
import numpy as np


def prepare_data(data_abs_path, cols_abs_path):
    df_crime = pd.DataFrame(
        data=get_data(data_file_abs_path),
        columns=organize_columns(columns_file_abs_path)
    )
    df_crime = df_crime.iloc[:, 5:]
    # 替换原始数据里的缺失占位符?为标准NaN
    df_crime = df_crime.replace('?', np.nan)
    # 统一转为浮点类型才能做数值比较
    df_crime = df_crime.astype(float)

    # 逐列判断是否符合保留要求
    # 1. 列内无缺失值
    col_has_no_na = ~df_crime.isna().any()
    # 2. 列内不存在小于0或大于1的越界值
    col_all_in_range = ~((df_crime < 0) | (df_crime > 1)).any()
    # 只保留同时满足两个条件的列
    df_crime = df_crime.loc[:, col_has_no_na & col_all_in_range]

    return df_crime


# 以下两个函数保持原逻辑即可,补充文件关闭操作避免句柄泄漏
def organize_columns(cols_abs_path):
    crime_file = open(cols_abs_path, "r")
    list_columns = []
    string_crime = crime_file.read().split('\n')
    for i in range(len(string_crime)):
        if len(string_crime[i]) > 10:
            if string_crime[i][0:10] == "@attribute":
                att_line_splitted = string_crime[i].split(' ')
                if len(att_line_splitted) >= 2:
                    list_columns += [str(att_line_splitted[1])]
    crime_file.close()
    return list_columns


def get_data(data_file_abs_path1):
    return np.loadtxt(data_file_abs_path1, dtype=str, delimiter=',')


if __name__ == '__main__':
    file_path = "/home/daniln/Documents/studies/BigData/ex3_home"
    columns_file_abs_path = file_path + "/communities.names"
    data_file_abs_path = file_path + "/communities.data"
    df_crime1 = prepare_data(data_file_abs_path, columns_file_abs_path)

原有代码的问题说明

你最初想的「替换非法值为NaN再调用dropna删列」的思路本身是可行的,只是写法不符合pandas语法规则:

  1. pandas不支持0 > df_crime > 1这种连续比较写法,必须拆成两个独立判断,用位运算符|(或)、&(且)连接,且每个判断条件要单独加括号
  2. df.loc只接受行、列两个维度的索引参数,你之前传了三个参数会直接报错
  3. 自定义的verify_valid_cols_values、delete_invalid_values_cols函数用了列表推导但没有返回值,也没有原地修改DataFrame,运行后不会产生任何实际效果

如果要沿用你最初的替换+删列思路,可以用mask方法实现非法值替换,代码如下:

# 将所有越界值替换为NaN
df_crime = df_crime.mask((df_crime < 0) | (df_crime > 1), np.nan)
# 直接删除存在NaN的列即可
df_crime = df_crime.dropna(axis=1)

示例DataFrame参考

dataframe示例

内容的提问来源于stack exchange,提问作者dani_l_n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 19:03:41