и его применение в биоинформатике
Материалы для самостоятельного изучения
Анна Валяева
17 октября 2025
# 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 и прочие справки…