Пропущенные значения

С самого первого занятия мы с вами говорили про пропущенные значения. В R они отображаются как NA. В реальных данных часто приходится сталкиваться с ними. Например, если проводить опрос людей, то некоторые не захотят говорить о своей заработной плате. Это и есть пропущенное значение.

Базовая работа с пропущенными значениями

Мы уже знаем функцию is.na. Она выдает логический ответ на вопрос: “Является ли значение пропущенным?”. Она может работать с массивами.

## [1] FALSE  TRUE FALSE  TRUE  TRUE FALSE

Но есть и другие инструменты. Они находятся в пакете naniar. Давайте установим и подгрузим его и остальные пакеты.

Наши переменные в наборе данных это массивы. И всегда хочется узнать, есть ли пропущенные значения в этой переменной. Для этого можно использовать функцию any_na. Она выдает логический ответ на вопрос: “Есть ли в массиве пропущенные значения?”

Если пропущенные значения есть, то хотелось бы знать их количество, а лучше долю.

NaN считается пропущенным значением, а бесконечность Inf не считается.

Будет использовать функцию для генерации массива с пропущенными значениями.

Сгенерим набор данных с 3 переменными.

С помощью функции n_miss можно узнать количество пропущенных значений во всем наборе данных или в отдельной переменной.

Обратная функция n_complete показывает сколько значений у нас есть о всем наборе данных или в отдельной переменной.

А функции prop_miss и prop_complete показывают долю пропущенных и имеющихся значений.

Различные статистики для пропущенных значений

Не хотелось бы использовать эти функции в случае, когда у нас много переменныех. Есть готовые решения для этого. Функция miss_var_summary показывает статистику для переменных, а функция miss_case_summary для наблюдений. Давайте попробуем эти функции на датасете airquality из пакета naniar.

## Observations: 153
## Variables: 6
## $ Ozone   <int> 41, 36, 12, 18, NA, 28, 23, 19, 8, NA, 7, 16, 11, 14, 18…
## $ Solar.R <int> 190, 118, 149, 313, NA, NA, 299, 99, 19, 194, NA, 256, 2…
## $ Wind    <dbl> 7.4, 8.0, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, …
## $ Temp    <int> 67, 72, 74, 62, 56, 66, 65, 59, 61, 69, 74, 69, 66, 68, …
## $ Month   <int> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,…
## $ Day     <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1…

Функция miss_var_summary выдает tibble- фрейм в котором есть переменные:

  • variable – переменная
  • n_miss – количество пропущенных значений
  • pct_miss – процент пропущенных значений

Такой фрейм отсортирован по столбцу n_miss.

## # A tibble: 6 x 3
##   variable n_miss pct_miss
##   <chr>     <int>    <dbl>
## 1 Ozone        37    24.2 
## 2 Solar.R       7     4.58
## 3 Wind          0     0   
## 4 Temp          0     0   
## 5 Month         0     0   
## 6 Day           0     0

Функция miss_case_summary выдает tibble- фрейм в котором есть переменные:

  • case – номер наблюдения
  • n_miss – количество пропущенных значений
  • pct_miss – процент пропущенных значений

Такой фрейм так же отсортирован по столбцу n_miss.

## # A tibble: 153 x 3
##     case n_miss pct_miss
##    <int>  <int>    <dbl>
##  1     5      2     33.3
##  2    27      2     33.3
##  3     6      1     16.7
##  4    10      1     16.7
##  5    11      1     16.7
##  6    25      1     16.7
##  7    26      1     16.7
##  8    32      1     16.7
##  9    33      1     16.7
## 10    34      1     16.7
## # … with 143 more rows

Эти функции можно применять с pipe’ом (%>%).

## # A tibble: 25 x 4
## # Groups:   Month [5]
##    Month variable n_miss pct_miss
##    <int> <chr>     <int>    <dbl>
##  1     5 Ozone         5     16.1
##  2     5 Solar.R       4     12.9
##  3     5 Wind          0      0  
##  4     5 Temp          0      0  
##  5     5 Day           0      0  
##  6     6 Ozone        21     70  
##  7     6 Solar.R       0      0  
##  8     6 Wind          0      0  
##  9     6 Temp          0      0  
## 10     6 Day           0      0  
## # … with 15 more rows
## # A tibble: 153 x 4
## # Groups:   Month [5]
##    Month  case n_miss pct_miss
##    <int> <int>  <int>    <dbl>
##  1     5     5      2       40
##  2     5    27      2       40
##  3     5     6      1       20
##  4     5    10      1       20
##  5     5    11      1       20
##  6     5    25      1       20
##  7     5    26      1       20
##  8     5     1      0        0
##  9     5     2      0        0
## 10     5     3      0        0
## # … with 143 more rows

