Задание 1. Создание датасета с NA

my_vector <- c(10, 25, NA, 15, 30, NA, 42, 55, NA, 18)
print("Исходный датасет (вектор):")
## [1] "Исходный датасет (вектор):"
print(my_vector)
##  [1] 10 25 NA 15 30 NA 42 55 NA 18

Задание 2. Очистка данных с использованием is.na()

print("Индексы пропусков (TRUE - пропуск):")
## [1] "Индексы пропусков (TRUE - пропуск):"
print(is.na(my_vector))
##  [1] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE
print("Очищенный датасет (без NA):")
## [1] "Очищенный датасет (без NA):"
print(my_vector[!is.na(my_vector)])
## [1] 10 25 15 30 42 55 18

Задание 3. Таблица данных и complete.cases()

df <- data.frame(
  ID = 1:10,
  Value = c(5.1, 6.3, NA, 4.8, 7.2, NA, 5.9, 8.0, NA, 6.6),
  Category = c("A", "B", "B", NA, "A", "C", "C", "B", NA, "A"),
  Score = c(85, NA, 92, 78, 88, 95, NA, 89, 76, 91),
  stringsAsFactors = FALSE
)
print("Исходная таблица данных:")
## [1] "Исходная таблица данных:"
print(df)
##    ID Value Category Score
## 1   1   5.1        A    85
## 2   2   6.3        B    NA
## 3   3    NA        B    92
## 4   4   4.8     <NA>    78
## 5   5   7.2        A    88
## 6   6    NA        C    95
## 7   7   5.9        C    NA
## 8   8   8.0        B    89
## 9   9    NA     <NA>    76
## 10 10   6.6        A    91
complete_rows <- complete.cases(df)
print("Логический вектор полных строк (TRUE - нет пропусков):")
## [1] "Логический вектор полных строк (TRUE - нет пропусков):"
print(complete_rows)
##  [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE
clean_df <- df[complete_rows, ]
print("Очищенная таблица данных (только полные строки):")
## [1] "Очищенная таблица данных (только полные строки):"
print(clean_df)
##    ID Value Category Score
## 1   1   5.1        A    85
## 5   5   7.2        A    88
## 8   8   8.0        B    89
## 10 10   6.6        A    91

Задание 4. Импутация данных airquality с помощью caret

library(caret)
library(datasets)

data("airquality")
print("Структура исходного датасета airquality:")
## [1] "Структура исходного датасета airquality:"
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 ...
print("Количество NA в каждом столбце:")
## [1] "Количество NA в каждом столбце:"
colSums(is.na(airquality))
##   Ozone Solar.R    Wind    Temp   Month     Day 
##      37       7       0       0       0       0
df_for_impute <- airquality[, 1:4]
print("Первые несколько строк данных до импутации:")
## [1] "Первые несколько строк данных до импутации:"
head(df_for_impute, 10)
##    Ozone Solar.R Wind Temp
## 1     41     190  7.4   67
## 2     36     118  8.0   72
## 3     12     149 12.6   74
## 4     18     313 11.5   62
## 5     NA      NA 14.3   56
## 6     28      NA 14.9   66
## 7     23     299  8.6   65
## 8     19      99 13.8   59
## 9      8      19 20.1   61
## 10    NA     194  8.6   69
set.seed(123)
preProc_median <- preProcess(df_for_impute, method = "medianImpute")
df_median_imputed <- predict(preProc_median, df_for_impute)

print("Первые несколько строк после импутации медианой:")
## [1] "Первые несколько строк после импутации медианой:"
head(df_median_imputed, 10)
##    Ozone Solar.R Wind Temp
## 1   41.0     190  7.4   67
## 2   36.0     118  8.0   72
## 3   12.0     149 12.6   74
## 4   18.0     313 11.5   62
## 5   31.5     205 14.3   56
## 6   28.0     205 14.9   66
## 7   23.0     299  8.6   65
## 8   19.0      99 13.8   59
## 9    8.0      19 20.1   61
## 10  31.5     194  8.6   69
print("Проверка NA после импутации медианой:")
## [1] "Проверка NA после импутации медианой:"
colSums(is.na(df_median_imputed))
##   Ozone Solar.R    Wind    Temp 
##       0       0       0       0

