Сформируйте свой собственный датасет с помощью функции c (конкатенация), в котором содержатся числовые данные и NA значения.
# Создаем датасет с числовыми данными и NA значениями
my_dataset <- c(10, 15, NA, 22, 18, NA, 30, 25, NA, 12, 8, NA, 45, 33, 27)
cat("Созданный датасет:\n")
## Созданный датасет:
print(my_dataset)
## [1] 10 15 NA 22 18 NA 30 25 NA 12 8 NA 45 33 27
cat("\nДлина датасета:", length(my_dataset))
##
## Длина датасета: 15
cat("\nКоличество NA значений:", sum(is.na(my_dataset)))
##
## Количество NA значений: 4
Проведите очистку данных с использованием функции is.na() и выведите “чистый” датасет.
# Определяем, какие элементы являются NA
na_positions <- is.na(my_dataset)
cat("Позиции NA значений:\n")
## Позиции NA значений:
print(na_positions)
## [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [13] FALSE FALSE FALSE
# Очищаем датасет (удаляем NA)
clean_dataset <- my_dataset[!na_positions]
cat("\nОчищенный датасет (без NA):\n")
##
## Очищенный датасет (без NA):
print(clean_dataset)
## [1] 10 15 22 18 30 25 12 8 45 33 27
cat("\nДлина очищенного датасета:", length(clean_dataset))
##
## Длина очищенного датасета: 11
cat("\nПроверка на наличие NA:", any(is.na(clean_dataset)))
##
## Проверка на наличие NA: FALSE
Сгенерируйте таблицу данных с числовыми и текстовыми столбцами. Очистите данные с помощью функции complete.cases().
# Создаем таблицу с числовыми и текстовыми столбцами
id <- c(1, 2, 3, 4, 5, 6)
name <- c("Иван", "Мария", "Петр", "Анна", "Сергей", "Елена")
age <- c(25, NA, 30, 22, NA, 35)
city <- c("Москва", "СПб", NA, "Казань", "Москва", NA)
score <- c(85, 92, NA, 78, 88, 95)
# Создаем data frame
df <- data.frame(ID = id, Name = name, Age = age, City = city, Score = score)
cat("Исходная таблица с пропусками:\n")
## Исходная таблица с пропусками:
print(df)
## ID Name Age City Score
## 1 1 Иван 25 Москва 85
## 2 2 Мария NA СПб 92
## 3 3 Петр 30 <NA> NA
## 4 4 Анна 22 Казань 78
## 5 5 Сергей NA Москва 88
## 6 6 Елена 35 <NA> 95
# Очистка данных с помощью complete.cases()
complete_rows <- complete.cases(df)
cat("\nСтроки без пропусков (complete.cases):\n")
##
## Строки без пропусков (complete.cases):
print(complete_rows)
## [1] TRUE FALSE FALSE TRUE FALSE FALSE
# Получаем чистый датасет
clean_df <- df[complete_rows, ]
cat("\nОчищенная таблица (только полные строки):\n")
##
## Очищенная таблица (только полные строки):
print(clean_df)
## ID Name Age City Score
## 1 1 Иван 25 Москва 85
## 4 4 Анна 22 Казань 78
cat("\nСтатистика:\n")
##
## Статистика:
cat("Всего строк:", nrow(df), "\n")
## Всего строк: 6
cat("Полных строк:", sum(complete_rows), "\n")
## Полных строк: 2
cat("Строк с пропусками:", sum(!complete_rows), "\n")
## Строк с пропусками: 4
Проанализируйте датасет airquality с пропусками. С использованием функции preProcess из пакета caret заполните пропуски предсказанными значениями (среднее, медиана).
library(caret)
# Загружаем датасет airquality
data(airquality)
cat("Датасет airquality:\n")
## Датасет airquality:
cat("Размерность:", dim(airquality), "\n")
## Размерность: 153 6
cat("Структура:\n")
## Структура:
str(airquality)
## 'data.frame': 153 obs. of 6 variables:
## $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ...
## $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ...
## $ Wind : num 7.4 8 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 ...
## $ Month : int 5 5 5 5 5 5 5 5 5 5 ...
## $ Day : int 1 2 3 4 5 6 7 8 9 10 ...
# Анализируем пропуски
cat("\nАнализ пропусков:\n")
##
## Анализ пропусков:
na_count <- colSums(is.na(airquality))
print(na_count)
## Ozone Solar.R Wind Temp Month Day
## 37 7 0 0 0 0
cat("\nПроцент пропусков:\n")
##
## Процент пропусков:
na_percent <- round(colMeans(is.na(airquality)) * 100, 2)
print(na_percent)
## Ozone Solar.R Wind Temp Month Day
## 24.18 4.58 0.00 0.00 0.00 0.00
# Заполнение пропусков методом среднего
preProcess_mean <- preProcess(airquality, method = "medianImpute")
airquality_mean <- predict(preProcess_mean, airquality)
cat("\nДатасет после заполнения средним:\n")
##
## Датасет после заполнения средним:
cat("Проверка наличия NA:", any(is.na(airquality_mean)), "\n")
## Проверка наличия NA: FALSE
# Сравнение результатов
cat("\nСравнение первых строк оригинала и после заполнения:\n")
##
## Сравнение первых строк оригинала и после заполнения:
comparison_df <- data.frame(
Оригинал = head(airquality$Ozone, 10),
После_заполнения = head(airquality_mean$Ozone, 10)
)
print(comparison_df)
## Оригинал После_заполнения
## 1 41 41.0
## 2 36 36.0
## 3 12 12.0
## 4 18 18.0
## 5 NA 31.5
## 6 28 28.0
## 7 23 23.0
## 8 19 19.0
## 9 8 8.0
## 10 NA 31.5
Сгенерируйте два числовых набора данных и добавьте в них выбросы. С использованием функции boxplot обнаружьте выбросы и удалите их.
set.seed(123)
# Генерируем два набора данных с выбросами
data1 <- c(rnorm(50, mean = 10, sd = 2), 25, 30, 5, 2)
data2 <- c(rnorm(50, mean = 20, sd = 3), 40, 45, 10, 8)
cat("Набор данных 1:\n")
## Набор данных 1:
cat("Длина:", length(data1), "\n")
## Длина: 54
cat("Сводная статистика:\n")
## Сводная статистика:
print(summary(data1))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.000 8.782 9.855 10.471 11.521 30.000
cat("\nНабор данных 2:\n")
##
## Набор данных 2:
cat("Длина:", length(data2), "\n")
## Длина: 54
cat("Сводная статистика:\n")
## Сводная статистика:
print(summary(data2))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8.00 18.62 20.46 20.83 22.56 45.00
# Визуализация выбросов с помощью boxplot
par(mfrow = c(2, 2))
# Boxplot для первого набора
boxplot(data1, main = "Набор 1 - с выбросами",
col = "lightblue", horizontal = TRUE)
# Boxplot для второго набора
boxplot(data2, main = "Набор 2 - с выбросами",
col = "lightgreen", horizontal = TRUE)
# Функция для обнаружения и удаления выбросов
remove_outliers <- function(x, coef = 1.5) {
qnt <- quantile(x, probs = c(0.25, 0.75), na.rm = TRUE)
iqr <- qnt[2] - qnt[1]
lower <- qnt[1] - coef * iqr
upper <- qnt[2] + coef * iqr
outliers <- x[x < lower | x > upper]
clean_x <- x[x >= lower & x <= upper]
return(list(
clean = clean_x,
outliers = outliers,
lower_bound = lower,
upper_bound = upper,
removed_count = length(outliers)
))
}
# Удаляем выбросы
result1 <- remove_outliers(data1)
result2 <- remove_outliers(data2)
cat("\nРезультаты удаления выбросов:\n")
##
## Результаты удаления выбросов:
cat("Набор 1 - удалено:", result1$removed_count, "выбросов\n")
## Набор 1 - удалено: 3 выбросов
cat("Выбросы в наборе 1:", result1$outliers, "\n")
## Выбросы в наборе 1: 25 30 2
cat("Набор 2 - удалено:", result2$removed_count, "выбросов\n")
## Набор 2 - удалено: 4 выбросов
cat("Выбросы в наборе 2:", result2$outliers, "\n")
## Выбросы в наборе 2: 40 45 10 8
# Визуализация после удаления выбросов
boxplot(result1$clean, main = "Набор 1 - после удаления",
col = "lightblue", horizontal = TRUE)
boxplot(result2$clean, main = "Набор 2 - после удаления",
col = "lightgreen", horizontal = TRUE)
Обнаружение и удаление выбросов
par(mfrow = c(1, 1))
# Сравнительная таблица
cat("\nСравнительная таблица:\n")
##
## Сравнительная таблица:
comparison <- data.frame(
Показатель = c("До удаления", "После удаления", "Удалено"),
Набор1 = c(length(data1), length(result1$clean), result1$removed_count),
Набор2 = c(length(data2), length(result2$clean), result2$removed_count)
)
print(comparison)
## Показатель Набор1 Набор2
## 1 До удаления 54 54
## 2 После удаления 51 50
## 3 Удалено 3 4
Сгенерируйте таблицу данных, в которой дублируются строки. Удалите строки с использованием функций unique(), duplicated(). Сравните результаты.
# Создаем таблицу с дубликатами
set.seed(123)
df_duplicates <- data.frame(
ID = c(1, 2, 3, 1, 4, 2, 5, 3, 6, 1),
Name = c("Анна", "Иван", "Мария", "Анна", "Петр", "Иван", "Елена", "Мария", "Сергей", "Анна"),
Age = c(25, 30, 28, 25, 35, 30, 22, 28, 40, 25),
Score = c(85, 90, 88, 85, 92, 90, 87, 88, 95, 85)
)
cat("Исходная таблица с дубликатами:\n")
## Исходная таблица с дубликатами:
print(df_duplicates)
## ID Name Age Score
## 1 1 Анна 25 85
## 2 2 Иван 30 90
## 3 3 Мария 28 88
## 4 1 Анна 25 85
## 5 4 Петр 35 92
## 6 2 Иван 30 90
## 7 5 Елена 22 87
## 8 3 Мария 28 88
## 9 6 Сергей 40 95
## 10 1 Анна 25 85
cat("\nРазмерность:", dim(df_duplicates), "\n")
##
## Размерность: 10 4
# Использование duplicated() для поиска дубликатов
duplicated_rows <- duplicated(df_duplicates)
cat("\nДублированные строки (duplicated):\n")
##
## Дублированные строки (duplicated):
print(duplicated_rows)
## [1] FALSE FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
# Использование duplicated() для удаления
df_no_duplicates_dup <- df_duplicates[!duplicated_rows, ]
cat("\nПосле удаления duplicated():\n")
##
## После удаления duplicated():
print(df_no_duplicates_dup)
## ID Name Age Score
## 1 1 Анна 25 85
## 2 2 Иван 30 90
## 3 3 Мария 28 88
## 5 4 Петр 35 92
## 7 5 Елена 22 87
## 9 6 Сергей 40 95
cat("Размерность:", dim(df_no_duplicates_dup), "\n")
## Размерность: 6 4
# Использование unique() для удаления
df_no_duplicates_unique <- unique(df_duplicates)
cat("\nПосле удаления unique():\n")
##
## После удаления unique():
print(df_no_duplicates_unique)
## ID Name Age Score
## 1 1 Анна 25 85
## 2 2 Иван 30 90
## 3 3 Мария 28 88
## 5 4 Петр 35 92
## 7 5 Елена 22 87
## 9 6 Сергей 40 95
cat("Размерность:", dim(df_no_duplicates_unique), "\n")
## Размерность: 6 4
# Сравнение результатов
cat("\n=== СРАВНЕНИЕ МЕТОДОВ ===\n")
##
## === СРАВНЕНИЕ МЕТОДОВ ===
cat("Исходная таблица:", nrow(df_duplicates), "строк\n")
## Исходная таблица: 10 строк
cat("После duplicated():", nrow(df_no_duplicates_dup), "строк\n")
## После duplicated(): 6 строк
cat("После unique():", nrow(df_no_duplicates_unique), "строк\n")
## После unique(): 6 строк
cat("Методы дают одинаковый результат:",
identical(df_no_duplicates_dup, df_no_duplicates_unique), "\n")
## Методы дают одинаковый результат: TRUE
Обработайте пропуски в данных с использованием пакета mice.
library(mice)
# Создаем данные с пропусками
set.seed(123)
n <- 50
df_mice <- data.frame(
x1 = rnorm(n, mean = 10, sd = 2),
x2 = rnorm(n, mean = 20, sd = 3),
x3 = rnorm(n, mean = 30, sd = 4),
x4 = factor(sample(c("A", "B", "C"), n, replace = TRUE))
)
# Вносим пропуски
df_mice$x1[sample(1:n, 10)] <- NA
df_mice$x2[sample(1:n, 8)] <- NA
df_mice$x3[sample(1:n, 5)] <- NA
df_mice$x4[sample(1:n, 12)] <- NA
cat("Датасет с пропусками:\n")
## Датасет с пропусками:
cat("Размерность:", dim(df_mice), "\n")
## Размерность: 50 4
cat("Количество пропусков:\n")
## Количество пропусков:
na_count_mice <- colSums(is.na(df_mice))
print(na_count_mice)
## x1 x2 x3 x4
## 10 8 5 12
# Визуализация пропусков
md.pattern(df_mice)
## x3 x2 x1 x4
## 24 1 1 1 1 0
## 8 1 1 1 0 1
## 5 1 1 0 1 1
## 1 1 1 0 0 2
## 3 1 0 1 1 1
## 2 1 0 0 1 2
## 2 1 0 0 0 3
## 3 0 1 1 1 1
## 1 0 1 1 0 2
## 1 0 0 1 1 2
## 5 8 10 12 35
# Применяем mice для множественной импутации
cat("\nЗапуск mice для множественной импутации...\n")
##
## Запуск mice для множественной импутации...
imp <- mice(df_mice, m = 5, maxit = 10, method = 'pmm', seed = 123, printFlag = FALSE)
cat("\nМетоды импутации для каждой переменной:\n")
##
## Методы импутации для каждой переменной:
print(imp$method)
## x1 x2 x3 x4
## "pmm" "pmm" "pmm" "pmm"
# Получаем первый заполненный датасет
df_complete_1 <- complete(imp, 1)
cat("\nПервый заполненный датасет (первые 10 строк):\n")
##
## Первый заполненный датасет (первые 10 строк):
print(head(df_complete_1, 10))
## x1 x2 x3 x4
## 1 8.879049 20.75996 27.15837 B
## 2 11.559930 20.54391 31.02753 A
## 3 7.864353 19.87139 29.01323 C
## 4 10.141017 24.10581 28.60983 B
## 5 10.258575 19.32269 26.19353 A
## 6 13.430130 20.54391 29.81989 A
## 7 10.921832 15.35374 26.86038 B
## 8 7.469878 21.75384 23.32823 C
## 9 8.626294 20.37156 28.47909 B
## 10 9.108676 20.64782 33.67599 C
# Проверка распределений
par(mfrow = c(2, 2))
for(i in 1:4) {
if(is.numeric(df_mice[,i])) {
# Оригинальные данные без NA
orig <- df_mice[!is.na(df_mice[,i]), i]
# Импутированные данные
imp_data <- complete(imp, 1)[,i]
plot(density(orig), col = "red", lwd = 2,
main = paste("Распределение", names(df_mice)[i]),
xlab = "Значения")
lines(density(imp_data), col = "blue", lwd = 2)
legend("topright", legend = c("Оригинал", "После импутации"),
col = c("red", "blue"), lwd = 2)
} else {
# Для факторных переменных - столбчатая диаграмма
barplot(table(df_mice[,i]), main = paste("Распределение", names(df_mice)[i]),
col = "lightblue", xlab = "Категории", ylab = "Частота")
}
}
par(mfrow = c(1, 1))
Разберите пример с мультиколлинеарностью.
library(caret)
library(corrplot)
library(car)
# Создаем данные с мультиколлинеарностью
set.seed(123)
n <- 100
# Основные переменные
x1 <- rnorm(n, mean = 10, sd = 2)
x2 <- rnorm(n, mean = 20, sd = 3)
x3 <- rnorm(n, mean = 30, sd = 4)
# Создаем сильно коррелированные переменные
x4 <- 2 * x1 + rnorm(n, 0, 0.5)
x5 <- 0.5 * x2 + rnorm(n, 0, 0.3)
x6 <- x3 + x1 + rnorm(n, 0, 1)
# Целевая переменная
y <- 5 + 2*x1 + 3*x2 + 1.5*x3 + rnorm(n, 0, 2)
df_multicoll <- data.frame(x1, x2, x3, x4, x5, x6, y)
cat("Датасет с мультиколлинеарностью:\n")
## Датасет с мультиколлинеарностью:
cat("Размерность:", dim(df_multicoll), "\n")
## Размерность: 100 7
# Анализ корреляционной матрицы
cat("\n=== КОРРЕЛЯЦИОННАЯ МАТРИЦА ===\n")
##
## === КОРРЕЛЯЦИОННАЯ МАТРИЦА ===
cor_matrix <- cor(df_multicoll[, 1:6])
print(round(cor_matrix, 3))
## x1 x2 x3 x4 x5 x6
## x1 1.000 -0.050 -0.129 0.990 -0.089 0.313
## x2 -0.050 1.000 0.031 -0.043 0.979 0.033
## x3 -0.129 0.031 1.000 -0.135 0.026 0.874
## x4 0.990 -0.043 -0.135 1.000 -0.083 0.300
## x5 -0.089 0.979 0.026 -0.083 1.000 0.020
## x6 0.313 0.033 0.874 0.300 0.020 1.000
# Визуализация корреляционной матрицы
corrplot(cor_matrix, method = "color", type = "upper",
tl.col = "black", tl.srt = 45,
title = "Корреляционная матрица")
# VIF анализ
model_full <- lm(y ~ ., data = df_multicoll)
cat("\n=== VIF АНАЛИЗ ===\n")
##
## === VIF АНАЛИЗ ===
vif_values <- vif(model_full)
print(vif_values)
## x1 x2 x3 x4 x5 x6
## 57.25092 25.93986 18.79531 50.60383 26.36414 20.53319
# Удаление коррелированных переменных
highly_correlated <- findCorrelation(cor_matrix, cutoff = 0.7)
cat("\nПеременные для удаления:", names(df_multicoll)[highly_correlated], "\n")
##
## Переменные для удаления: x1 x6 x5
df_reduced <- df_multicoll[, -highly_correlated]
cat("\nДатасет после удаления:\n")
##
## Датасет после удаления:
cat("Переменные:", names(df_reduced), "\n")
## Переменные: x2 x3 x4 y
# Сравнение моделей
model_reduced <- lm(y ~ ., data = df_reduced)
cat("\n=== СРАВНЕНИЕ МОДЕЛЕЙ ===\n")
##
## === СРАВНЕНИЕ МОДЕЛЕЙ ===
cat("Полная модель R²:", round(summary(model_full)$r.squared, 4), "\n")
## Полная модель R²: 0.9662
cat("Уменьшенная модель R²:", round(summary(model_reduced)$r.squared, 4), "\n")
## Уменьшенная модель R²: 0.9626
# Визуализация VIF до и после
par(mfrow = c(1, 2))
# VIF до удаления
barplot(vif_values, main = "VIF до удаления",
col = ifelse(vif_values > 10, "red", "lightblue"),
ylab = "VIF", las = 2, ylim = c(0, max(vif_values) * 1.1))
abline(h = 10, col = "red", lty = 2)
# VIF после удаления
vif_reduced <- vif(model_reduced)
barplot(vif_reduced, main = "VIF после удаления",
col = "lightgreen",
ylab = "VIF", las = 2, ylim = c(0, max(vif_reduced) * 1.1))
abline(h = 10, col = "red", lty = 2)
par(mfrow = c(1, 1))
cat("\n=== ВЫВОДЫ ===\n")
##
## === ВЫВОДЫ ===
cat("Мультиколлинеарность успешно обнаружена и устранена.\n")
## Мультиколлинеарность успешно обнаружена и устранена.
В ходе выполнения работы были освоены основные методы обработки и очистки данных в R:
Все методы были успешно применены на практике с соответствующими примерами и визуализацией результатов.