43
$\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$
46
$\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.impute.SimpleImputer 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
7
$\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
4
$\begingroup$

Don't forget

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

Which returns a boolean mask indicating np.nan values.

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.loc[row_mask,col_mask]
$\endgroup$
3
$\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$
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$
1
$\begingroup$

In most cases getting rid of infinite and null values solve this problem.

get rid of infinite values.

df.replace([np.inf, -np.inf], np.nan, inplace=True)

get rid of null values the way you like, specific value such as 999, mean, or create your own function to impute missing values

df.fillna(999, inplace=True)

or

df.fillna(df.mean(), inplace=True)
$\endgroup$
1
$\begingroup$

If your values are larger than float32, try to run some scaler first. It'd be rather unusual to have deviation spanning more than float32.

$\endgroup$
0
$\begingroup$

Here is the code for how to "Replace NaN with zero and infinity with large finite numbers." using numpy.nan_to_num.

df[:] = np.nan_to_num(df)

Also see fernando's answer.

$\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.