1. Краткое описание данных
(Кто/что измеряется, какие основные поля, где пропуски.)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.1 ✔ stringr 1.5.2
✔ ggplot2 4.0.0 ✔ tibble 3.3.0
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.1.0
── 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
Присоединяю пакет: 'palmerpenguins'
Следующие объекты скрыты от 'package:datasets':
penguins, penguins_raw
library (skimr)
library (naniar)
Присоединяю пакет: 'naniar'
Следующий объект скрыт от 'package:skimr':
n_complete
library (ggplot2)
library (dplyr)
library (tidyr)
data (penguins)
penguins |> head ()
# A tibble: 6 × 8
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
<fct> <fct> <dbl> <dbl> <int> <int>
1 Adelie Torgersen 39.1 18.7 181 3750
2 Adelie Torgersen 39.5 17.4 186 3800
3 Adelie Torgersen 40.3 18 195 3250
4 Adelie Torgersen NA NA NA NA
5 Adelie Torgersen 36.7 19.3 193 3450
6 Adelie Torgersen 39.3 20.6 190 3650
# ℹ 2 more variables: sex <fct>, year <int>
Data summary
Name
penguins
Number of rows
344
Number of columns
8
_______________________
Column type frequency:
factor
3
numeric
5
________________________
Group variables
None
Variable type: factor
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
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
▇▁▇▁▇
2. Ход работы
(Кратко: диагностика → базовые подходы → заполнение медианой → групповая медиана → сравнение → визуализация.)
3. Результаты
3.1. Диагностика
Таблица/рисунки с пропусками…
naniar:: gg_miss_var (penguins) + ggtitle ("Доля пропусков по столбцам" )
naniar:: vis_miss (penguins) + ggtitle ("Карта пропусков (NA)" )
sort (colSums (is.na (penguins)), decreasing= TRUE )
sex bill_length_mm bill_depth_mm flipper_length_mm
11 2 2 2
body_mass_g species island year
2 0 0 0
Пропусков больше всего в колонке sex. ### 3.2. Базовые подходы
Размерность после drop_na, распределение sex до/после…
mode_val <- function (x) {
ux <- na.omit (x); if (length (ux) == 0 ) return (NA )
names (sort (table (ux), decreasing = TRUE ))[1 ]
}
penguins_drop <- penguins |> drop_na (bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g)
dim (penguins)
penguins_mode <- penguins |>
mutate (
sex = if_else (is.na (sex), mode_val (sex), sex)
)
ggplot (penguins, aes (x = sex)) +
geom_bar (fill = "skyblue" ) +
labs (title = "Распределение переменной sex (до преобразований)" ,
x = "Пол" , y = "Количество" ) +
theme_minimal ()
ggplot (penguins_mode, aes (x = sex)) +
geom_bar (fill = "skyblue" ) +
labs (title = "Распределение переменной sex (до преобразований)" ,
x = "Пол" , y = "Количество" ) +
theme_minimal ()
3.3. Заполнение статистиками
Гистограмма/таблица до/после заполнения медианой…
medians <- penguins |> summarise (across (where (is.numeric), ~ median (.x, na.rm = TRUE )))
penguins_med <- penguins |> mutate (across (where (is.numeric), ~ replace_na (.x, medians[[cur_column ()]])))
penguins_original = penguins
penguins_original$ state <- "До заполнения"
penguins_med$ state <- "После заполнения"
penguins_combined <- bind_rows (penguins_original, penguins_med)
facet_hist = ggplot (penguins_combined, aes (x = bill_length_mm)) +
geom_histogram (bins = 30 , fill = "steelblue" , color = "white" ) +
facet_wrap (~ state, ncol = 1 ) +
labs (title = "Распределение bill_length_mm до и после заполнения" ,
x = "bill_length_mm" ,
y = "Количество наблюдений" ) +
theme_minimal ()
facet_hist
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 ()
# медианы в оригинальных данных
med_original <- penguins %>%
group_by (species) %>%
summarise (across (where (is.numeric), ~ median (.x, na.rm = TRUE ), .names = "orig_{.col}" ))
# медианы в обработанных данных
med_filled <- penguins_group_med %>%
group_by (species) %>%
summarise (across (where (is.numeric), ~ median (.x, na.rm = TRUE ), .names = "filled_{.col}" ))
# объединяем в одну таблицу
comparison_table <- med_original %>%
left_join (med_filled, by = "species" )
comparison_table %>% select (species, orig_body_mass_g, filled_body_mass_g)
# A tibble: 3 × 3
species orig_body_mass_g filled_body_mass_g
<fct> <dbl> <dbl>
1 Adelie 3700 3700
2 Chinstrap 3700 3700
3 Gentoo 5000 5000
3.4. Сравнение стратегий
# penguins penguins_med penguins_group_med
# Создаем обобщенную таблицу со всеми статистиками
summary_table <- bind_rows (
# Оригинальные данные
penguins %>%
group_by (species) %>%
summarise (
mean_value = mean (bill_depth_mm, na.rm = TRUE ),
median_value = median (bill_depth_mm, na.rm = TRUE ),
dataset = "orig"
),
# penguins_med
penguins_med %>%
group_by (species) %>%
summarise (
mean_value = mean (bill_depth_mm, na.rm = TRUE ),
median_value = median (bill_depth_mm, na.rm = TRUE ),
dataset = "med"
),
# penguins_group_med
penguins_group_med %>%
group_by (species) %>%
summarise (
mean_value = mean (bill_depth_mm, na.rm = TRUE ),
median_value = median (bill_depth_mm, na.rm = TRUE ),
dataset = "group_med"
)
) %>%
pivot_wider (
names_from = dataset,
values_from = c (mean_value, median_value),
names_glue = "{dataset}_{.value}"
)
print (summary_table)
# A tibble: 3 × 7
species orig_mean_value med_mean_value group_med_mean_value orig_median_value
<fct> <dbl> <dbl> <dbl> <dbl>
1 Adelie 18.3 18.3 18.3 18.4
2 Chinstr… 18.4 18.4 18.4 18.4
3 Gentoo 15.0 15.0 15.0 15
# ℹ 2 more variables: med_median_value <dbl>, group_med_median_value <dbl>
Сводная таблица mean/median по видам…
3.5. Визуализация
Boxplot по видам/полу (вставьте сохранённые изображения).
box_plot = ggplot (penguins_group_med, aes (x = species, y = body_mass_g, fill = sex)) +
geom_boxplot () +
labs (
title = "Распределение массы тела пингвинов" ,
subtitle = "После группового заполнения пропущенных значений" ,
x = "Вид пингвина" ,
y = "Масса тела (г)" ,
fill = "Пол"
) +
theme_minimal ()
box_plot
4. Выводы
(2–5 тезисов: какая стратегия адекватнее для набора, как изменились распределения и т.п.)
ggsave ("my_ggplot_box_plot.png" , plot = box_plot, width = 8 , height = 6 , dpi = 300 )
ggsave ("my_ggplot_facet_hist.png" , plot= facet_hist, width= 8 , height= 6 , dpi= 300 )
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_bin()`).
-наиболее эффективная стратегия - заполнять медианами по группам, в этом случае можно получить наиболее вероятные заполенния в данных(my_ggplot_facet_hist.png) -после заполнений распределения изменились незначительно, так как пропусков было мало(my_ggplot_box_plot.png) ## 5. Ссылки (если использовались)
(Документация, статьи, заметки.)