Введение

Этот отчет показывает ход и результаты выполнения лабораторной работы №4 по дисциплине «Анализ данных».

Тема лабораторной работы: «Способы подготовки исходных данных».

В работе рассматриваются способы обработки пропущенных значений, удаления выбросов, удаления дубликатов, заполнения пропусков с помощью пакетов caret и mice, а также пример анализа мультиколлинеарности.

Установка и подключение компонентов

Перед запуском отчета необходимо один раз установить нужные пакеты в консоли RStudio:

install.packages("caret")
install.packages("mice")
install.packages("car")

Подключим необходимые библиотеки:

library(caret)
library(mice)
library(car)

Задание №1

Условие

Сформировать собственный датасет с помощью функции c(), в котором содержатся числовые данные и значения NA.

Выполнение задания

my_data <- c(10, 20, NA, 30, 40, NA, 50)

my_data
## [1] 10 20 NA 30 40 NA 50

Вывод по заданию №1

Был создан числовой вектор my_data, содержащий обычные числовые значения и пропущенные значения NA. Такой набор данных можно использовать для демонстрации способов поиска и обработки пропусков.

Задание №2

Условие

Провести очистку данных с использованием функции is.na() и вывести «чистый» датасет.

Выполнение задания

na_positions <- is.na(my_data)

na_positions
## [1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE
clean_data <- my_data[!na_positions]

clean_data
## [1] 10 20 30 40 50

Вывод по заданию №2

Функция is.na() позволяет определить, в каких позициях находятся пропущенные значения. После этого с помощью логической индексации были удалены элементы NA.

В результате был получен очищенный вектор, содержащий только числовые значения: 10, 20, 30, 40, 50.

Задание №3

Условие

Сгенерировать таблицу данных с числовыми и текстовыми столбцами с помощью функции c(). Очистить данные с помощью функции complete.cases().

Выполнение задания

my_table <- data.frame(
  numbers = c(1, 2, 3, NA, 5),
  text = c("A", NA, "C", "D", "E")
)

my_table
##   numbers text
## 1       1    A
## 2       2 <NA>
## 3       3    C
## 4      NA    D
## 5       5    E
clean_table <- my_table[complete.cases(my_table), ]

clean_table
##   numbers text
## 1       1    A
## 3       3    C
## 5       5    E

Вывод по заданию №3

Функция complete.cases() определяет строки, в которых нет пропущенных значений. С ее помощью из таблицы были удалены строки, содержащие NA.

В результате остались только полностью заполненные строки таблицы.

Задание №4

Условие

Проанализировать датасет airquality с пропусками. С использованием функции preProcess() из пакета caret заполнить пропуски предсказанными значениями: средним и медианой.

Выполнение задания

data(airquality)

head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
colSums(is.na(airquality))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##      37       7       0       0       0       0

Заполнение пропусков средними значениями

airquality_mean <- airquality

airquality_mean$Ozone[is.na(airquality_mean$Ozone)] <- 
  mean(airquality$Ozone, na.rm = TRUE)

airquality_mean$Solar.R[is.na(airquality_mean$Solar.R)] <- 
  mean(airquality$Solar.R, na.rm = TRUE)

head(airquality_mean)
##      Ozone  Solar.R Wind Temp Month Day
## 1 41.00000 190.0000  7.4   67     5   1
## 2 36.00000 118.0000  8.0   72     5   2
## 3 12.00000 149.0000 12.6   74     5   3
## 4 18.00000 313.0000 11.5   62     5   4
## 5 42.12931 185.9315 14.3   56     5   5
## 6 28.00000 185.9315 14.9   66     5   6
colSums(is.na(airquality_mean))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##       0       0       0       0       0       0

Заполнение пропусков медианными значениями

preproc_median <- preProcess(airquality, method = "medianImpute")

airquality_median <- predict(preproc_median, airquality)

head(airquality_median)
##   Ozone Solar.R Wind Temp Month Day
## 1  41.0     190  7.4   67     5   1
## 2  36.0     118  8.0   72     5   2
## 3  12.0     149 12.6   74     5   3
## 4  18.0     313 11.5   62     5   4
## 5  31.5     205 14.3   56     5   5
## 6  28.0     205 14.9   66     5   6
colSums(is.na(airquality_median))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##       0       0       0       0       0       0

Вывод по заданию №4

В исходном датасете airquality были обнаружены пропуски в столбцах Ozone и Solar.R.

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

При заполнении медианой пропуски заменяются медианным значением. Этот способ часто является более устойчивым, так как медиана меньше зависит от выбросов.

После обработки в обоих вариантах пропущенные значения были устранены.

Задание №5

Условие

Сгенерировать два числовых набора данных и добавить в них выбросы. С использованием функции boxplot() обнаружить выбросы и удалить их.

Выполнение задания

set1 <- c(1, 2, 3, 4, 123)
set2 <- c(10, 20, 30, 40, 250)
boxplot(set1, main = "Set 1")

boxplot(set2, main = "Set 2")

outliers_set1 <- boxplot.stats(set1)$out
outliers_set2 <- boxplot.stats(set2)$out

outliers_set1
## [1] 123
outliers_set2
## [1] 250
clean_set1 <- set1[!set1 %in% outliers_set1]
clean_set2 <- set2[!set2 %in% outliers_set2]

clean_set1
## [1] 1 2 3 4
clean_set2
## [1] 10 20 30 40

Вывод по заданию №5

