29
$\begingroup$

I got ValueError when predicting test data using a RandomForest model.

My code:

clf = RandomForestClassifier(n_estimators=10, max_depth=6, n_jobs=1, verbose=2)
clf.fit(X_fit, y_fit)

df_test.fillna(df_test.mean())
X_test = df_test.values  
y_pred = clf.predict(X_test)

The error:

ValueError: Input contains NaN, infinity or a value too large for dtype('float32').

How do I find the bad values in the test dataset? Also, I do not want to drop these records, can I just replace them with the mean or median?

Thanks.

$\endgroup$
32
$\begingroup$

With np.isnan(X) you get a boolean mask back with True for positions containing NaNs.

With np.where(np.isnan(X)) you get back a tuple with i, j coordinates of NaNs.

Finally, with np.nan_to_num(X) you "replace nan with zero and inf with finite numbers".

Alternatively, you can use:

  • sklearn.preprocessing.Imputer for mean / median imputation of missing values, or
  • pandas' pd.DataFrame(X).fillna(), if you need something other than filling it with zeros.
$\endgroup$
  • $\begingroup$ I prefer identity condition for checking nan, if x!=x return None, many times np.isnan(x) had failed for me, do not remember the reason $\endgroup$ – Itachi Jul 19 '18 at 6:43
  • 1
    $\begingroup$ It is not advisable to replace NaN values with zeros. NaN values might still have significance in being missing and imputing them with zeros is probably the worst thing you can do and the worst imputation method you use. Not only will you be introducing zeros arbitrarily which might skew your variable but 0 might not even be an acceptable value in your variables, meaning your variable might not have a true zero. $\endgroup$ – hussam May 9 at 20:04
  • $\begingroup$ I realized that I did not provide any guidance. If you want to impute your data either use a rolling average using .rolling() to replace missing value with the mean value of a rolling window. If you want something more robust use module <b>missingpy</b> you can use MissForest for a randomforest based imputation. $\endgroup$ – hussam May 9 at 21:32
7
$\begingroup$

Assuming X_test is a pandas dataframe, you can use DataFrame.fillna to replace the NaN values with the mean:

X_test.fillna(X_test.mean())
$\endgroup$
  • $\begingroup$ X_test is the numpy array. Just updated the df_test in the original question, still got the same error ... $\endgroup$ – Edamame May 26 '16 at 14:56
4
$\begingroup$

For anybody happening across this, to actually modify the original:

X_test.fillna(X_train.mean(), inplace=True)

To overwrite the original:

X_test = X_test.fillna(X_train.mean())

To check if you're in a copy vs a view:

X_test._is_view
$\endgroup$
  • 2
    $\begingroup$ While this is true technically, it's wrong practically. You can't fill the X_test NAs with the X_test mean, because in real life you won't have the X_test mean when you're predicting a sample. You should use the X_train mean because this is the only data you actually have in hand (in 99% of the scenarios) $\endgroup$ – Omri374 Jun 17 '18 at 11:56
3
$\begingroup$

Don't forget

col_mask=df.isnull().any(axis=0) 

Which returns the column names containing np.nan.

row_mask=df.isnull().any(axis=1)

Which return the rows where np.nan appeared. Then by simple indexing you can flag all of your points that are np.nan.

df.iloc[row_mask,col_mask]
$\endgroup$
2
$\begingroup$

I faced similar problem and saw that numpy handles NaN and Inf differently.
Incase if you data has Inf, try this:

np.where(x.values >= np.finfo(np.float64).max)
Where x is my pandas Dataframe 

This will be giving a tuple of location of places where NA values are present.

Incase if your data has Nan, try this:

np.isnan(x.values.any())
$\endgroup$
2
$\begingroup$

Do not forget to check for inf values as well. The only thing that worked for me:

df[df==np.inf]=np.nan
df.fillna(df.mean(), inplace=True)

And even better if you are using sklearn

def replace_missing_value(df, number_features):

    imputer = Imputer(strategy="median")
    df_num = df[number_features]
    imputer.fit(df_num)
    X = imputer.transform(df_num)
    res_def = pd.DataFrame(X, columns=df_num.columns)
    return res_def

When number_features would be an array of the number_features labels, for example:

number_features = ['median_income', 'gdp']
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.