Функции miss_var_table и miss_case_table дают более общую информацию. Например, первая показывает количество переменных, в которых нет пропущенных значений или есть определенное количество.

## # A tibble: 3 x 3
##   n_miss_in_var n_vars pct_vars
##           <int>  <int>    <dbl>
## 1             0      4     66.7
## 2             7      1     16.7
## 3            37      1     16.7
## # A tibble: 3 x 3
##   n_miss_in_case n_cases pct_cases
##            <int>   <int>     <dbl>
## 1              0     111     72.5 
## 2              1      40     26.1 
## 3              2       2      1.31

Эти функции так же можно использовать с pipe’ом (%>%).

## # A tibble: 12 x 4
## # Groups:   Month [5]
##    Month n_miss_in_var n_vars pct_vars
##    <int>         <int>  <int>    <dbl>
##  1     5             0      3       60
##  2     5             4      1       20
##  3     5             5      1       20
##  4     6             0      4       80
##  5     6            21      1       20
##  6     7             0      4       80
##  7     7             5      1       20
##  8     8             0      3       60
##  9     8             3      1       20
## 10     8             5      1       20
## 11     9             0      4       80
## 12     9             1      1       20
## # A tibble: 11 x 4
## # Groups:   Month [5]
##    Month n_miss_in_case n_cases pct_cases
##    <int>          <int>   <int>     <dbl>
##  1     5              0      24     77.4 
##  2     5              1       5     16.1 
##  3     5              2       2      6.45
##  4     6              0       9     30   
##  5     6              1      21     70   
##  6     7              0      26     83.9 
##  7     7              1       5     16.1 
##  8     8              0      23     74.2 
##  9     8              1       8     25.8 
## 10     9              0      29     96.7 
## 11     9              1       1      3.33

Также есть функции miss_var_span и miss_var_run, которые можно изучить дополнительно.

Визуализация пропущенных значений

Функция vis_miss

Эта функция позволяет в прямом смысле посмотреть на ваши данные и на пропущенные значения.

Чтобы как-то сгрупиировать пропущенные значения можно установить параметр cluster.

Попробуем использовать эту функцию на датасете riskfactors, в котором больше переменных.

Можно так же отсортировать столбцы по количеству пропущенных значений с помощью параметра sort.

Функции gg_miss_var и gg_miss_case

Эти функции показывают наглядно количество пропущенных значений в виде гистограмм.

С помощью параметра facet можно посмотреть эти графики в разрезе группы.

Функции gg_miss_upset и gg_miss_fct

Функция gg_miss_upset показывает количество пропущенных значений для различных комбинаций переменных.

Функция gg_miss_fct позволяет увидеть в каких группах и по каким переменным пропущенных значений больше.

Что делать с пропущенными значениями

Рассмотрим разные случаи при работе с пропущенными значениями.

Cлучай №1

Сгенерим набор данных, в котором будет один столбец иметь много пропущенных значений.

C помощью функции miss_var_summary и vis_miss посмотрим какие переменные имеют пропущенные значения.

## # A tibble: 3 x 3
##   variable n_miss pct_miss
##   <chr>     <int>    <dbl>
## 1 z           701     70.1
## 2 x             0      0  
## 3 y             0      0

Видно, что в переменной z \(70.2\)% значений пропущены. В таких ситуациях лучше удалить всю такую переменную.

Cлучай №2

Сгенерим набор данных, в котором будет небольшое количество пропущенных значений во всех переменных.

C помощью функции miss_var_summary и vis_miss посмотрим какие переменные имеют пропущенные значения.

## # A tibble: 3 x 3
##   variable n_miss pct_miss
##   <chr>     <int>    <dbl>
## 1 y            74      7.4
## 2 x            42      4.2
## 3 z            20      2

В данному случае удалять переменные не логично. Можно удалить переменные, которые содержат пропущенные значения. Найдем количество таких наблюдений с помощью функции miss_case_summary.

## # A tibble: 1 x 1
##       n
##   <int>
## 1   128

Таких наблюдений 131. Удалим их все с помощью функции drop_na из пакета dplyr.

Cлучай №3

