使用dropna后数据集为空,如何不借助fillna去除NaN值适配RandomForest?
解决方案:避免
dropna()导致数据集为空的处理方法 你当前的核心问题有两个:
- 先基于原始数据计算
training_size,但后续处理缺失值后数据长度大幅缩短,导致拆分逻辑失效 - 直接使用无参数的
dropna()会删除任何包含NaN的行,加上shift(-1)生成的最后一行NaN,最终把所有数据删空
以下是无需使用fillna()的处理方案:
1. 针对性过滤缺失值,而非全量删除
不要直接调用无参数的dropna(),而是指定只过滤关键列的缺失值,保留尽可能多的有效数据:
query = f"SELECT * FROM {HISTORICAL_TABLE}" historical_data = pd.read_sql(query, conn) # 先过滤特征列和Close列的Null值(只删这些列有Null的行) features = [...] # 你的特征列表 historical_data = historical_data.dropna(subset=features + ['Close']) # 生成Next_Close,此时仅最后一行会有NaN historical_data = historical_data.assign(Next_Close=historical_data['Close'].shift(-1)) # 单独删除最后一行的NaN,而非全量dropna historical_data = historical_data.iloc[:-1] # 现在再根据处理后的数据拆分训练测试集 training_size = int(len(historical_data) * 0.6) train = historical_data.iloc[:training_size] test = historical_data.iloc[training_size:] # 后续的特征缩放逻辑不变 X_train = train[features] X_test = test[features] y_train = train['Next_Close'] y_test = test['Next_Close'] scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test)
2. 在SQL层面提前过滤缺失值
从数据源直接过滤掉含Null的行,减少后续处理的压力:
features = [...] # 你的特征列表 # 拼接需要保留的列(特征+Close) target_columns = ', '.join(features + ['Close']) # 构造SQL过滤条件:所有指定列都非Null filter_conditions = ' AND '.join([f'{col} IS NOT NULL' for col in features + ['Close']]) query = f"SELECT {target_columns} FROM {HISTORICAL_TABLE} WHERE {filter_conditions}" historical_data = pd.read_sql(query, conn) # 生成Next_Close并删除最后一行NaN historical_data = historical_data.assign(Next_Close=historical_data['Close'].shift(-1)) historical_data = historical_data.iloc[:-1] # 拆分训练测试集 training_size = int(len(historical_data) * 0.6) train = historical_data.iloc[:training_size] test = historical_data.iloc[training_size:] # 后续缩放逻辑不变
3. 先清理无效空列
如果某些列的Null占比极高,直接删除这些列,减少缺失值对行过滤的影响:
query = f"SELECT * FROM {HISTORICAL_TABLE}" historical_data = pd.read_sql(query, conn) # 删除非Null值占比低于50%的列(可根据需求调整阈值) threshold = len(historical_data) * 0.5 historical_data = historical_data.dropna(axis=1, thresh=threshold) # 再过滤行的缺失值 historical_data = historical_data.dropna(subset=historical_data.columns) # 生成Next_Close并删除最后一行 historical_data = historical_data.assign(Next_Close=historical_data['Close'].shift(-1)) historical_data = historical_data.iloc[:-1] # 拆分训练测试集 training_size = int(len(historical_data) * 0.6) train = historical_data.iloc[:training_size] test = historical_data.iloc[training_size:] # 后续缩放逻辑不变
关键注意点
- 必须先处理完所有缺失值,再计算训练集大小并拆分,否则原始数据长度和处理后的数据长度不匹配,会导致拆分逻辑失效
- 避免无差别使用
dropna(),要针对关键列或高占比Null列做针对性处理,保留尽可能多的有效数据
内容的提问来源于stack exchange,提问作者ridhamb
相关产品推荐
相关产品推荐

