library(palmerpenguins)Warning: пакет 'palmerpenguins' был собран под R версии 4.3.3
Обработка пропусков на наборе данных Palmer Penguins
library(palmerpenguins)Warning: пакет 'palmerpenguins' был собран под R версии 4.3.3
Набор данных о пингвинах с островов Палмер (Антарктика). Содержит измерения трёх видов: Adelie, Chinstrap, Gentoo.
Ключевые переменные (с пропусками в некоторых столбцах):
species - вид
island - остров
bill_length_mm - длина клюва (мм)
bill_depth_mm - глубина клюва (мм)
flipper_length_mm - длина плавника (мм)
body_mass_g - масса тела (г)
sex - пол
year - год наблюдения
colSums(is.na(penguins)) species island bill_length_mm bill_depth_mm
0 0 2 2
flipper_length_mm body_mass_g sex year
2 2 11 0
Выше представлено количество пропущенных значений в каждом столбце датасета.
Проведена диагностика пропусков с визуализацией. Базовые подходы включали удаление NA и заполнение модой. Глобальная и групповая медиана сравнены после этапа заполнения статистиками, выявив преимущество второго варианта. Визуализация подтвердила корректность группового заполнения.
library(tidyverse)Warning: пакет 'tidyverse' был собран под R версии 4.3.3
Warning: пакет 'ggplot2' был собран под R версии 4.3.3
Warning: пакет 'tibble' был собран под R версии 4.3.2
Warning: пакет 'tidyr' был собран под R версии 4.3.3
Warning: пакет 'readr' был собран под R версии 4.3.3
Warning: пакет 'purrr' был собран под R версии 4.3.2
Warning: пакет 'dplyr' был собран под R версии 4.3.2
Warning: пакет 'stringr' был собран под R версии 4.3.2
Warning: пакет 'forcats' был собран под R версии 4.3.2
Warning: пакет 'lubridate' был собран под R версии 4.3.2
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.0 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(skimr)
library(naniar)Warning: пакет 'naniar' был собран под R версии 4.3.3
Присоединяю пакет: 'naniar'
Следующий объект скрыт от 'package:skimr':
n_complete
arrange(miss_var_summary(penguins), desc(n_miss))# A tibble: 8 × 3
variable n_miss pct_miss
<chr> <int> <num>
1 sex 11 3.20
2 bill_length_mm 2 0.581
3 bill_depth_mm 2 0.581
4 flipper_length_mm 2 0.581
5 body_mass_g 2 0.581
6 species 0 0
7 island 0 0
8 year 0 0
p1 <- gg_miss_var(penguins) +
labs(title = "Доля пропусков по столбцам")
p2 <- vis_miss(penguins) +
labs(title = "Карта пропусков")
print(p1)print(p2)clean_ds <- penguins |> drop_na(bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g)
skim(penguins)| Name | penguins |
| Number of rows | 344 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| factor | 3 |
| numeric | 5 |
| ________________________ | |
| Group variables | None |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| species | 0 | 1.00 | FALSE | 3 | Ade: 152, Gen: 124, Chi: 68 |
| island | 0 | 1.00 | FALSE | 3 | Bis: 168, Dre: 124, Tor: 52 |
| sex | 11 | 0.97 | FALSE | 2 | mal: 168, fem: 165 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| bill_length_mm | 2 | 0.99 | 43.92 | 5.46 | 32.1 | 39.23 | 44.45 | 48.5 | 59.6 | ▃▇▇▆▁ |
| bill_depth_mm | 2 | 0.99 | 17.15 | 1.97 | 13.1 | 15.60 | 17.30 | 18.7 | 21.5 | ▅▅▇▇▂ |
| flipper_length_mm | 2 | 0.99 | 200.92 | 14.06 | 172.0 | 190.00 | 197.00 | 213.0 | 231.0 | ▂▇▃▅▂ |
| body_mass_g | 2 | 0.99 | 4201.75 | 801.95 | 2700.0 | 3550.00 | 4050.00 | 4750.0 | 6300.0 | ▃▇▆▃▂ |
| year | 0 | 1.00 | 2008.03 | 0.82 | 2007.0 | 2007.00 | 2008.00 | 2009.0 | 2009.0 | ▇▁▇▁▇ |
skim(clean_ds)| Name | clean_ds |
| Number of rows | 342 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| factor | 3 |
| numeric | 5 |
| ________________________ | |
| Group variables | None |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| species | 0 | 1.00 | FALSE | 3 | Ade: 151, Gen: 123, Chi: 68 |
| island | 0 | 1.00 | FALSE | 3 | Bis: 167, Dre: 124, Tor: 51 |
| sex | 9 | 0.97 | FALSE | 2 | mal: 168, fem: 165 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| bill_length_mm | 0 | 1 | 43.92 | 5.46 | 32.1 | 39.23 | 44.45 | 48.5 | 59.6 | ▃▇▇▆▁ |
| bill_depth_mm | 0 | 1 | 17.15 | 1.97 | 13.1 | 15.60 | 17.30 | 18.7 | 21.5 | ▅▅▇▇▂ |
| flipper_length_mm | 0 | 1 | 200.92 | 14.06 | 172.0 | 190.00 | 197.00 | 213.0 | 231.0 | ▂▇▃▅▂ |
| body_mass_g | 0 | 1 | 4201.75 | 801.95 | 2700.0 | 3550.00 | 4050.00 | 4750.0 | 6300.0 | ▃▇▆▃▂ |
| year | 0 | 1 | 2008.03 | 0.82 | 2007.0 | 2007.00 | 2008.00 | 2009.0 | 2009.0 | ▇▁▇▁▇ |
mode_val <- function(x) {
ux <- na.omit(x); if (length(ux) == 0) return(NA)
names(sort(table(ux), decreasing = TRUE))[1]
}
penguins_mode <- penguins |>
mutate(
sex = if_else(is.na(sex), mode_val(sex), sex)
)
p1 <- ggplot(penguins, aes(x = sex, fill = sex)) +
geom_bar() + labs(title = "До заполнения")
p2 <- ggplot(penguins_mode, aes(x = sex, fill = sex)) +
geom_bar() + labs(title = "После заполнения")
print(p1)print(p2)penguins_median <- penguins |> mutate(across(where(is.numeric), ~if_else(is.na(.), median(., na.rm = TRUE), .)))
pp <- bind_rows(
penguins |> mutate(period = "До"),
penguins_median |> mutate(period = "После")
)
ggplot(pp, aes(x = bill_length_mm, fill = period)) +
geom_histogram(position = "identity", alpha = 0.7, bins = 30)Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_bin()`).
penguins_group_med <- penguins |>
group_by(species) |>
mutate(across(where(is.numeric), ~if_else(is.na(.x), median(.x, na.rm = TRUE), .x))) |>
ungroup()
penguins |> group_by(species) |> summarise(med_body_mass = median(body_mass_g, na.rm = TRUE))# A tibble: 3 × 2
species med_body_mass
<fct> <dbl>
1 Adelie 3700
2 Chinstrap 3700
3 Gentoo 5000
penguins_group_med |> group_by(species) |> summarise(med_body_mass = median(body_mass_g, na.rm = TRUE))# A tibble: 3 × 2
species med_body_mass
<fct> <dbl>
1 Adelie 3700
2 Chinstrap 3700
3 Gentoo 5000
penguins_global <- penguins |> mutate(bill_depth_mm = if_else(is.na(bill_depth_mm), median(bill_depth_mm, na.rm = TRUE), bill_depth_mm))
penguins_group <- penguins |> group_by(species) |>
mutate(bill_depth_mm = if_else(is.na(bill_depth_mm), median(bill_depth_mm, na.rm = TRUE), bill_depth_mm)) |>
ungroup()
bind_rows(
penguins |> mutate(method = "original"),
penguins_global |> mutate(method = "global"),
penguins_group |> mutate(method = "group")
) |>
group_by(method, species) |>
summarise(
mean = mean(bill_depth_mm),
median = median(bill_depth_mm),
.groups = "drop"
) |>
pivot_wider(
names_from = method,
values_from = c(mean, median)
)# A tibble: 3 × 7
species mean_global mean_group mean_original median_global median_group
<fct> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Adelie 18.3 18.3 NA 18.4 18.4
2 Chinstrap 18.4 18.4 18.4 18.4 18.4
3 Gentoo 15.0 15.0 NA 15 15
# ℹ 1 more variable: median_original <dbl>
pp <- penguins |>
group_by(species) |>
mutate(across(where(is.numeric), ~if_else(is.na(.), median(., na.rm = TRUE), .))) |>
ungroup()
p1 <- ggplot(pp, aes(x = species, y = body_mass_g, fill = sex)) +
geom_boxplot() +
facet_wrap(~ species, scales = "free") +
labs(
title = "Распределение массы тела по видам и полу",
x = "Вид пингвинов",
y = "Масса тела",
fill = "Пол"
)
print(p1)ggsave("p1.png", p1, width = 8, height = 6, dpi = 300)
p2 <- ggplot(pp, aes(x = flipper_length_mm, y = body_mass_g, color = species)) +
geom_point(alpha = 0.7) +
labs(title = "Зависимость массы тела от длины ласта",
x = "Длина ласта",
y = "Масса тела",
color = "Вид"
)
print(p2)ggsave("p2.png", p2, width = 8, height = 6, dpi = 300)
p3 <- ggplot(pp, aes(x = bill_length_mm, fill = species, color = species)) +
geom_density(alpha = 0.5) +
labs(
title = "Распределение длины клюва по видам пингвинов",
x = "Длина клюва",
y = "Плотность",
fill = "Вид",
color = "Вид"
) +
theme_minimal()
print(p3)ggsave("p3.png", p3, width = 8, height = 6, dpi = 300)https://ggplot2.tidyverse.org/
https://search.r-project.org/CRAN/refmans/ggplot2/html/ggsave.html