vec <- c(5, 8, NA, 12, 15, NA, 20, 25)
vec
## [1] 5 8 NA 12 15 NA 20 25
Вывод: создан числовой вектор, содержащий значения и пропуски (NA).
is.na(vec)
## [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE
vec_clean <- vec[!is.na(vec)]
vec_clean
## [1] 5 8 12 15 20 25
Вывод: is.na() возвращает логический
вектор, по которому можно удалить NA и получить “чистые” данные.
df <- data.frame(
id = c(101, 102, 103, 104, 105),
score = c(4.5, NA, 3.8, 4.9, NA),
name = c("Ivan", "Olga", NA, "Maria", "Alex")
)
df
## id score name
## 1 101 4.5 Ivan
## 2 102 NA Olga
## 3 103 3.8 <NA>
## 4 104 4.9 Maria
## 5 105 NA Alex
complete.cases(df)
## [1] TRUE FALSE FALSE TRUE FALSE
df_clean <- df[complete.cases(df), ]
df_clean
## id score name
## 1 101 4.5 Ivan
## 4 104 4.9 Maria
Вывод: complete.cases() оставляет
строки без пропусков.
library(caret)
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
##
colSums(is.na(airquality))
## Ozone Solar.R Wind Temp Month Day
## 37 7 0 0 0 0
air_mean <- airquality
num_cols <- sapply(air_mean, is.numeric)
for (col in names(air_mean)[num_cols]) {
air_mean[[col]][is.na(air_mean[[col]])] <- mean(air_mean[[col]], na.rm = TRUE)
}
colSums(is.na(air_mean))
## Ozone Solar.R Wind Temp Month Day
## 0 0 0 0 0 0
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
pre_median <- preProcess(airquality, method = "medianImpute")
air_median <- predict(pre_median, airquality)
colSums(is.na(air_median))
## Ozone Solar.R Wind Temp Month Day
## 0 0 0 0 0 0
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
Вывод: после заполнения пропусков количество NA стало равно нулю. Замена медианой более устойчива к выбросам, чем замена средним.
set.seed(42)
a <- c(rnorm(50, mean=10, sd=2), 35, 40)
b <- c(rnorm(50, mean=100, sd=10), 180, 220)
boxplot(a, main="Набор a (с выбросами)")
boxplot(b, main="Набор b (с выбросами)")
Найдём выбросы:
out_a <- boxplot.stats(a)$out
out_b <- boxplot.stats(b)$out
out_a
## [1] 35 40
out_b
## [1] 70.0691 180.0000 220.0000
Удалим выбросы и построим boxplot повторно:
a_no_out <- a[!(a %in% out_a)]
b_no_out <- b[!(b %in% out_b)]
boxplot(a_no_out, main="Набор a (без выбросов)")
boxplot(b_no_out, main="Набор b (без выбросов)")
Вывод: boxplot позволяет выявить выбросы, а
boxplot.stats()$out — получить их значения и удалить из
данных.
dup_df <- data.frame(
id = c(1, 2, 2, 3, 4, 4, 5),
name = c("Ann", "Bob", "Bob", "Kate", "Tom", "Tom", "Max")
)
dup_df
## id name
## 1 1 Ann
## 2 2 Bob
## 3 2 Bob
## 4 3 Kate
## 5 4 Tom
## 6 4 Tom
## 7 5 Max
Удаление дублей через unique():
unique_df <- unique(dup_df)
unique_df
## id name
## 1 1 Ann
## 2 2 Bob
## 4 3 Kate
## 5 4 Tom
## 7 5 Max
Удаление дублей через duplicated():
dup_removed <- dup_df[!duplicated(dup_df), ]
dup_removed
## id name
## 1 1 Ann
## 2 2 Bob
## 4 3 Kate
## 5 4 Tom
## 7 5 Max
Сравнение:
identical(unique_df, dup_removed)
## [1] TRUE
Вывод: оба метода дают одинаковый результат — остаются только уникальные строки.
library(mice)
df_mice <- data.frame(
x1 = c(1, 2, NA, 4, 5),
x2 = c(NA, 1, 2, 3, 4),
group = c("A", "A", "B", "B", "B")
)
df_mice
## x1 x2 group
## 1 1 NA A
## 2 2 1 A
## 3 NA 2 B
## 4 4 3 B
## 5 5 4 B
Импутация:
imp <- mice(df_mice, m=3, method="pmm", seed=42)
##
## iter imp variable
## 1 1 x1
## 1 2 x1
## 1 3 x1
## 2 1 x1
## 2 2 x1
## 2 3 x1
## 3 1 x1
## 3 2 x1
## 3 3 x1
## 4 1 x1
## 4 2 x1
## 4 3 x1
## 5 1 x1
## 5 2 x1
## 5 3 x1
completed <- complete(imp, 1)
completed
## x1 x2 group
## 1 1 NA A
## 2 2 1 A
## 3 5 2 B
## 4 4 3 B
## 5 5 4 B
Вывод: mice выполняет множественную
импутацию, восстанавливая пропуски на основе связей между
признаками.
set.seed(100)
n <- 100
x1 <- rnorm(n)
x2 <- x1 * 0.95 + rnorm(n, sd=0.05)
x3 <- rnorm(n)
y <- 3*x1 + rnorm(n)
mc_df <- data.frame(y, x1, x2, x3)
cor(mc_df[, c("x1","x2","x3")])
## x1 x2 x3
## x1 1.0000000 0.99916444 0.10679137
## x2 0.9991644 1.00000000 0.09632181
## x3 0.1067914 0.09632181 1.00000000
Линейная модель:
model <- lm(y ~ x1 + x2 + x3, data=mc_df)
summary(model)
##
## Call:
## lm(formula = y ~ x1 + x2 + x3, data = mc_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.6057 -0.6113 -0.0340 0.6866 3.4316
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.08296 0.10877 -0.763 0.447
## x1 1.51746 2.71255 0.559 0.577
## x2 1.62474 2.86576 0.567 0.572
## x3 -0.10681 0.10939 -0.976 0.331
##
## Residual standard error: 1.087 on 96 degrees of freedom
## Multiple R-squared: 0.8938, Adjusted R-squared: 0.8905
## F-statistic: 269.4 on 3 and 96 DF, p-value: < 2.2e-16
VIF:
if (!requireNamespace("car", quietly = TRUE)) install.packages("car")
library(car)
vif(model)
## x1 x2 x3
## 641.816764 640.439156 1.082145
Вывод: при высокой корреляции признаков VIF становится большим (часто >5 или >10), что указывает на мультиколлинеарность и может ухудшать интерпретацию коэффициентов модели.