В данной лабораторной работе рассматриваются основные методы подготовки данных в языке R: обработка пропусков, удаление выбросов, работа с дубликатами, а также анализ мультиколлинеарности.
options(repos = "https://cran.r-project.org/")
install.packages(c("RANN", "caret", "mice", "car"))
## Устанавливаю пакеты в 'C:/Users/Olekander/AppData/Local/R/win-library/4.5'
## (потому что 'lib' не определено)
## пакет 'RANN' успешно распакован, MD5-суммы проверены
## пакет 'caret' успешно распакован, MD5-суммы проверены
## пакет 'mice' успешно распакован, MD5-суммы проверены
## пакет 'car' успешно распакован, MD5-суммы проверены
##
## Скачанные бинарные пакеты находятся в
## D:\temp\Rtmp6jYY8G\downloaded_packages
library(caret)
## Warning: пакет 'caret' был собран под R версии 4.5.3
## Загрузка требуемого пакета: ggplot2
## Загрузка требуемого пакета: lattice
library(mice)
## Warning: пакет 'mice' был собран под R версии 4.5.3
##
## Присоединяю пакет: 'mice'
## Следующий объект скрыт от 'package:stats':
##
## filter
## Следующие объекты скрыты от 'package:base':
##
## cbind, rbind
library(car)
## Warning: пакет 'car' был собран под R версии 4.5.3
## Загрузка требуемого пакета: carData
## Warning: пакет 'carData' был собран под R версии 4.5.3
## Registered S3 method overwritten by 'car':
## method from
## na.action.merMod lme4
Сформируйте свой собственный датасет с помощью функции c (конкатенация), в котором содержатся числовые данные и NA значения.
# Создаем вектор с числами и NA и выводим его
data1 <- c(10, 20, NA, 40, 50, NA, 70)
data1
## [1] 10 20 NA 40 50 NA 70
Проведите очистку данных с использованием функции is.na() [1]. И выведите “чистый” датасет.
# Проверяем, где находятся NA, создавая вектор с логическими данными, удаляем все NA и выводим измененный вектор
clean_data1 <- data1[!is.na(data1)]
clean_data1
## [1] 10 20 40 50 70
Сгенерируйте таблицу данных с числовыми и текстовые столбцами (аналогично с помощью функции c). Очистите данные с помощью функции complete.cases() [1].
# Создаем таблицу данных с NA среди них, выводим ее, очищаем данные с помощью
# complete.cases()
df <- data.frame(
numbers = c(1, 2, NA, 4, 5),
text = c("A", "B", "C", NA, "E")
)
df
## numbers text
## 1 1 A
## 2 2 B
## 3 NA C
## 4 4 <NA>
## 5 5 E
clean_df <- df[complete.cases(df), ]
#Запятая , означает: [строки, колонки]
#До запятой - условие для отбора строк (только TRUE)
#После запятой - пусто, значит берем все колонки
clean_df
## numbers text
## 1 1 A
## 2 2 B
## 5 5 E
Проанализируйте датасет airquality с пропусками из пакета caret. С использованием функции preProcess из пакета caret заполните пропуски предсказанными значениями (среднее, медиана) [2].
data("airquality")
# Определяем строки с пропусками
ind <- apply(airquality, 1, function(x) sum(is.na(x))) > 0
# Смотрим строки с NA
airquality[ind, ]
## Ozone Solar.R Wind Temp Month Day
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## 10 NA 194 8.6 69 5 10
## 11 7 NA 6.9 74 5 11
## 25 NA 66 16.6 57 5 25
## 26 NA 266 14.9 58 5 26
## 27 NA NA 8.0 57 5 27
## 32 NA 286 8.6 78 6 1
## 33 NA 287 9.7 74 6 2
## 34 NA 242 16.1 67 6 3
## 35 NA 186 9.2 84 6 4
## 36 NA 220 8.6 85 6 5
## 37 NA 264 14.3 79 6 6
## 39 NA 273 6.9 87 6 8
## 42 NA 259 10.9 93 6 11
## 43 NA 250 9.2 92 6 12
## 45 NA 332 13.8 80 6 14
## 46 NA 322 11.5 79 6 15
## 52 NA 150 6.3 77 6 21
## 53 NA 59 1.7 76 6 22
## 54 NA 91 4.6 76 6 23
## 55 NA 250 6.3 76 6 24
## 56 NA 135 8.0 75 6 25
## 57 NA 127 8.0 78 6 26
## 58 NA 47 10.3 73 6 27
## 59 NA 98 11.5 80 6 28
## 60 NA 31 14.9 77 6 29
## 61 NA 138 8.0 83 6 30
## 65 NA 101 10.9 84 7 4
## 72 NA 139 8.6 82 7 11
## 75 NA 291 14.9 91 7 14
## 83 NA 258 9.7 81 7 22
## 84 NA 295 11.5 82 7 23
## 96 78 NA 6.9 86 8 4
## 97 35 NA 7.4 85 8 5
## 98 66 NA 4.6 87 8 6
## 102 NA 222 8.6 92 8 10
## 103 NA 137 11.5 86 8 11
## 107 NA 64 11.5 79 8 15
## 115 NA 255 12.6 75 8 23
## 119 NA 153 5.7 88 8 27
## 150 NA 145 13.2 77 9 27
# Заполнение медианой
pPmI <- preProcess(airquality, method = "medianImpute")
airquality_imp <- predict(pPmI, airquality)
# Сравнение: строки ДО и ПОСЛЕ (медиана)
airquality[ind, ]
## Ozone Solar.R Wind Temp Month Day
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## 10 NA 194 8.6 69 5 10
## 11 7 NA 6.9 74 5 11
## 25 NA 66 16.6 57 5 25
## 26 NA 266 14.9 58 5 26
## 27 NA NA 8.0 57 5 27
## 32 NA 286 8.6 78 6 1
## 33 NA 287 9.7 74 6 2
## 34 NA 242 16.1 67 6 3
## 35 NA 186 9.2 84 6 4
## 36 NA 220 8.6 85 6 5
## 37 NA 264 14.3 79 6 6
## 39 NA 273 6.9 87 6 8
## 42 NA 259 10.9 93 6 11
## 43 NA 250 9.2 92 6 12
## 45 NA 332 13.8 80 6 14
## 46 NA 322 11.5 79 6 15
## 52 NA 150 6.3 77 6 21
## 53 NA 59 1.7 76 6 22
## 54 NA 91 4.6 76 6 23
## 55 NA 250 6.3 76 6 24
## 56 NA 135 8.0 75 6 25
## 57 NA 127 8.0 78 6 26
## 58 NA 47 10.3 73 6 27
## 59 NA 98 11.5 80 6 28
## 60 NA 31 14.9 77 6 29
## 61 NA 138 8.0 83 6 30
## 65 NA 101 10.9 84 7 4
## 72 NA 139 8.6 82 7 11
## 75 NA 291 14.9 91 7 14
## 83 NA 258 9.7 81 7 22
## 84 NA 295 11.5 82 7 23
## 96 78 NA 6.9 86 8 4
## 97 35 NA 7.4 85 8 5
## 98 66 NA 4.6 87 8 6
## 102 NA 222 8.6 92 8 10
## 103 NA 137 11.5 86 8 11
## 107 NA 64 11.5 79 8 15
## 115 NA 255 12.6 75 8 23
## 119 NA 153 5.7 88 8 27
## 150 NA 145 13.2 77 9 27
airquality_imp[ind, ]
## Ozone Solar.R Wind Temp Month Day
## 5 31.5 205 14.3 56 5 5
## 6 28.0 205 14.9 66 5 6
## 10 31.5 194 8.6 69 5 10
## 11 7.0 205 6.9 74 5 11
## 25 31.5 66 16.6 57 5 25
## 26 31.5 266 14.9 58 5 26
## 27 31.5 205 8.0 57 5 27
## 32 31.5 286 8.6 78 6 1
## 33 31.5 287 9.7 74 6 2
## 34 31.5 242 16.1 67 6 3
## 35 31.5 186 9.2 84 6 4
## 36 31.5 220 8.6 85 6 5
## 37 31.5 264 14.3 79 6 6
## 39 31.5 273 6.9 87 6 8
## 42 31.5 259 10.9 93 6 11
## 43 31.5 250 9.2 92 6 12
## 45 31.5 332 13.8 80 6 14
## 46 31.5 322 11.5 79 6 15
## 52 31.5 150 6.3 77 6 21
## 53 31.5 59 1.7 76 6 22
## 54 31.5 91 4.6 76 6 23
## 55 31.5 250 6.3 76 6 24
## 56 31.5 135 8.0 75 6 25
## 57 31.5 127 8.0 78 6 26
## 58 31.5 47 10.3 73 6 27
## 59 31.5 98 11.5 80 6 28
## 60 31.5 31 14.9 77 6 29
## 61 31.5 138 8.0 83 6 30
## 65 31.5 101 10.9 84 7 4
## 72 31.5 139 8.6 82 7 11
## 75 31.5 291 14.9 91 7 14
## 83 31.5 258 9.7 81 7 22
## 84 31.5 295 11.5 82 7 23
## 96 78.0 205 6.9 86 8 4
## 97 35.0 205 7.4 85 8 5
## 98 66.0 205 4.6 87 8 6
## 102 31.5 222 8.6 92 8 10
## 103 31.5 137 11.5 86 8 11
## 107 31.5 64 11.5 79 8 15
## 115 31.5 255 12.6 75 8 23
## 119 31.5 153 5.7 88 8 27
## 150 31.5 145 13.2 77 9 27
# Заполнение средним (ручной способ, так как meanImpute отсутствует в caret)
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)
# Сравнение строк после заполнения средним
airquality_mean[ind, ]
## Ozone Solar.R Wind Temp Month Day
## 5 42.12931 185.9315 14.3 56 5 5
## 6 28.00000 185.9315 14.9 66 5 6
## 10 42.12931 194.0000 8.6 69 5 10
## 11 7.00000 185.9315 6.9 74 5 11
## 25 42.12931 66.0000 16.6 57 5 25
## 26 42.12931 266.0000 14.9 58 5 26
## 27 42.12931 185.9315 8.0 57 5 27
## 32 42.12931 286.0000 8.6 78 6 1
## 33 42.12931 287.0000 9.7 74 6 2
## 34 42.12931 242.0000 16.1 67 6 3
## 35 42.12931 186.0000 9.2 84 6 4
## 36 42.12931 220.0000 8.6 85 6 5
## 37 42.12931 264.0000 14.3 79 6 6
## 39 42.12931 273.0000 6.9 87 6 8
## 42 42.12931 259.0000 10.9 93 6 11
## 43 42.12931 250.0000 9.2 92 6 12
## 45 42.12931 332.0000 13.8 80 6 14
## 46 42.12931 322.0000 11.5 79 6 15
## 52 42.12931 150.0000 6.3 77 6 21
## 53 42.12931 59.0000 1.7 76 6 22
## 54 42.12931 91.0000 4.6 76 6 23
## 55 42.12931 250.0000 6.3 76 6 24
## 56 42.12931 135.0000 8.0 75 6 25
## 57 42.12931 127.0000 8.0 78 6 26
## 58 42.12931 47.0000 10.3 73 6 27
## 59 42.12931 98.0000 11.5 80 6 28
## 60 42.12931 31.0000 14.9 77 6 29
## 61 42.12931 138.0000 8.0 83 6 30
## 65 42.12931 101.0000 10.9 84 7 4
## 72 42.12931 139.0000 8.6 82 7 11
## 75 42.12931 291.0000 14.9 91 7 14
## 83 42.12931 258.0000 9.7 81 7 22
## 84 42.12931 295.0000 11.5 82 7 23
## 96 78.00000 185.9315 6.9 86 8 4
## 97 35.00000 185.9315 7.4 85 8 5
## 98 66.00000 185.9315 4.6 87 8 6
## 102 42.12931 222.0000 8.6 92 8 10
## 103 42.12931 137.0000 11.5 86 8 11
## 107 42.12931 64.0000 11.5 79 8 15
## 115 42.12931 255.0000 12.6 75 8 23
## 119 42.12931 153.0000 5.7 88 8 27
## 150 42.12931 145.0000 13.2 77 9 27
Сгенерируйте два числовых набора данных и добавьте в них выбросы. С использованием функции boxplot обнаружьте выбросы и удалить их [3, 4].
set.seed(123)
# Создаём базовые данные
data_a <- rnorm(50, mean = 10)
data_b <- rnorm(50, mean = 20)
# Добавляем выбросы
data_a <- c(data_a, 100, 120)
data_b <- c(data_b, -50, -70)
# Обнаружение выбросов
outliers_a <- boxplot.stats(data_a)$out
outliers_b <- boxplot.stats(data_b)$out
outliers_a
## [1] 100 120
outliers_b
## [1] 17.69083 -50.00000 -70.00000
# Визуализация с указанием выбросов
boxplot(data_a, main = "Data A")
mtext(paste("Выбросы:", paste(outliers_a, collapse=", ")), cex=0.7)
boxplot(data_b, main = "Data B")
mtext(paste("Выбросы:", paste(outliers_b, collapse=", ")), cex=0.7)
# Удаление выбросов
clean_a <- data_a[!data_a %in% outliers_a]
clean_b <- data_b[!data_b %in% outliers_b]
# Сравнение ДО и ПОСЛЕ
par(mfrow=c(1,2))
boxplot(data_a, main = "До удаления")
boxplot(clean_a, main = "После удаления")
Сгенерируйте таблицу данных, в которой дублируются строки. Удалите строки с использованием функций unique(), duplicated(). Сравните результаты [5].
# Создание таблицы с дублирующимися строками (строки 2-3 и 5-6 дублируются)
df_dup <- data.frame(
x = c(1, 2, 2, 3, 4, 4),
y = c("A", "B", "B", "C", "D", "D")
)
df_dup # Исходная таблица с дубликатами
## x y
## 1 1 A
## 2 2 B
## 3 2 B
## 4 3 C
## 5 4 D
## 6 4 D
# Способ 1: unique() - возвращает уникальные строки
unique_df <- unique(df_dup)
# Способ 2: duplicated() - логический вектор, FALSE для первых вхождений
dup_removed <- df_dup[!duplicated(df_dup), ]
# Проверка, что результаты совпадают
identical(unique_df, dup_removed)
## [1] TRUE
Разница между методами: unique(): Просто возвращает уникальные строки Не показывает процесс отбора Удобно для быстрого результата
duplicated(): Показывает, какие строки дублируются !duplicated() оставляет только первые вхождения Дает больше контроля и информации
Обработайте пропуски в данных с использованием пакета mice [6].
# Применяем mice к airquality
imp <- mice(airquality, m = 2, maxit = 10, method = "pmm", seed = 123)
##
## iter imp variable
## 1 1 Ozone Solar.R
## 1 2 Ozone Solar.R
## 2 1 Ozone Solar.R
## 2 2 Ozone Solar.R
## 3 1 Ozone Solar.R
## 3 2 Ozone Solar.R
## 4 1 Ozone Solar.R
## 4 2 Ozone Solar.R
## 5 1 Ozone Solar.R
## 5 2 Ozone Solar.R
## 6 1 Ozone Solar.R
## 6 2 Ozone Solar.R
## 7 1 Ozone Solar.R
## 7 2 Ozone Solar.R
## 8 1 Ozone Solar.R
## 8 2 Ozone Solar.R
## 9 1 Ozone Solar.R
## 9 2 Ozone Solar.R
## 10 1 Ozone Solar.R
## 10 2 Ozone Solar.R
airquality_mice <- complete(imp)
# Сравнение ДО и ПОСЛЕ
print(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
print(colSums(is.na(airquality)))
## Ozone Solar.R Wind Temp Month Day
## 37 7 0 0 0 0
print(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
print(colSums(is.na(airquality_mice)))
## Ozone Solar.R Wind Temp Month Day
## 0 0 0 0 0 0
Преимущества MICE перед простой медианой: Учитывает контекст - значения зависят от других переменных Сохраняет вариативность - не все пропуски получают одинаковые значения Реалистичность - использует только существующие в данных значения
Разберите пример с мультиколлинеарностью [7].
# Создаем данные с мультиколлинеарностью (x2 сильно коррелирует с x1), проверяем корреляцию
set.seed(123)
x1 <- rnorm(100)
x2 <- x1 * 0.9 + rnorm(100, sd = 0.1) # x2 коррелирует с x1
x3 <- rnorm(100) # независимая переменная
df_multi <- data.frame(x1, x2, x3)
cor(df_multi)
## x1 x2 x3
## x1 1.000000 0.9930810 -0.1291760
## x2 0.993081 1.0000000 -0.1254392
## x3 -0.129176 -0.1254392 1.0000000
# Регрессионная модель с мультиколлинеарностью
model <- lm(x1 ~ x2 + x3, data = df_multi)
summary(model)
##
## Call:
## lm(formula = x1 ~ x2 + x3, data = df_multi)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.37309 -0.05931 0.01159 0.07465 0.21749
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.013165 0.010965 1.201 0.233
## x2 1.101563 0.013329 82.646 <2e-16 ***
## x3 -0.004496 0.011540 -0.390 0.698
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1082 on 97 degrees of freedom
## Multiple R-squared: 0.9862, Adjusted R-squared: 0.9859
## F-statistic: 3474 on 2 and 97 DF, p-value: < 2.2e-16
# Расчет VIF (Variance Inflation Factor) - если VIF > 10, проблема мультиколлинеарности
vif(model)
## x2 x3
## 1.015987 1.015987
В ходе лабораторной работы были изучены основные методы подготовки данных: очистка от пропусков, обработка выбросов, удаление дубликатов и анализ мультиколлинеарности.