Примечание: метод meanImpute в пакете caret недоступен — при попытке его использования возникает ошибка These pre-processing methods are unknown: 'meanImpute'. Поэтому импутация выполнена медианой.

Задание 5. Обнаружение и удаление выбросов

set.seed(456)
data1 <- c(rnorm(40, mean = 10, sd = 2), 25, 30)
data2 <- c(rnorm(40, mean = 50, sd = 5), 10, 75)

print("Сгенерированные данные (data1):")
## [1] "Сгенерированные данные (data1):"
print(data1)
##  [1]  7.312957 11.243551 11.601749  7.222215  8.571286  9.351878 11.381286
##  [8] 10.501096 12.014705 11.146469  8.168379 12.622195 11.977453 13.307857
## [15]  7.118390 13.894713 13.473872 10.774967 14.560068 13.075767  9.050792
## [22]  6.565382  7.146339 10.416472  9.928328 12.268569  9.074290  9.343232
## [29] 12.969079  7.821244  8.942412  8.812414  6.002169 10.592306 10.341251
## [36] 13.631305  8.678794  9.719496  9.152042  9.922528 25.000000 30.000000
print("Сгенерированные данные (data2):")
## [1] "Сгенерированные данные (data2):"
print(data2)
##  [1] 49.85529 51.96519 48.75193 50.41725 60.39437 50.60426 50.59075 53.85027
##  [9] 44.12299 52.04519 46.67525 48.71738 53.39391 54.48422 53.09178 53.65727
## [17] 47.93413 57.78907 52.70849 52.88575 38.72645 45.08970 48.99716 54.47965
## [25] 49.78228 58.23654 57.81650 42.84311 47.27703 46.14373 49.15006 49.79619
## [33] 41.39730 57.22053 49.89993 51.35116 49.43533 45.72556 44.83129 51.11013
## [41] 10.00000 75.00000
remove_outliers <- function(x) {
  outliers <- boxplot.stats(x)$out
  outlier_indices <- which(x %in% outliers)
  if (length(outlier_indices) > 0) {
    cat("Найдены выбросы на позициях:", paste(outlier_indices, collapse=", "), "со значениями:", paste(outliers, collapse=", "), "\n")
    return(x[-outlier_indices])
  } else {
    cat("Выбросов не найдено.\n")
    return(x)
  }
}

par(mfrow=c(1,2))
boxplot(data1, main="Data1 с выбросами", col="lightblue", horizontal=TRUE)
boxplot(data2, main="Data2 с выбросами", col="lightgreen", horizontal=TRUE)

clean_data1 <- remove_outliers(data1)
## Найдены выбросы на позициях: 41, 42 со значениями: 25, 30
clean_data2 <- remove_outliers(data2)
## Найдены выбросы на позициях: 41, 42 со значениями: 10, 75
par(mfrow=c(1,2))
boxplot(clean_data1, main="Data1 без выбросов", col="lightblue", horizontal=TRUE)
boxplot(clean_data2, main="Data2 без выбросов", col="lightgreen", horizontal=TRUE)

par(mfrow=c(1,1))

Задание 6. Удаление дублирующихся строк

