I boxplot all of my columns with seaborn boxplot in order to know how many outliers that i have, surprisingly there're too many outliers and so i can remove the outliers because i'm afraid with too many outliers it will have bad impact to my model especially impacting the mean,median, variance which will further impact the performance of my model. Then i found this QnA about too many outliers the answer said that the case is not really an outliers. The answer makes sense but i'm still afraid it will give bad impact to the performance of my model. What is the best thing should i do?

These are two of examples of what i mean, 9 out of 10 columns of my data are exactly like this and i'm really worried about this because you see, it's not only there're too many outliers, it also happens in almost every (9 of 10 columns in total) columns.

enter image description here enter image description here


3 Answers 3


If you have lots and lots of missing datapoint in any feature that you are depending on, you final analysis will be pretty weak. Let's say you want to train your model on heights of basketball players and overall scoring on the court. If you have 100 players, and only have heights for 10 players, and nulls for the other 90 players, how accurate do you think the model will be in predicting scores per player. Well, not very accurate.

You can use this small script to find the percentage of nulls, per column/feature, in your entire dataset.

import pandas as pd
import numpy as np

df = pd.read_csv('C:\\your_path\\data.csv')
df_missing = df.isna()
df_num_missing = df_missing.sum()
print(df_num_missing / len(df))
print(df.isna().mean().round(4) * 100)

I don't know what the rule of thumb is, but you probably want to have at least 70% - 80% coverage, at least. Closer to 100% is better!!

For outliers, there are a few things you can do.

Cnsider finding Z-Scores for each column/feature in your dataframe.

cols = list(df.columns)
# now iterate over the remaining columns and create a new zscore column
for col in cols:
    col_zscore = col + '_zscore'
    df[col_zscore] = (df[col] - df[col].mean())/df[col].std(ddof=0)



Kick out records with a Z-Score over a certain threshold.

from scipy import stats
df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]



Also, consider using some kind of scaling or normalization technique to handle those pesky outliers! Which is which? The difference is that, in scaling, you’re changing the range of your data while in normalization you’re changing the shape of the distribution of your data.


from sklearn.preprocessing import StandardScaler
scaler = preprocessing.StandardScaler()
scaled_df = scaler.fit_transform(df)
#[where df=data]

enter image description here


from sklearn import preprocessing
scaler = preprocessing.Normalizer()
scaled_df = scaler.fit_transform(df)

enter image description here

That's a lot to take in. Let's wrap it up very soon. Just one final topic to discuss...

Feature Selection:

#importing libraries
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE
from sklearn.linear_model import RidgeCV, LassoCV, Ridge, Lasso#Loading the dataset
x = load_boston()
df = pd.DataFrame(x.data, columns = x.feature_names)
df["MEDV"] = x.target
X = df.drop("MEDV",1)   #Feature Matrix
y = df["MEDV"]          #Target Variable

reg = LassoCV()
reg.fit(X, y)
print("Best alpha using built-in LassoCV: %f" % reg.alpha_)
print("Best score using built-in LassoCV: %f" %reg.score(X,y))
coef = pd.Series(reg.coef_, index = X.columns)

print("Lasso picked " + str(sum(coef != 0)) + " variables and eliminated the other " +  str(sum(coef == 0)) + " variables")

imp_coef = coef.sort_values()
import matplotlib
matplotlib.rcParams['figure.figsize'] = (8.0, 10.0)
imp_coef.plot(kind = "barh")
plt.title("Feature importance using Lasso Model")

enter image description here







It looks like most of your data is at 0, right? Either:

Those values are not really 0 but 'missing' and should be treated as missing, rather than as 0. If a lot is missing, this will indeed be problematic for models that do not handle these, because you have to infer some value for them. You can't really drop all these if there are a lot. You could impute a mean or pick a model that handles missing values. Or:

The distribution of these values isn't normal/Gaussian, in which case there's no strong reason to believe that values outside the IQR are 'outliers'. In particular looks like it could be exponential, or a mixture of two distributions in the second case. Just use the values as is. For linear models, some transformation of the input might be better, like its log, but depends a lot on what you're doing.

  • $\begingroup$ hello, thank you for your explanation, this is my dataset. Since you mentioned that most of my data is not really 0 but missing, In the data there are 3 columns that have many 0 and the rests are pretty far from 0. Is it the boxplot that's working odd? $\endgroup$ Mar 11, 2020 at 14:48
  • $\begingroup$ Why do you think the 0s mean missing? they don't seem to. The boxplot is fine; it does what it does. Your interpretation of it is incorrect here, I think. $\endgroup$
    – Sean Owen
    Mar 11, 2020 at 15:16
  • $\begingroup$ oh right sorry, i thought Those values are not really 0 but 'missing' and should be treated as missing, rather than as 0 means i can perceive it as missing.. i'm sorry i'm still quite new at this, what do you think the best way to handle this 0s then? impute it with mean? or pick a model that handles missing values? or Just use the values as is? just like you said.. $\endgroup$ Mar 12, 2020 at 3:35
  • $\begingroup$ Why not just accept that they are 0? do nothing. $\endgroup$
    – Sean Owen
    Mar 12, 2020 at 16:09

Another way that I would suggest is to use the Box-Cox transformation

It significantly reduces the number of outliers in your dataset. Please let me know if there are any suggestions/comments for my answer.

from scipy import stats

normalized_data = stats.boxcox(modified_df['Income_of_Applicant'])

# Plot both together to compare
fig, ax=plt.subplots(1,2)
sns.distplot(modified_df['Income_of_Applicant'], ax=ax[0])
ax[0].set_title("Original Data")
sns.distplot(normalized_data[0], ax=ax[1])
ax[1].set_title("Normalized data")

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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