В первом наборе данных выбросом является значение 123, а во втором наборе данных выбросом является значение 250.

С помощью функции boxplot() выбросы были визуально обнаружены, а с помощью boxplot.stats() были получены их значения. После удаления выбросов остались очищенные наборы данных.

Задание №6

Условие

Сгенерировать таблицу данных, в которой дублируются строки. Удалить строки с использованием функций unique() и duplicated(). Сравнить результаты.

Выполнение задания

dup_table <- data.frame(
  col1 = c(1, 2, 3, 3, 2, 1),
  col2 = c("A", "B", "C", "C", "B", "A")
)

dup_table
##   col1 col2
## 1    1    A
## 2    2    B
## 3    3    C
## 4    3    C
## 5    2    B
## 6    1    A

Удаление дубликатов с помощью unique()

unique_table <- unique(dup_table)

unique_table
##   col1 col2
## 1    1    A
## 2    2    B
## 3    3    C

Удаление дубликатов с помощью duplicated()

no_dup_table <- dup_table[!duplicated(dup_table), ]

no_dup_table
##   col1 col2
## 1    1    A
## 2    2    B
## 3    3    C

Вывод по заданию №6

Функция unique() сразу возвращает таблицу без повторяющихся строк. Это простой и удобный способ быстро удалить дубликаты.

Функция duplicated() показывает, какие строки являются повторными. В сочетании с логическим отрицанием ! она позволяет оставить только первые вхождения строк.

Оба способа дали одинаковый итоговый результат, но duplicated() дает больше контроля над процессом отбора строк.

Задание №7

Условие

Обработать пропуски в данных с использованием пакета mice.

Выполнение задания

data(airquality)

imp <- mice(
  airquality,
  m = 2,
  maxit = 10,
  method = "pmm",
  seed = 123,
  printFlag = FALSE
)
airquality_mice <- complete(imp)

head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
head(airquality_mice)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5     6     273 14.3   56     5   5
## 6    28     186 14.9   66     5   6
colSums(is.na(airquality_mice))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##       0       0       0       0       0       0

Вывод по заданию №7

Пакет mice используется для обработки пропущенных значений методом множественной импутации. В отличие от простой замены пропусков средним или медианой, метод mice учитывает связь между переменными.

В данном случае использовался метод pmm. После обработки все пропуски в датасете были заполнены.

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

Задание №8

Условие

Разобрать пример с мультиколлинеарностью.

Выполнение задания

set.seed(123)

x1 <- rnorm(100)
x2 <- x1 * 2 + rnorm(100, 0, 0.1)
y <- 3 * x1 + 2 * x2 + rnorm(100)

data_mc <- data.frame(y, x1, x2)

head(data_mc)
##            y          x1         x2
## 1 -1.8666005 -0.56047565 -1.1919919
## 2 -0.2474527 -0.23017749 -0.4346666
## 3 10.5964748  1.55870831  3.0927474
## 4  0.9672443  0.07050839  0.1062625
## 5  0.3003505  0.12928774  0.1634136
## 6 11.5202025  1.71506499  3.4256272
cor_matrix <- cor(data_mc)

cor_matrix
##            y        x1        x2
## y  1.0000000 0.9882897 0.9887106
## x1 0.9882897 1.0000000 0.9985963
## x2 0.9887106 0.9985963 1.0000000
model <- lm(y ~ x1 + x2, data = data_mc)

summary(model)
## 
## Call:
## lm(formula = y ~ x1 + x2, data = data_mc)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.8730 -0.6607 -0.1245  0.6214  2.0798 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  0.13507    0.09614   1.405    0.163  
## x1           2.39060    1.97748   1.209    0.230  
## x2           2.23811    0.98995   2.261    0.026 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9513 on 97 degrees of freedom
## Multiple R-squared:  0.9779, Adjusted R-squared:  0.9774 
## F-statistic:  2144 on 2 and 97 DF,  p-value: < 2.2e-16
vif(model)
##       x1       x2 
## 356.4434 356.4434

Вывод по заданию №8

В примере были созданы две переменные x1 и x2, между которыми существует очень сильная связь. Переменная x2 была специально сформирована на основе x1, поэтому между ними возникает мультиколлинеарность.

Корреляционная матрица показывает, что признаки x1 и x2 сильно коррелируют друг с другом. После построения линейной регрессии был рассчитан показатель VIF.

VIF показывает, насколько увеличивается дисперсия коэффициента из-за мультиколлинеарности. Чем выше значение VIF, тем сильнее проблема мультиколлинеарности.

В данном примере значения VIF получились очень высокими, поэтому можно сделать вывод, что между признаками есть сильная мультиколлинеарность.

Задание №9

Условие

Всю представленную работу собрать в единый отчет с формулировкой задания, кодом и скриншотами выполнения.

Выполнение задания

Работа была оформлена в виде единого файла RMarkdown. В отчете представлены формулировки заданий, программный код, результаты выполнения и выводы.

После выполнения команды Knit можно получить HTML-файл отчета. Далее его можно опубликовать на RPubs.

Для публикации необходимо нажать кнопку Publish, выбрать сервис RPubs, указать название и описание публикации, после чего скопировать полученную ссылку.

Общий вывод по лабораторной работе

В результате выполнения лабораторной работы были закреплены навыки предварительной подготовки данных в языке R.

Были рассмотрены следующие операции:

Лабораторная работа показала, что подготовка исходных данных является важным этапом анализа. От качества очистки данных зависит корректность дальнейших расчетов и выводов.