df_dup <- data.frame(
  ID = c(1, 2, 3, 1, 4, 2, 5, 3),
  Value = c("A", "B", "C", "A", "B", "B", "E", "C"),
  Score = c(10, 20, 30, 10, 40, 20, 50, 30),
  stringsAsFactors = FALSE
)
print("Исходная таблица с дубликатами:")
## [1] "Исходная таблица с дубликатами:"
print(df_dup)
##   ID Value Score
## 1  1     A    10
## 2  2     B    20
## 3  3     C    30
## 4  1     A    10
## 5  4     B    40
## 6  2     B    20
## 7  5     E    50
## 8  3     C    30
df_unique <- unique(df_dup)
print("Результат unique() (все уникальные строки):")
## [1] "Результат unique() (все уникальные строки):"
print(df_unique)
##   ID Value Score
## 1  1     A    10
## 2  2     B    20
## 3  3     C    30
## 5  4     B    40
## 7  5     E    50
print(paste("Количество строк после unique():", nrow(df_unique)))
## [1] "Количество строк после unique(): 5"
duplicate_rows <- duplicated(df_dup)
print("Логический вектор duplicated() (TRUE - дубликат):")
## [1] "Логический вектор duplicated() (TRUE - дубликат):"
print(duplicate_rows)
## [1] FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE
df_dup_removed <- df_dup[!duplicate_rows, ]
print("Результат duplicated() (первые вхождения каждой уникальной строки):")
## [1] "Результат duplicated() (первые вхождения каждой уникальной строки):"
print(df_dup_removed)
##   ID Value Score
## 1  1     A    10
## 2  2     B    20
## 3  3     C    30
## 5  4     B    40
## 7  5     E    50

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

library(mice)
df_mice_clean <- airquality[, 1:4]

set.seed(123)
mice_imputed <- mice(df_mice_clean, m = 2, method = 'pmm', maxit = 5, printFlag = FALSE)
df_complete_1 <- complete(mice_imputed, 1)
print("Заполненный датасет (импутация №1):")
## [1] "Заполненный датасет (импутация №1):"
head(df_complete_1, 20)
##    Ozone Solar.R Wind Temp
## 1     41     190  7.4   67
## 2     36     118  8.0   72
## 3     12     149 12.6   74
## 4     18     313 11.5   62
## 5     18      59 14.3   56
## 6     28     255 14.9   66
## 7     23     299  8.6   65
## 8     19      99 13.8   59
## 9      8      19 20.1   61
## 10    11     194  8.6   69
## 11     7      37  6.9   74
## 12    16     256  9.7   69
## 13    11     290  9.2   66
## 14    14     274 10.9   68
## 15    18      65 13.2   58
## 16    14     334 11.5   64
## 17    34     307 12.0   66
## 18     6      78 18.4   57
## 19    30     322 11.5   68
## 20    11      44  9.7   62
df_complete_2 <- complete(mice_imputed, 2)
print("Заполненный датасет (импутация №2):")
## [1] "Заполненный датасет (импутация №2):"
head(df_complete_2, 20)
##    Ozone Solar.R Wind Temp
## 1     41     190  7.4   67
## 2     36     118  8.0   72
## 3     12     149 12.6   74
## 4     18     313 11.5   62
## 5     14     290 14.3   56
## 6     28     320 14.9   66
## 7     23     299  8.6   65
## 8     19      99 13.8   59
## 9      8      19 20.1   61
## 10    14     194  8.6   69
## 11     7      44  6.9   74
## 12    16     256  9.7   69
## 13    11     290  9.2   66
## 14    14     274 10.9   68
## 15    18      65 13.2   58
## 16    14     334 11.5   64
## 17    34     307 12.0   66
## 18     6      78 18.4   57
## 19    30     322 11.5   68
## 20    11      44  9.7   62
print("Оригинальные данные (первые 20 строк):")
## [1] "Оригинальные данные (первые 20 строк):"
head(df_mice_clean, 20)
##    Ozone Solar.R Wind Temp
## 1     41     190  7.4   67
## 2     36     118  8.0   72
## 3     12     149 12.6   74
## 4     18     313 11.5   62
## 5     NA      NA 14.3   56
## 6     28      NA 14.9   66
## 7     23     299  8.6   65
## 8     19      99 13.8   59
## 9      8      19 20.1   61
## 10    NA     194  8.6   69
## 11     7      NA  6.9   74
## 12    16     256  9.7   69
## 13    11     290  9.2   66
## 14    14     274 10.9   68
## 15    18      65 13.2   58
## 16    14     334 11.5   64
## 17    34     307 12.0   66
## 18     6      78 18.4   57
## 19    30     322 11.5   68
## 20    11      44  9.7   62
print("Проверка NA после импутации:")
## [1] "Проверка NA после импутации:"
print(colSums(is.na(df_complete_1)))
##   Ozone Solar.R    Wind    Temp 
##       0       0       0       0
print(colSums(is.na(df_complete_2)))
##   Ozone Solar.R    Wind    Temp 
##       0       0       0       0