В прошлом случае мы удалили 131 наблюдение. Данные очень ценный ресурс для построения моделей, поэтому нужно стараться не удалять их. Но для этого нужно заменить пропущенные значения какими-то дуругими значениями.

Замена средним

## # A tibble: 10 x 2
##         x     y
##     <dbl> <dbl>
##  1 -100    11.1
##  2  -11.1  55.6
##  3   NA   -33.3
##  4   33.3 -55.6
##  5   55.6 -55.6
##  6   NA   100  
##  7  -11.1  NA  
##  8   NA   -33.3
##  9  -33.3  NA  
## 10   NA   -11.1
## [1] -11.1111
##  [1] -100.0000  -11.1111  -11.1111   33.3333   55.5556  -11.1111  -11.1111
##  [8]  -11.1111  -33.3333  -11.1111
## # A tibble: 10 x 2
##         x      y
##     <dbl>  <dbl>
##  1 -100    11.1 
##  2  -11.1  55.6 
##  3  -11.1 -33.3 
##  4   33.3 -55.6 
##  5   55.6 -55.6 
##  6  -11.1 100   
##  7  -11.1  -2.78
##  8  -11.1 -33.3 
##  9  -33.3  -2.78
## 10  -11.1 -11.1
## # A tibble: 10 x 2
##         x     y
##     <dbl> <dbl>
##  1 -100    11.1
##  2  -11.1  55.6
##  3  -11.1 -33.3
##  4   33.3 -55.6
##  5   55.6 -55.6
##  6  -11.1 100  
##  7  -11.1  NA  
##  8  -11.1 -33.3
##  9  -33.3  NA  
## 10  -11.1 -11.1
## # A tibble: 10 x 2
##         x      y
##     <dbl>  <dbl>
##  1 -100    11.1 
##  2  -11.1  55.6 
##  3  -11.1 -33.3 
##  4   33.3 -55.6 
##  5   55.6 -55.6 
##  6  -11.1 100   
##  7  -11.1  -2.78
##  8  -11.1 -33.3 
##  9  -33.3  -2.78
## 10  -11.1 -11.1

Замена медианой

## [1] -11.1111
##  [1] -100.0000  -11.1111  -11.1111   33.3333   55.5556  -11.1111  -11.1111
##  [8]  -11.1111  -33.3333  -11.1111
## # A tibble: 10 x 2
##         x     y
##     <dbl> <dbl>
##  1 -100    11.1
##  2  -11.1  55.6
##  3  -11.1 -33.3
##  4   33.3 -55.6
##  5   55.6 -55.6
##  6  -11.1 100  
##  7  -11.1 -22.2
##  8  -11.1 -33.3
##  9  -33.3 -22.2
## 10  -11.1 -11.1
## # A tibble: 10 x 2
##         x     y
##     <dbl> <dbl>
##  1 -100    11.1
##  2  -11.1  55.6
##  3  -11.1 -33.3
##  4   33.3 -55.6
##  5   55.6 -55.6
##  6  -11.1 100  
##  7  -11.1  NA  
##  8  -11.1 -33.3
##  9  -33.3  NA  
## 10  -11.1 -11.1
## # A tibble: 10 x 2
##         x     y
##     <dbl> <dbl>
##  1 -100    11.1
##  2  -11.1  55.6
##  3  -11.1 -33.3
##  4   33.3 -55.6
##  5   55.6 -55.6
##  6  -11.1 100  
##  7  -11.1 -22.2
##  8  -11.1 -33.3
##  9  -33.3 -22.2
## 10  -11.1 -11.1

Индикатор пропущенной переменной

Если мы заменяем пропущенное значение средним или медианой, мы в какой-то степени ошибаемся, так как истинное значение могло быть совершенно другим. Чтобы это не мешало модели, можно ввести переменную-индикатор, которая будет равняться 1, если значение заменено.

Можно использовать следующую функцию.

Можно использовать даже с pipe :)

## # A tibble: 10 x 4
##         x     y x_IND y_IND
##     <dbl> <dbl> <dbl> <dbl>
##  1 -100    11.1     0     0
##  2  -11.1  55.6     0     0
##  3  -11.1 -33.3     1     0
##  4   33.3 -55.6     0     0
##  5   55.6 -55.6     0     0
##  6  -11.1 100       1     0
##  7  -11.1 -22.2     0     1
##  8  -11.1 -33.3     1     0
##  9  -33.3 -22.2     0     1
## 10  -11.1 -11.1     1     0