Задание 1

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

# Создаём вектор, содержащий числовые значения и пропуски (NA) — имитируем реальные данные.
my_data <- c(5, 3, NA, 7, 2, NA, 9)
my_data
## [1]  5  3 NA  7  2 NA  9

Задание 2

Проведите очистку данных с использованием is.na(). Выведите “чистый” датасет.

# Удаляем пропуски из вектора, оставляя только заполненные значения.
clean_data <- my_data[!is.na(my_data)]
clean_data
## [1] 5 3 7 2 9

Задание 3

Создайте таблицу с числовыми и текстовыми столбцами. Очистите её с помощью complete.cases().

# Создаём датафрейм с пропусками в разных столбцах
# Используем complete.cases() для удаления строк, содержащих хотя бы один NA.
df <- data.frame(
  Name = c("Антон", "Никита", NA, "Сергей", "Гвозден"),
  Score = c(80, NA, 75, 90, NA)
)
df
##      Name Score
## 1   Антон    80
## 2  Никита    NA
## 3    <NA>    75
## 4  Сергей    90
## 5 Гвозден    NA
df_clean <- df[complete.cases(df), ]
df_clean
##     Name Score
## 1  Антон    80
## 4 Сергей    90

Задание 4

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

library(caret)
## Загрузка требуемого пакета: ggplot2
## Загрузка требуемого пакета: lattice
data("airquality")

# Проверка пропусков
summary(airquality)
##      Ozone           Solar.R           Wind             Temp      
##  Min.   :  1.00   Min.   :  7.0   Min.   : 1.700   Min.   :56.00  
##  1st Qu.: 18.00   1st Qu.:115.8   1st Qu.: 7.400   1st Qu.:72.00  
##  Median : 31.50   Median :205.0   Median : 9.700   Median :79.00  
##  Mean   : 42.13   Mean   :185.9   Mean   : 9.958   Mean   :77.88  
##  3rd Qu.: 63.25   3rd Qu.:258.8   3rd Qu.:11.500   3rd Qu.:85.00  
##  Max.   :168.00   Max.   :334.0   Max.   :20.700   Max.   :97.00  
##  NA's   :37       NA's   :7                                       
##      Month            Day      
##  Min.   :5.000   Min.   : 1.0  
##  1st Qu.:6.000   1st Qu.: 8.0  
##  Median :7.000   Median :16.0  
##  Mean   :6.993   Mean   :15.8  
##  3rd Qu.:8.000   3rd Qu.:23.0  
##  Max.   :9.000   Max.   :31.0  
## 

Вариант 1: knnImpute

# Метод KNN подбирает значения для NA, опираясь на наиболее похожие строки по остальным признакам
pre_knn <- preProcess(airquality, method = "knnImpute")
airquality_knn <- predict(pre_knn, airquality)
head(airquality_knn)
##         Ozone      Solar.R       Wind       Temp     Month       Day
## 1 -0.03423409  0.045176154 -0.7259482 -1.1497140 -1.407294 -1.670019
## 2 -0.18580489 -0.754304874 -0.5556388 -0.6214670 -1.407294 -1.557210
## 3 -0.91334473 -0.410083876  0.7500660 -0.4101682 -1.407294 -1.444401
## 4 -0.73145977  1.410956244  0.4378323 -1.6779609 -1.407294 -1.331592
## 5 -0.81027658 -0.221317522  1.2326091 -2.3118573 -1.407294 -1.218782
## 6 -0.42831817  0.007422883  1.4029185 -1.2553634 -1.407294 -1.105973

Вариант 2: вручную (среднее и медиана)

# Замена NA на среднее значение по столбцу
air_mean <- airquality
for (col in names(air_mean)) {
  if (is.numeric(air_mean[[col]])) {
    air_mean[[col]][is.na(air_mean[[col]])] <- mean(air_mean[[col]], na.rm = TRUE)
  }
}

# Замена NA на медиану по столбцу
air_median <- airquality
for (col in names(air_median)) {
  if (is.numeric(air_median[[col]])) {
    air_median[[col]][is.na(air_median[[col]])] <- median(air_median[[col]], na.rm = TRUE)
  }
}

head(air_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
head(air_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

Задание 5

Создайте 2 числовых набора с выбросами. Обнаружьте и удалите их с помощью boxplot.

set.seed(123)
x <- c(rnorm(20), 100)  # добавлен выброс
y <- c(rnorm(20), -50)  # добавлен выброс

# Boxplot позволяет визуально оценить выбросы по распределению данных
boxplot(x, main="x с выбросом")

boxplot(y, main="y с выбросом")

# Удаляем выбросы с использованием boxplot.stats()
x_clean <- x[!x %in% boxplot.stats(x)$out]
y_clean <- y[!y %in% boxplot.stats(y)$out]

boxplot(x_clean, main="x без выбросов")

boxplot(y_clean, main="y без выбросов")

Задание 6

Создайте таблицу с дублирующимися строками и удалите дубли с помощью unique() и duplicated().

# Создаём датафрейм с повторяющимися строками
df_dup <- data.frame(
  Name = c("А", "Б", "А", "В", "Б"),
  Score = c(90, 85, 90, 75, 85)
)

# unique() возвращает датафрейм без повторов, оставляя первую встречу
unique_rows <- unique(df_dup)

# duplicated() даёт логический вектор — оставляем только первые вхождения
df_no_dup <- df_dup[!duplicated(df_dup), ]

unique_rows
##   Name Score
## 1    А    90
## 2    Б    85
## 4    В    75
df_no_dup
##   Name Score
## 1    А    90
## 2    Б    85
## 4    В    75

Задание 7

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

library(mice)
## 
## Присоединяю пакет: 'mice'
## Следующий объект скрыт от 'package:stats':
## 
##     filter
## Следующие объекты скрыты от 'package:base':
## 
##     cbind, rbind
data("airquality")

# Метод pmm (предиктивное сопоставление) используется для реалистичного восстановления NA
imp <- mice(airquality, method = "pmm", m = 1)
## 
##  iter imp variable
##   1   1  Ozone  Solar.R
##   2   1  Ozone  Solar.R
##   3   1  Ozone  Solar.R
##   4   1  Ozone  Solar.R
##   5   1  Ozone  Solar.R
airquality_mice <- complete(imp)
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     1      71 14.3   56     5   5
## 6    28     285 14.9   66     5   6

Задание 8

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

library(car)
## Загрузка требуемого пакета: carData
set.seed(42)

# x2 почти полностью коррелирует с x1 — будет высокая мультиколлинеарность
x1 <- rnorm(100)
x2 <- x1 * 0.95 + rnorm(100, sd=0.1)
x3 <- rnorm(100)
y <- 3*x1 + 2*x3 + rnorm(100)

df_multi <- data.frame(y, x1, x2, x3)
model <- lm(y ~ x1 + x2 + x3, data = df_multi)

# Функция vif() оценивает фактор инфляции дисперсии — значения > 5–10 указывают на коррелирующие переменные
vif(model)
##         x1         x2         x3 
## 122.497193 122.234024   1.027438