Задание 8. Пример с мультиколлинеарностью

set.seed(123)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
x3 <- x1 + rnorm(n, sd = 0.1)
x4 <- rnorm(n)
y <- 2*x1 + 3*x2 + rnorm(n)

df_ml <- data.frame(y, x1, x2, x3, x4)

model <- lm(y ~ x1 + x2 + x3 + x4, data = df_ml)
print("Модель множественной линейной регрессии:")
## [1] "Модель множественной линейной регрессии:"
print(summary(model))
## 
## Call:
## lm(formula = y ~ x1 + x2 + x3 + x4, data = df_ml)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.47336 -0.58010  0.07461  0.68778  2.46552 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.11614    0.10000   1.161   0.2484    
## x1           2.28032    1.03822   2.196   0.0305 *  
## x2           2.85849    0.10204  28.012   <2e-16 ***
## x3          -0.50457    1.04676  -0.482   0.6309    
## x4          -0.02333    0.09506  -0.245   0.8067    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9794 on 95 degrees of freedom
## Multiple R-squared:  0.9144, Adjusted R-squared:  0.9108 
## F-statistic: 253.8 on 4 and 95 DF,  p-value: < 2.2e-16
vif_values <- car::vif(model)
print("VIF (Variance Inflation Factor):")
## [1] "VIF (Variance Inflation Factor):"
print(vif_values)
##        x1        x2        x3        x4 
## 92.696750  1.004920 92.714680  1.006429
print("VIF > 10 указывает на проблемную мультиколлинеарность.")
## [1] "VIF > 10 указывает на проблемную мультиколлинеарность."
eigen_values <- eigen(cor(df_ml[, -1]))$values
print("Собственные значения корреляционной матрицы:")
## [1] "Собственные значения корреляционной матрицы:"
print(eigen_values)
## [1] 2.003925603 1.034485302 0.956181096 0.005407999
if (min(eigen_values) < 0.05) {
  print("Минимальное собственное значение < 0.05, что подтверждает мультиколлинеарность.")
}
## [1] "Минимальное собственное значение < 0.05, что подтверждает мультиколлинеарность."
model_corrected <- lm(y ~ x1 + x2 + x4, data = df_ml)
print("Скорректированная модель (без x3):")
## [1] "Скорректированная модель (без x3):"
print(summary(model_corrected))
## 
## Call:
## lm(formula = y ~ x1 + x2 + x4, data = df_ml)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.47367 -0.58303  0.02779  0.64393  2.50255 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.10939    0.09862   1.109    0.270    
## x1           1.78259    0.10763  16.562   <2e-16 ***
## x2           2.85718    0.10160  28.122   <2e-16 ***
## x4          -0.02094    0.09455  -0.221    0.825    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9755 on 96 degrees of freedom
## Multiple R-squared:  0.9142, Adjusted R-squared:  0.9115 
## F-statistic:   341 on 3 and 96 DF,  p-value: < 2.2e-16
print("VIF для новой модели:")
## [1] "VIF для новой модели:"
print(car::vif(model_corrected))
##       x1       x2       x4 
## 1.004231 1.004209 1.003696