0
$\begingroup$

I have data 14581 obs. of 45 variables that contains missing values:

> apply(is.na(tabular_data), 2, sum)
PERIOD     ID    V_1    V_2    V_3    V_4    V_5    V_6    V_7    V_8    V_9   V_10   V_11   V_12   V_13 
     0      0   1395   1405   1439   1396   1352   1345   1388   1460   1416   1385   1391   1435   1440 
  V_14   V_15   V_16   V_17   V_18   V_19   V_20   V_21   V_22   V_23   V_24   V_25   V_26   V_27   V_28 
  1414   1427   1458   1446   1459   1410   1416   1436   1420   1377   1433   1397   1419   1453   1405 
  V_29   V_30   V_31   V_32   V_33   V_34   V_35   V_36   V_37   V_38   V_39   V_40   V_41   V_42   V_43 
  1385   1449   1453   1439   1417   1411   1464   1341   1370   1418   1391   1434   1386   1429   1421

I want to make a binary classification based on such data. How to approach this task correctly? For example, should I try to eliminate all missing values, or better use classification methods that are resistant to missing values?

UPD:

I tried to use na.omit(tabular_data) to remove missing values. The result significantly reduced the training sample, so this is not a solution.

> dim(na.omit(tabular_data))
[1] 177  45
$\endgroup$
6
  • 1
    $\begingroup$ Since the numbers of missing observations per feature are somewhat close you could check if it's actually mostly the same instances missing most feature observations. Those instances might need to be excluded. If that's not the case, imputation could be considered. $\endgroup$
    – deemel
    Commented Dec 20, 2019 at 22:49
  • $\begingroup$ @deemel thanks for the tip, but removing missing values is not a solution. $\endgroup$
    – Vitalii
    Commented Dec 21, 2019 at 16:45
  • $\begingroup$ You can choose between imputation methods and algorithms that internally deal with missing input (most gradient boosting algos). $\endgroup$
    – Michael M
    Commented Dec 21, 2019 at 16:47
  • $\begingroup$ @MichaelM thank you very much for the excellent advice! I will be very glad if you advise me on literature or some tutorial on the Internet about this topic. $\endgroup$
    – Vitalii
    Commented Dec 21, 2019 at 16:58
  • $\begingroup$ What is the ultimate goal of your analysis? Is it e.g. to predict things, or to estimate effects, or to calculate p values? $\endgroup$
    – Michael M
    Commented Dec 21, 2019 at 17:57

1 Answer 1

0
$\begingroup$

The options

Since you are interested in predictions only, your two natural options are:

1) Use a method that deals with missing values internally. Drawback: This limits the choice of the model (-> mostly tree-based models). Advantage: It will also work in model application, i.e. when predicting new observations e.g. if running on a web service.

2) Replace missing values first by some univariate or multivariate imputation method and afterward use your model approach of choice. Drawback and advantage are just the other way round as for Option 1).

Illustration

library(missRanger)
library(gbm)

#============================================
# A) Prepare data set with missings
#============================================

# Download red wine quality data
head(raw <- read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", 
                     sep = ";"))

# Our binary response and covariable names
raw$quality <- raw$quality > 5
y <- "quality"
x <- setdiff(names(raw), y)

# Add missings in all variables except the response
set.seed(435)
prop_missings <- setNames(rep(0.05, length(x)), x)
head(raw_with_NA <- generateNA(raw, p = prop_missings))
colMeans(is.na(raw_with_NA))

# For Option 1), use a package like 'gbm', 'xgboost', or 'lightgbm' that internally deals with missing values.
fit_gbm <- gbm(quality ~ ., data = prep, distribution = "bernoulli", 
               interaction.depth = 5, shrinkage = 0.1, n.trees = 400)
# It can be applied to "new" lines with missings
predict(fit_gbm, raw_with_NA[1, ], n.trees = 400, type = "response") # 0.193032

# For Option 2), impute the values including the response, then use your approach of choice.
prep <- missRanger(raw_with_NA, pmm.k = 3, num.trees = 100)
head(prep)
fit_glm <- glm(quality ~ ., data = prep, family = binomial())
# It cannot be applied to "new" lines with missings
predict(fit_glm, raw_with_NA[1, ], type = "response") # NA

For Option 2), check out my vignette on CRAN

$\endgroup$

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.