и его применение в биоинформатике
Материалы для самостоятельного изучения
Анна Валяева
18 октября 2024
# A tibble: 3 × 52
weight_date Agatha Angelique `Annabel Lee` `Ardrey-A` Ardrey `Bellatrix-A`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
1 weight_1 1060 2920 944 98 3000 NA
2 weight_2 1860 2940 1180 98 2780 NA
3 weight_3 2000 209 1689 95 666 NA
# ℹ 45 more variables: `Bellatrix-B` <lgl>, `Bellatrix-C` <lgl>,
# Bellatrix <dbl>, `Blue Devil` <dbl>, Caliban <dbl>, Claudia <dbl>,
# Cruella <dbl>, Damien <lgl>, Elphaba <dbl>, Endora <dbl>, Goblin <dbl>,
# Grendel <dbl>, Hitchcock <dbl>, Ichabod <dbl>, Imp <lgl>, Kali <dbl>,
# Kambana <lgl>, Loki <lgl>, Lucrezia <dbl>, Medea <dbl>, Medusa <dbl>,
# Mephistopheles <dbl>, Merlin <dbl>, Morticia <dbl>, Niffy <lgl>,
# `Norman Bates` <dbl>, Nosferatu <dbl>, `Ozma-A` <dbl>, Ozma <dbl>, …
Очень широкий датафрейм, работать с таким форматом не всегда удобно.
Как привести его к форме name-weight_1-weight_2-weight_3?
# A tibble: 3 × 52
weight_date Agatha Angelique `Annabel Lee` `Ardrey-A` Ardrey `Bellatrix-A`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
1 weight_1 1060 2920 944 98 3000 NA
2 weight_2 1860 2940 1180 98 2780 NA
3 weight_3 2000 209 1689 95 666 NA
# ℹ 45 more variables: `Bellatrix-B` <lgl>, `Bellatrix-C` <lgl>,
# Bellatrix <dbl>, `Blue Devil` <dbl>, Caliban <dbl>, Claudia <dbl>,
# Cruella <dbl>, Damien <lgl>, Elphaba <dbl>, Endora <dbl>, Goblin <dbl>,
# Grendel <dbl>, Hitchcock <dbl>, Ichabod <dbl>, Imp <lgl>, Kali <dbl>,
# Kambana <lgl>, Loki <lgl>, Lucrezia <dbl>, Medea <dbl>, Medusa <dbl>,
# Mephistopheles <dbl>, Merlin <dbl>, Morticia <dbl>, Niffy <lgl>,
# `Norman Bates` <dbl>, Nosferatu <dbl>, `Ozma-A` <dbl>, Ozma <dbl>, …
Как привести его к форме name-weight_1-weight_2-weight_3?
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
4 Ardrey-A 98 98 95
5 Ardrey 3000 2780 666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 585 2760 2460
10 Blue Devil 1330 1820 2460
# ℹ 41 more rows
Как привести его к форме name-weight_1-weight_2-weight_3?
lemurs_weights <- lemurs_weights_wide %>%
pivot_longer(-weight_date) %>%
pivot_wider(names_from = weight_date, values_from = value)
lemurs_weights
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
4 Ardrey-A 98 98 95
5 Ardrey 3000 2780 666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 585 2760 2460
10 Blue Devil 1330 1820 2460
# ℹ 41 more rows
where(is.character)
, where(is.numeric)
, …starts_with("pattern")
- начинается с patternends_with("pattern")
- заканчивается на patterncontains("pattern")
- содержит подслово patternmatches("pattern")
- находится по регулярному выражению patternnum_range()
- поиск по общему префиксу среди столбцов с некой нумерацией# A tibble: 1 × 1
weight_3
<dbl>
1 2000
Устаревшее:
all_of()
или any_of()
.Задача: по 3 взвешиваниям посчитать средний вес каждого лемура.
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
4 Ardrey-A 98 98 95
5 Ardrey 3000 2780 666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 585 2760 2460
10 Blue Devil 1330 1820 2460
# ℹ 41 more rows
Задача: по 3 взвешиваниям посчитать средний вес каждого лемура.
Получилось что-то странное…
# A tibble: 51 × 5
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1530
2 Angelique 2920 2940 209 1530
3 Annabel Lee 944 1180 1689 1530
4 Ardrey-A 98 98 95 1530
5 Ardrey 3000 2780 666 1530
6 Bellatrix-A NA NA NA 1530
7 Bellatrix-B NA NA NA 1530
8 Bellatrix-C NA NA NA 1530
9 Bellatrix 585 2760 2460 1530
10 Blue Devil 1330 1820 2460 1530
# ℹ 41 more rows
Задача: по 3 взвешиваниям посчитать средний вес каждого лемура.
Получилось верно, но как-то глупо считать среднее “вручную”…
# A tibble: 51 × 5
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1640
2 Angelique 2920 2940 209 2023
3 Annabel Lee 944 1180 1689 1271
4 Ardrey-A 98 98 95 97
5 Ardrey 3000 2780 666 2149.
6 Bellatrix-A NA NA NA NA
7 Bellatrix-B NA NA NA NA
8 Bellatrix-C NA NA NA NA
9 Bellatrix 585 2760 2460 1935
10 Blue Devil 1330 1820 2460 1870
# ℹ 41 more rows
Группируем построчно и для каждой строки считаем среднее. Каждый лемур сам себе группа.
lemurs_weights %>%
rowwise() %>%
mutate(
avg_weight = mean(c(weight_1, weight_2, weight_3), na.rm = TRUE))
# A tibble: 51 × 5
# Rowwise:
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1640
2 Angelique 2920 2940 209 2023
3 Annabel Lee 944 1180 1689 1271
4 Ardrey-A 98 98 95 97
5 Ardrey 3000 2780 666 2149.
6 Bellatrix-A NA NA NA NaN
7 Bellatrix-B NA NA NA NaN
8 Bellatrix-C NA NA NA NaN
9 Bellatrix 585 2760 2460 1935
10 Blue Devil 1330 1820 2460 1870
# ℹ 41 more rows
c_across()
позволяет отбирать столбцы по-умному (как срез, по типу данных, …).
lemurs_weights %>%
rowwise() %>%
mutate(
avg_weight = mean(c_across(weight_1:weight_3), na.rm = TRUE))
# A tibble: 51 × 5
# Rowwise:
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1640
2 Angelique 2920 2940 209 2023
3 Annabel Lee 944 1180 1689 1271
4 Ardrey-A 98 98 95 97
5 Ardrey 3000 2780 666 2149.
6 Bellatrix-A NA NA NA NaN
7 Bellatrix-B NA NA NA NaN
8 Bellatrix-C NA NA NA NaN
9 Bellatrix 585 2760 2460 1935
10 Blue Devil 1330 1820 2460 1870
# ℹ 41 more rows
c_across()
позволяет отбирать столбцы по-умному (как срез, по типу данных, …).
lemurs_weights %>%
rowwise() %>%
mutate(
avg_weight = mean(c_across(where(is.numeric)), na.rm = TRUE))
# A tibble: 51 × 5
# Rowwise:
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1640
2 Angelique 2920 2940 209 2023
3 Annabel Lee 944 1180 1689 1271
4 Ardrey-A 98 98 95 97
5 Ardrey 3000 2780 666 2149.
6 Bellatrix-A NA NA NA NaN
7 Bellatrix-B NA NA NA NaN
8 Bellatrix-C NA NA NA NaN
9 Bellatrix 585 2760 2460 1935
10 Blue Devil 1330 1820 2460 1870
# ℹ 41 more rows
rowwise()
создает группировку, которую умеет снимать summarise()
или ungroup()
.
lemurs_weights %>%
rowwise() %>%
mutate(
avg_weight = mean(c_across(where(is.numeric)), na.rm = TRUE)) %>%
ungroup()
# A tibble: 51 × 5
name weight_1 weight_2 weight_3 avg_weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1640
2 Angelique 2920 2940 209 2023
3 Annabel Lee 944 1180 1689 1271
4 Ardrey-A 98 98 95 97
5 Ardrey 3000 2780 666 2149.
6 Bellatrix-A NA NA NA NaN
7 Bellatrix-B NA NA NA NaN
8 Bellatrix-C NA NA NA NaN
9 Bellatrix 585 2760 2460 1935
10 Blue Devil 1330 1820 2460 1870
# ℹ 41 more rows
Столбцы перезаписываются.
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <chr> <chr> <chr>
1 AGATHA 1060 1860 2000
2 ANGELIQUE 2920 2940 209
3 ANNABEL LEE 944 1180 1689
4 ARDREY-A 98 98 95
5 ARDREY 3000 2780 666
6 BELLATRIX-A <NA> <NA> <NA>
7 BELLATRIX-B <NA> <NA> <NA>
8 BELLATRIX-C <NA> <NA> <NA>
9 BELLATRIX 585 2760 2460
10 BLUE DEVIL 1330 1820 2460
# ℹ 41 more rows
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 AGATHA 1060 1860 2000
2 ANGELIQUE 2920 2940 209
3 ANNABEL LEE 944 1180 1689
4 ARDREY-A 98 98 95
5 ARDREY 3000 2780 666
6 BELLATRIX-A NA NA NA
7 BELLATRIX-B NA NA NA
8 BELLATRIX-C NA NA NA
9 BELLATRIX 585 2760 2460
10 BLUE DEVIL 1330 1820 2460
# ℹ 41 more rows
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
4 Ardrey-A 98 98 95
5 Ardrey 3000 2780 666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 585 2760 2460
10 Blue Devil 1330 1820 2460
# ℹ 41 more rows
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1.06 1.86 2
2 Angelique 2.92 2.94 0.209
3 Annabel Lee 0.944 1.18 1.69
4 Ardrey-A 0.098 0.098 0.095
5 Ardrey 3 2.78 0.666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 0.585 2.76 2.46
10 Blue Devil 1.33 1.82 2.46
# ℹ 41 more rows
# A tibble: 51 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1.06 1.86 2
2 Angelique 2.92 2.94 0.209
3 Annabel Lee 0.944 1.18 1.69
4 Ardrey-A 0.098 0.098 0.095
5 Ardrey 3 2.78 0.666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 0.585 2.76 2.46
10 Blue Devil 1.33 1.82 2.46
# ℹ 41 more rows
При использовании list(...)
или при указании .names = ...
создаются новые столбцы.
# A tibble: 51 × 7
name weight_1 weight_2 weight_3 weight_1_kg weight_2_kg weight_3_kg
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1.06 1.86 2
2 Angelique 2920 2940 209 2.92 2.94 0.209
3 Annabel Lee 944 1180 1689 0.944 1.18 1.69
4 Ardrey-A 98 98 95 0.098 0.098 0.095
5 Ardrey 3000 2780 666 3 2.78 0.666
6 Bellatrix-A NA NA NA NA NA NA
7 Bellatrix-B NA NA NA NA NA NA
8 Bellatrix-C NA NA NA NA NA NA
9 Bellatrix 585 2760 2460 0.585 2.76 2.46
10 Blue Devil 1330 1820 2460 1.33 1.82 2.46
# ℹ 41 more rows
Сначала указываем, как модифицировать названия столбцов, затем - какие столбцы.
lemurs_weights %>%
mutate(across(starts_with("weight"), list(kg = ~ .x/1000))) %>%
rename_with(~ str_c("KG_", str_remove(., "_kg")), ends_with("kg"))
# A tibble: 51 × 7
name weight_1 weight_2 weight_3 KG_weight_1 KG_weight_2 KG_weight_3
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000 1.06 1.86 2
2 Angelique 2920 2940 209 2.92 2.94 0.209
3 Annabel Lee 944 1180 1689 0.944 1.18 1.69
4 Ardrey-A 98 98 95 0.098 0.098 0.095
5 Ardrey 3000 2780 666 3 2.78 0.666
6 Bellatrix-A NA NA NA NA NA NA
7 Bellatrix-B NA NA NA NA NA NA
8 Bellatrix-C NA NA NA NA NA NA
9 Bellatrix 585 2760 2460 0.585 2.76 2.46
10 Blue Devil 1330 1820 2460 1.33 1.82 2.46
# ℹ 41 more rows
transmute
оставляет только перечисленные и новые столбцы.
lemurs_weights %>%
transmute(
name,
across(starts_with("weight"), list(kg = ~ .x/1000), .names = "KG_{.col}"))
# A tibble: 51 × 4
name KG_weight_1 KG_weight_2 KG_weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1.06 1.86 2
2 Angelique 2.92 2.94 0.209
3 Annabel Lee 0.944 1.18 1.69
4 Ardrey-A 0.098 0.098 0.095
5 Ardrey 3 2.78 0.666
6 Bellatrix-A NA NA NA
7 Bellatrix-B NA NA NA
8 Bellatrix-C NA NA NA
9 Bellatrix 0.585 2.76 2.46
10 Blue Devil 1.33 1.82 2.46
# ℹ 41 more rows
summarise
по нескольким столбцам с группировкой# A tibble: 51 × 6
name sex weight_1 weight_2 weight_3 birth_type
<chr> <chr> <dbl> <dbl> <dbl> <chr>
1 Nosferatu M 2860 2505 2930 wild
2 Poe M 2700 2610 2680 wild
3 Samantha F 2242 2360 2415 wild
4 Annabel Lee F 944 1180 1689 captive
5 Mephistopheles M 2760 2520 2620 wild
6 Endora F 2600 2360 2645 wild
7 Ozma F 2500 2440 2620 wild
8 Morticia F 2700 2550 2255 wild
9 Blue Devil M 1330 1820 2460 captive
10 Goblin M 1180 1460 1150 captive
# ℹ 41 more rows
summarise
по нескольким столбцам с группировкойlemurs %>%
group_by(sex, birth_type) %>%
summarise(across(starts_with("weight"), mean, na.rm = TRUE))
# A tibble: 5 × 5
# Groups: sex [3]
sex birth_type weight_1 weight_2 weight_3
<chr> <chr> <dbl> <dbl> <dbl>
1 F captive 1604. 1490. 1722.
2 F wild 2510. 2428. 2484.
3 M captive 1893. 1589. 1410.
4 M wild 2773. 2545 2743.
5 <NA> captive NaN NaN NaN
summarise
по нескольким столбцам с группировкойlemurs %>%
drop_na(sex) %>%
group_by(sex, birth_type) %>%
summarise(across(starts_with("weight"), \(x) mean(x, na.rm = TRUE)))
# A tibble: 4 × 5
# Groups: sex [2]
sex birth_type weight_1 weight_2 weight_3
<chr> <chr> <dbl> <dbl> <dbl>
1 F captive 1604. 1490. 1722.
2 F wild 2510. 2428. 2484.
3 M captive 1893. 1589. 1410.
4 M wild 2773. 2545 2743.
summarise
по нескольким столбцам с группировкой…Посчитаем средний вес в разных измерениях по группам, затем посчитаем для этих групп средний вес по измерениям.
lemurs %>%
drop_na(sex) %>%
group_by(sex, birth_type) %>%
summarise(across(starts_with("weight"), mean, na.rm = TRUE)) %>%
ungroup() %>%
rowwise() %>%
mutate(avg_weight = mean(c_across(starts_with("weight")), na.rm = TRUE))
# A tibble: 4 × 6
# Rowwise:
sex birth_type weight_1 weight_2 weight_3 avg_weight
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 F captive 1604. 1490. 1722. 1605.
2 F wild 2510. 2428. 2484. 2474.
3 M captive 1893. 1589. 1410. 1631.
4 M wild 2773. 2545 2743. 2687.
tally()
- количество набюдений (строк) всегоadd_tally()
- добавляется отдельный столбец с общим количеством наблюденийcount()
- количество набюдений (строк) в группеadd_count()
- добавляется отдельный столбец с количеством наблюдений в группеbetween()
near()
# A tibble: 24 × 6
name sex weight_1 weight_2 weight_3 birth_type
<chr> <chr> <dbl> <dbl> <dbl> <chr>
1 Poe M 2700 2610 2680 wild
2 Samantha F 2242 2360 2415 wild
3 Annabel Lee F 944 1180 1689 captive
4 Mephistopheles M 2760 2520 2620 wild
5 Endora F 2600 2360 2645 wild
6 Ozma F 2500 2440 2620 wild
7 Morticia F 2700 2550 2255 wild
8 Blue Devil M 1330 1820 2460 captive
9 Goblin M 1180 1460 1150 captive
10 Cruella F 2050 1350 2340 captive
# ℹ 14 more rows
if_any
оставляет те строки, где хотя бы в одном из указанных столбцов условие выполняется.if_all
оставляет те строки, где во всех указанных столбцах условие выполняется.Все значения должны быть не NA
.
# A tibble: 3 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
Хоть одно значение не NA
.
# A tibble: 37 × 4
name weight_1 weight_2 weight_3
<chr> <dbl> <dbl> <dbl>
1 Agatha 1060 1860 2000
2 Angelique 2920 2940 209
3 Annabel Lee 944 1180 1689
4 Ardrey-A 98 98 95
5 Ardrey 3000 2780 666
6 Bellatrix 585 2760 2460
7 Blue Devil 1330 1820 2460
8 Caliban 2080 296. 641
9 Claudia 740 2550 2390
10 Cruella 2050 1350 2340
# ℹ 27 more rows
?across
и прочие справки…