13 Группирование данных
На этой странице рассматривается группирование и агрегирование данных для описательного анализа. Для этого используется семейство пакетов tidyverse, где есть часто применяемые и простые в использовании функции.
Группирование данных - ключевой компонент управления и анализа данных. Группированные данные статистически резюмируются по группам, а также могут быть отражены на графике по группам. Функции из пакета dplyr (является частью tidyverse) существенно облегчают группирование и дальнейшие операции.
На этой странице мы рассмотрим следующие темы:
- Группирование данных с помощью функции
group_by()
- Разгруппирование данных
-
summarise()
реюмирование группированных данных со статистикой
- Разница между
count()
иtally()
-
arrange()
применительно к группированным данным
-
filter()
применительно к группированным данным
-
mutate()
применительно к группированным данным
-
select()
применительно к группированным данным
- Команда
aggregate()
из базового R как альтернатива
13.1 Подготовка
Загрузка пакетов
Данный фрагмент кода показывает загрузку пакетов, необходимых для анализа. В данном руководстве мы фокусируемся на использовании p_load()
из пакета pacman, которая устанавливает пакет, если необходимо, и загружает его для использования. Вы можете также загрузить установленные пакеты с помощью library()
из базового R. См. страницу Основы R для получения дополнительной информации о пакетах R.
::p_load(
pacman# для импорта данных
rio, # для расположения файла
here, # для вычистки, работы с данными и построения графиков (включает dplyr)
tidyverse, # добавление строк и столбцов с итогами janitor)
Импорт данных
Мы импортируем набор данных о случаях имитированной эпидемии Эболы. Если вы хотите параллельно выполнять действия, кликните, чтобы скачать “чистый” построчный список (as .rds file). Набор данных импортируется с помощью функции import()
из пакета rio. См. страницу Импорт и экспорт, где указаны разные способы импорта данных.
<- import("linelist_cleaned.rds") linelist
Первые 50 строк linelist
:
13.2 Группирование
Функция group_by()
из пакета dplyr группирует строки по уникальным значениям в указанном для функции столбце. Если указаны несколько столбцов, строки группируются по уникальным комбинациям значений по всем столбцам. Каждое уникальное значение (или комбинация значений) составляет группу. Дальнейшие изменения в наборе данных или расчетах затем можно проводить в контексте каждой группы.
Например, команда ниже берет linelist
и группирует строки по уникальным значениям в столбце outcome
, сохраняя выходные данные как новый датафрейм ll_by_outcome
. Столбец(цы), по которым идет группирование, размещаются внутри скобок функции group_by()
.
<- linelist %>%
ll_by_outcome group_by(outcome)
Обратите внимание, что в наборе данных нет видимых изменений после выполнения group_by()
, пока не будет применена другая глагольная функция dplyr, такая как mutate()
, summarise()
, либо arrange()
к “группированному” датафрейму.
Однако вы можете “увидеть” группирование, напечатав датафрейм. Когда вы печатаете сгруппированный датафрейм, вы увидите, что он превратился в объект класса tibble
который при печати отображает, какое группирование применено и сколько существует групп - это пишется над строкой заголовка.
# печать, чтобы увидеть, какие группы активны
ll_by_outcome
# A tibble: 5,888 × 30
# Groups: outcome [3]
case_id generation date_infection date_onset date_hospitalisation
<chr> <dbl> <date> <date> <date>
1 5fe599 4 2014-05-08 2014-05-13 2014-05-15
2 8689b7 4 NA 2014-05-13 2014-05-14
3 11f8ea 2 NA 2014-05-16 2014-05-18
4 b8812a 3 2014-05-04 2014-05-18 2014-05-20
5 893f25 3 2014-05-18 2014-05-21 2014-05-22
6 be99c8 3 2014-05-03 2014-05-22 2014-05-23
7 07e3e8 4 2014-05-22 2014-05-27 2014-05-29
8 369449 4 2014-05-28 2014-06-02 2014-06-03
9 f393b4 4 NA 2014-06-05 2014-06-06
10 1389ca 4 NA 2014-06-05 2014-06-07
# ℹ 5,878 more rows
# ℹ 25 more variables: date_outcome <date>, outcome <chr>, gender <chr>,
# age <dbl>, age_unit <chr>, age_years <dbl>, age_cat <fct>, age_cat5 <fct>,
# hospital <chr>, lon <dbl>, lat <dbl>, infector <chr>, source <chr>,
# wt_kg <dbl>, ht_cm <dbl>, ct_blood <dbl>, fever <chr>, chills <chr>,
# cough <chr>, aches <chr>, vomit <chr>, temp <dbl>, time_admission <chr>,
# bmi <dbl>, days_onset_hosp <dbl>
Уникальные группы
Созданные группы отображают каждую уникальную комбинацию значений по столбцам группирования.
Чтобы увидеть группы и количество строк в каждой группе, передайте группированные данные в функцию tally()
.Чтобы увидеть только уникальные группы без подсчета количества вы можете передать их в group_keys()
.
См. ниже, что существует три уникальных значения в группируемом столбце исхода outcome
: “Death” (смерть), “Recover” (выздоровление), и NA
(отсутствует). Вы видите, что было nrow(linelist %>% filter(outcome == "Death"))
смертей, nrow(linelist %>% filter(outcome == "Recover"))
выздоровевших и nrow(linelist %>% filter(is.na(outcome)))
без документированного исхода.
%>%
linelist group_by(outcome) %>%
tally()
# A tibble: 3 × 2
outcome n
<chr> <int>
1 Death 2582
2 Recover 1983
3 <NA> 1323
Вы можете группировать более чем по одному столбцу. Ниже датафрейм группируется по исходу outcome
и полу gender
, а затем делается подсчет. Обратите внимание, что каждая уникальная комбинация исхода outcome
и пола gender
регистрируется как отдельная группа - включая отсутствующие значения для каждого столбца.
%>%
linelist group_by(outcome, gender) %>%
tally()
# A tibble: 9 × 3
# Groups: outcome [3]
outcome gender n
<chr> <chr> <int>
1 Death f 1227
2 Death m 1228
3 Death <NA> 127
4 Recover f 953
5 Recover m 950
6 Recover <NA> 80
7 <NA> f 627
8 <NA> m 625
9 <NA> <NA> 71
Новые столбцы
Вы можете также создать новый столбец группирования внутри утверждения group_by()
. Это все равно что поставить mutate()
перед group_by()
. Этот стиль может подойти для быстрого подсчета, но для ясности кода попробуйте создавать этот столбец отдельным шагом mutate()
и потом присоединяйте его по каналу в group_by()
.
# группирование данных на основе двоичного столбца, созданного *внутри* команды group_by()
%>%
linelist group_by(
age_class = ifelse(age >= 18, "adult", "child")) %>%
tally(sort = T)
# A tibble: 3 × 2
age_class n
<chr> <int>
1 child 3618
2 adult 2184
3 <NA> 86
Добавление/удаление столбцов группирования
По умолчанию если вы выполните group_by()
для данных, которые уже сгруппированы, старые группы будут удалены и будут применены новые группы. Если вы хотите добавить новые группы к существующим, включите аргумент .add = TRUE
.
# Сгруппировано по исходу
<- linelist %>%
by_outcome group_by(outcome)
# Добавляем дополнительное группирование по полу
<- by_outcome %>%
by_outcome_gender group_by(gender, .add = TRUE)
Сохраняем все группы
Если вы сгруппируете по столбцу в классе фактор, могут быть уровни фактора, которых в настоящее время нет в данных. Если вы проведете группирование по этому столбцу, по умолчанию эти отсутствующие уровни будут выкинуты и не будут включены как группы. Чтобы это изменить так, чтобы все уровни появлялись как группы (даже если их нет в наличии в данных), установите в команде group_by()
аргумент .drop = FALSE
.
13.3 Разгруппирование
Данные, которые были сгруппированы, останутся сгруппированными, пока вы их не разгруппируете с помощью ungroup()
. Если вы забудете разгруппировать, это может привести к ошибкам в расчетах! Ниже представлен пример снятия всех группирований:
%>%
linelist group_by(outcome, gender) %>%
tally() %>%
ungroup()
Вы можете также снять группирование только конкретных столбцов, разместив имя этого столбца внутри ungroup()
.
%>%
linelist group_by(outcome, gender) %>%
tally() %>%
ungroup(gender) # снимаем группирование по полу, сохраняем группирование по исходу
ПРИМЕЧАНИЕ: Глагол count()
автоматически разгруппирует данные после подсчета.
13.4 Резюмирование
См. раздел dplyr страницы [Описательные таблицы] для получения детального описания того, как создавать суммарные таблицы с помощью summarise()
. Здесь мы кратко рассматриваем то, как меняется поведение этой функции при применениии к группированным данным.
функция summarise()
(или summarize()
) из dplyr берет датафрейм и конвертирует его в новый сводный датафрейм, где столбцы содержат сводную статистику, которую вы зададите. В негруппированном датафрейме сводная статистика рассчитывается по всем строкам. Применение summarise()
к группированным данным выдаст такую статистику для каждой группы.
Синтаксис summarise()
таков, что вы задаете имя(имена) нового сводного столба(ов), знак равно, а затем статистическую функцию, которую нужно применить к данным, как показано ниже. Например, min()
(минимум), max()
(максимум), median()
(медиана), либо sd()
(стандартное отклонение). В рамках статистической функции укажите столбец, над которым нужно работать и необходимый аргумент (например, na.rm = TRUE
). Вы можете использовать sum()
(сумма), чтобы подсчитать количество строк, соответствующих логическому критерию (с двойным знаком равно ==
).
Ниже представлен пример применения summarise()
без группирования данных. Полученная статистика является результатом для всего набора данных.
# сводная статистика по разгруппированному построчному списку
%>%
linelist summarise(
n_cases = n(),
mean_age = mean(age_years, na.rm=T),
max_age = max(age_years, na.rm=T),
min_age = min(age_years, na.rm=T),
n_males = sum(gender == "m", na.rm=T))
n_cases mean_age max_age min_age n_males
1 5888 16.01831 84 0 2803
Для сравнения, ниже представлено то же самое утверждение summarise()
, но применительно к группированным данным. Статистика рассчитывается для каждой группы исходов outcome
. Обратите внимание, что столбцы группирования переносятся в новый датафрейм.
# сводная статистика по группированному построчному списку
%>%
linelist group_by(outcome) %>%
summarise(
n_cases = n(),
mean_age = mean(age_years, na.rm=T),
max_age = max(age_years, na.rm=T),
min_age = min(age_years, na.rm=T),
n_males = sum(gender == "m", na.rm=T))
# A tibble: 3 × 6
outcome n_cases mean_age max_age min_age n_males
<chr> <int> <dbl> <dbl> <dbl> <int>
1 Death 2582 15.9 76 0 1228
2 Recover 1983 16.1 84 0 950
3 <NA> 1323 16.2 69 0 625
СОВЕТ: Функция резюмирования работает и в британском, и в американском написании слова - summarise()
и summarize()
выполняют одинаковую функцию.
13.5 Подсчет с помощью count и tally
count()
и tally()
выполняют схожий функционал, но отличаются друг от друга. Более подробно об этих отличиях между tally()
и count()
можно прочитать тут
tally()
tally()
- это сокращение для summarise(n = n())
и не группирует данные. Таким образом, чтбы получить группированный подсчет, перед ней должна идти команда group_by()
. Вы можете добавить sort = TRUE
, чтобы сначала увидеть более крупные группы.
%>%
linelist tally()
n
1 5888
%>%
linelist group_by(outcome) %>%
tally(sort = TRUE)
# A tibble: 3 × 2
outcome n
<chr> <int>
1 Death 2582
2 Recover 1983
3 <NA> 1323
count()
А команда count()
работает следующим образом:
- применяет
group_by()
к указанному столбцу(ам)
- применяет
summarise()
и выдает столбецn
с количеством строк на группу
- применяет
ungroup()
%>%
linelist count(outcome)
outcome n
1 Death 2582
2 Recover 1983
3 <NA> 1323
Как и в случаев с group_by()
вы можете создать новый столбец внутри команды count()
:
%>%
linelist count(age_class = ifelse(age >= 18, "adult", "child"), sort = T)
age_class n
1 child 3618
2 adult 2184
3 <NA> 86
count()
можно вызывать несколько раз, а ее функционал будет “комбинироватся”. Например, чтобы свести количество больниц, в которых есть каждый пол, выполните следующее. Обратите внимание, что имя итогового столбца меняется с имени по умолчанию “n” для большей ясности (с помощью name =
).
%>%
linelist # создаем подсчет по уникальным группам исход-пол
count(gender, hospital) %>%
# собираем строки по полу (3) и считаем количество больниц на пол (6)
count(gender, name = "hospitals per gender" )
gender hospitals per gender
1 f 6
2 m 6
3 <NA> 6
Добавить подсчеты
Вместо count()
и summarise()
вы можете использовать add_count()
, чтобы добавить новый столбец n
с подсчетом строк на группу, при этом сохранив все остальные столбцы датафрейма.
Это означает, что подсчитанное количество по группе в новом столбце n
будет напечатано в каждой строке группы. Для демонстрации мы добавим этот столбец, а затем переупорядочим столбцы для облегчения просмотра. См. раздел ниже фильтр по размеру группы, где приведен еще один пример.
%>%
linelist as_tibble() %>% # конвертируем в таблицу tibble для более красивой печати
add_count(hospital) %>% # добавляем столбец n с подсчетами по больнице
select(hospital, n, everything()) # переупорядочиваем для демонстрации
# A tibble: 5,888 × 31
hospital n case_id generation date_infection date_onset
<chr> <int> <chr> <dbl> <date> <date>
1 Other 885 5fe599 4 2014-05-08 2014-05-13
2 Missing 1469 8689b7 4 NA 2014-05-13
3 St. Mark's Maternity Hosp… 422 11f8ea 2 NA 2014-05-16
4 Port Hospital 1762 b8812a 3 2014-05-04 2014-05-18
5 Military Hospital 896 893f25 3 2014-05-18 2014-05-21
6 Port Hospital 1762 be99c8 3 2014-05-03 2014-05-22
7 Missing 1469 07e3e8 4 2014-05-22 2014-05-27
8 Missing 1469 369449 4 2014-05-28 2014-06-02
9 Missing 1469 f393b4 4 NA 2014-06-05
10 Missing 1469 1389ca 4 NA 2014-06-05
# ℹ 5,878 more rows
# ℹ 25 more variables: date_hospitalisation <date>, date_outcome <date>,
# outcome <chr>, gender <chr>, age <dbl>, age_unit <chr>, age_years <dbl>,
# age_cat <fct>, age_cat5 <fct>, lon <dbl>, lat <dbl>, infector <chr>,
# source <chr>, wt_kg <dbl>, ht_cm <dbl>, ct_blood <dbl>, fever <chr>,
# chills <chr>, cough <chr>, aches <chr>, vomit <chr>, temp <dbl>,
# time_admission <chr>, bmi <dbl>, days_onset_hosp <dbl>
Добавление Итого
Чтобы легко добавить итоговую сумму по строкам или столбцам после применения tally()
или count()
, см. раздел janitor на странице Описательные таблицы. Этот пакет предлагает другие функции, такие как adorn_totals()
и adorn_percentages()
, чтобы складывать итоговые показатели и конвертировать для отображения в виде процентов. Ниже приведен короткий пример:
%>% # построчный список случаев
linelist tabyl(age_cat, gender) %>% # кросс-табуляция подсчета по двум столбцам
adorn_totals(where = "row") %>% # добавляем строку итого
adorn_percentages(denominator = "col") %>% # конвертируем в долю со знаменателем столбца
adorn_pct_formatting() %>% # конвертируем долю в проценты
adorn_ns(position = "front") %>% # отображаем как: "count (percent)"
adorn_title( # корректируем заголовки
row_name = "Age Category",
col_name = "Gender")
Gender
Age Category f m NA_
0-4 640 (22.8%) 416 (14.8%) 39 (14.0%)
5-9 641 (22.8%) 412 (14.7%) 42 (15.1%)
10-14 518 (18.5%) 383 (13.7%) 40 (14.4%)
15-19 359 (12.8%) 364 (13.0%) 20 (7.2%)
20-29 468 (16.7%) 575 (20.5%) 30 (10.8%)
30-49 179 (6.4%) 557 (19.9%) 18 (6.5%)
50-69 2 (0.1%) 91 (3.2%) 2 (0.7%)
70+ 0 (0.0%) 5 (0.2%) 1 (0.4%)
<NA> 0 (0.0%) 0 (0.0%) 86 (30.9%)
Total 2,807 (100.0%) 2,803 (100.0%) 278 (100.0%)
Чтобы добавить более сложные строки Итого, которые требуют сводной статистики, а не просто суммы, см. этот раздел страницы Описательные таблицы.
13.6 Группировка по дате
При группировании данных по дате, у вас должен быть (или вам нужно создать) столбец с интересующей единицей даты - например, “день”, “эпиднеделя”, “месяц” и т.п. Вы можете создать этот столбец, используя floor_date()
из lubridate, как объясняется в разделе Эпидемиологические недели страницы [Работа с датами]. Как только у вас будет такой столбец, вы можете использовать count()
из dplyr, чтобы сгруппировать строки по этим уникальным значениям даты и получить агрегированный подсчет.
Еще один дополнительный шаг, часто встречающийся в ситуации с датами - “заполнение” дат в последовательности, которые не присутствуют в данных. Используйте complete()
из tidyr, чтобы агрегированный ряд дат был полным, включая все возможные единицы дат в диапазоне. Без этого шага неделя, в которой не было зарегистрировано случаев, может не появиться в ваших данных!
В рамках complete()
вы переопределяете ваш столбец дата как последовательность дат seq.Date()
от минимальной до максимальной - таким образом расширяются даты. По умолчанию значения подсчета случаев в любых новых “расширенных” строках будут NA
. Вы можете их установить на 0, используя аргумент fill =
в complete()
, который ожидает именованного списка (если ваш столбец подсчет назван n
, задайте fill = list(n = 0)
. См. ?complete
для получения более детальной информации, а также пример на странице Работа с датами.
Построчный список случаев по дням
Здесь приведен пример группирования случаев по дням без использования complete()
. Обратите внимание, что первые строки пропускают даты без случаев.
<- linelist %>%
daily_counts drop_na(date_onset) %>% # удаляем те, в которых отсутствует дата заболевания (date_onset)
count(date_onset) # считаем количество строк на уникальную дату
Ниже мы добавляем команду complete()
, чтобы убедиться, что каждый день в диапазоне представлен.
<- linelist %>%
daily_counts drop_na(date_onset) %>% # удаляем случаи, где отсутствует дата заболевания (date_onset)
count(date_onset) %>% # считаем количество строк на уникальную дату
complete( # чтобы появились все даты, даже без случаев
date_onset = seq.Date( # переопределяем столбец дата как ежедневную последовательность дат
from = min(date_onset, na.rm=T),
to = max(date_onset, na.rm=T),
by = "day"),
fill = list(n = 0)) # задаем отображение 0 во всех новых заполненных строках в столбце n (вместо NA как отображается по умолчанию)
Построчный список случаев по неделям
Тот же принцип можно применить к неделям. Сначала создаем новый столбец - неделя случая, используя floor_date()
с аргументом unit = "week"
. Затем используем count()
, как показано выше, чтобы получить понедельное количество случаев. Затем закончите с помощью complete()
, чтобы убедиться, что присутствуют все недели, даже если в них не было случаев.
# Создаем набор данных с недельным количеством случаев
<- linelist %>%
weekly_counts drop_na(date_onset) %>% # удаляем случаи с отсутствующей датой заболевания (date_onset)
mutate(week = lubridate::floor_date(date_onset, unit = "week")) %>% # новый столбец недели заболевания
count(week) %>% # группируем данные по неделе и считаем количество строк на группу
complete( # чтобы появились все дни, даже без случаев
week = seq.Date( # переопределяем столбец дата как ежедневную последовательность дат
from = min(week, na.rm=T),
to = max(week, na.rm=T),
by = "week"),
fill = list(n = 0)) # задаем отображение 0 во всех новых заполненных строках в столбце n (вместо NA как отображается по умолчанию)
Вот первые 50 строк получившегося датафрейма:
###Построчный список случаев по месяцам {.unnumbered}
Чтобы агрегировать случаи по месяцам, снова используйте floor_date()
из пакета lubridate, но с аргументом unit = "months"
. Это округлит дату вниз до 1го числа месяца. Выходные данные будут в классе Дата. Обратите внимание, что в шаге complete()
, мы также используем аргумент by = "months"
.
# Создаем набор данных ежемесячного количества случаев
<- linelist %>%
monthly_counts drop_na(date_onset) %>%
mutate(month = lubridate::floor_date(date_onset, unit = "months")) %>% # новый столбец, 1е число месяца заболевания
count(month) %>% # подсчет количества случаев по месяцу
complete(
month = seq.Date(
min(month, na.rm=T), # включает все месяцы, где не было зарегистрировано случаев
max(month, na.rm=T),
by="month"),
fill = list(n = 0))
Ежедневное количество в недельное
Чтобы агрегировать ежедневное количество случаев в недельное количество, используйте floor_date()
как показано выше. Однако, используйте group_by()
и summarize()
вместо count()
, поскольку вам нужна сумма sum()
ежедневного количества случаев, а не просто подсчет количества строк в неделю.
Ежедневное количество в месячное
Чтобы агрегировать ежедневное количество случаев в месячное количество, используйте floor_date()
с аргументом unit = "month"
, как показано выше. Однако, используйте group_by()
и summarize()
вместо count()
, поскольку вам нужна сумма sum()
ежедневного количества случаев, а не просто подсчет количества строк в месяц.
13.7 Упорядочивание сгруппированных данных
Использование глагольной функции arrange()
из dplyr, чтобы упорядочить строки в датафрейме, даст вам такое же поведение, как и при группировании данных, если только вы не зададите аргумент .by_group =TRUE
. В таком случае строки будут сначала упорядочены по группированным столбцам, которые вы укажете в аргументе arrange()
.
13.8 Фильтр по группированным данным
filter()
При применении в сочетании с функциями, которые оценивают датафрейм (например, max()
, min()
, mean()
), эти функции теперь будут применяться к группам. Например, если вы хотите фильтровать и сохранить те строки, где пациенты старше медианного возраста, это теперь будет применяться по группам - фильтр, чтобы сохранить строки выше медианного возраста группы.
Выбор строк в группе
Функция slice()
из dplyr, которая фильтрует строки на основе их положения в данных, может также применяться к группе. Помните, что нужно учесть сортировку данных внутри каждой группы, чтобы получить желаемый “срез”.
Например, чтобы извлечь только последние 5 госпитализаций из каждой больницы:
- Сгруппируйте построчный список по столбцу
hospital
- Упорядочьте записи от самой последней к самой ранней дате госпитализации
date_hospitalisation
внутри каждой группы больниц
- Используйте slice, чтобы извлечь первые 5 строк для каждой больницы
%>%
linelist group_by(hospital) %>%
arrange(hospital, date_hospitalisation) %>%
slice_head(n = 5) %>%
arrange(hospital) %>% # для отображения
select(case_id, hospital, date_hospitalisation) # для отображения
# A tibble: 30 × 3
# Groups: hospital [6]
case_id hospital date_hospitalisation
<chr> <chr> <date>
1 20b688 Central Hospital 2014-05-06
2 d58402 Central Hospital 2014-05-10
3 b8f2fd Central Hospital 2014-05-13
4 acf422 Central Hospital 2014-05-28
5 275cc7 Central Hospital 2014-05-28
6 d1fafd Military Hospital 2014-04-17
7 974bc1 Military Hospital 2014-05-13
8 6a9004 Military Hospital 2014-05-13
9 09e386 Military Hospital 2014-05-14
10 865581 Military Hospital 2014-05-15
# ℹ 20 more rows
slice_head()
- выбирает n строк сверхуslice_tail()
- выбирает n строк снизуslice_sample()
- случайно выбирает n строкslice_min()
- выбирает n строк с наибольшими значениями в столбце order_by =
, используйте with_ties = TRUE
, чтобы сохранить связиslice_max()
- выбирает n строк с наименьшими значениями в столбце order_by =
, используйте with_ties = TRUE
, чтобы сохранить связи
См. страницу [Дедупликация], где представлено больше примеров и деталей по slice()
.
Фильтр по размеру группы
Фукнция add_count()
добавляет столбец n
к оригинальным данным, указывая количество строк в этой группе строк.
Ниже показано, как add_count()
применяется к столбцу hospital
, так что значения в новом столбце n
отражают количество строк в группе больниц этой строки. Обратите внимание, что значения в столбце n
повторяются. В примере ниже, столбец n
можно изменить, используя name =
внутри add_count()
. Для демонстрационных целей мы переупорядочиваем столбцы с помощью select()
.
%>%
linelist as_tibble() %>%
add_count(hospital) %>% # добавляем "количество строк госпитализированных в ту же больницу, что и эта строка"
select(hospital, n, everything())
# A tibble: 5,888 × 31
hospital n case_id generation date_infection date_onset
<chr> <int> <chr> <dbl> <date> <date>
1 Other 885 5fe599 4 2014-05-08 2014-05-13
2 Missing 1469 8689b7 4 NA 2014-05-13
3 St. Mark's Maternity Hosp… 422 11f8ea 2 NA 2014-05-16
4 Port Hospital 1762 b8812a 3 2014-05-04 2014-05-18
5 Military Hospital 896 893f25 3 2014-05-18 2014-05-21
6 Port Hospital 1762 be99c8 3 2014-05-03 2014-05-22
7 Missing 1469 07e3e8 4 2014-05-22 2014-05-27
8 Missing 1469 369449 4 2014-05-28 2014-06-02
9 Missing 1469 f393b4 4 NA 2014-06-05
10 Missing 1469 1389ca 4 NA 2014-06-05
# ℹ 5,878 more rows
# ℹ 25 more variables: date_hospitalisation <date>, date_outcome <date>,
# outcome <chr>, gender <chr>, age <dbl>, age_unit <chr>, age_years <dbl>,
# age_cat <fct>, age_cat5 <fct>, lon <dbl>, lat <dbl>, infector <chr>,
# source <chr>, wt_kg <dbl>, ht_cm <dbl>, ct_blood <dbl>, fever <chr>,
# chills <chr>, cough <chr>, aches <chr>, vomit <chr>, temp <dbl>,
# time_admission <chr>, bmi <dbl>, days_onset_hosp <dbl>
Затем становится легче фильтровать по строкам случаев, которые были госпитализированы в “маленькую” больницу, например, в больницу, куда госпитализировано менее 500 пациентов:
%>%
linelist add_count(hospital) %>%
filter(n < 500)
13.9 Функция mutate для сгруппированных данных
Чтобы сохранить все столбцы и строки (не обобщать) и добавить новый столбец, содержащий стастистику группы, используйте mutate()
после group_by()
вместо summarise()
.
Это полезно, если вы хотите получить статистику группы в оригинальном наборе данных с сохранением всех остальных столбцов - например, для расчетов, которые сравнивают одну строку с ее группой.
Например, код ниже рассчитывает разницу между задержкой госпитализации строки и медианной задержкой по этой больнице. Выполняются следующие шаги:
- Группируем данные по больнице
- Используем столбец
days_onset_hosp
(задержка госпитализации), чтобы создать новый столбец, содержащий среднюю задержку в больнице из этой строки
- Рассчитываем разницу между двумя столбцами
Мы выбираем только некоторые столбцы для отображения с помощью select()
для целей демонстрации.
%>%
linelist # группируем данные по больнице (еще не изменяем построчный список)
group_by(hospital) %>%
# новые столбцы
mutate(
# среднее количество дней до госпитализации по больнице (округляется до 1 десятичного знака)
group_delay_admit = round(mean(days_onset_hosp, na.rm=T), 1),
# разница между задержкой строки и средней задержкой в этой больнице (округляется до 1 десятичного знака)
diff_to_group = round(days_onset_hosp - group_delay_admit, 1)) %>%
# выбираем только определенные строки для демонстрации/просмотра
select(case_id, hospital, days_onset_hosp, group_delay_admit, diff_to_group)
# A tibble: 5,888 × 5
# Groups: hospital [6]
case_id hospital days_onset_hosp group_delay_admit diff_to_group
<chr> <chr> <dbl> <dbl> <dbl>
1 5fe599 Other 2 2 0
2 8689b7 Missing 1 2.1 -1.1
3 11f8ea St. Mark's Maternity… 2 2.1 -0.1
4 b8812a Port Hospital 2 2.1 -0.1
5 893f25 Military Hospital 1 2.1 -1.1
6 be99c8 Port Hospital 1 2.1 -1.1
7 07e3e8 Missing 2 2.1 -0.1
8 369449 Missing 1 2.1 -1.1
9 f393b4 Missing 1 2.1 -1.1
10 1389ca Missing 2 2.1 -0.1
# ℹ 5,878 more rows
13.10 Функция select для сгруппированных данных
Глагольная функция select()
работает на сгруппированных данных, но столбцы группирования всегда включаются (даже если не упомянуты в select()
). Если вам не нужны эти столбцы группирования, используйте сначала ungroup()
.
13.11 Ресурсы
Вот некоторые полезные ресурсы с дополнительной информацией:
Вы можете применять любую резюмирующую функцию к группированным данным; см. Шпаргалку по преобразованию данных в RStudio
Страница Data Carpentry в dplyr
Справочная страница tidyverse по group_by() и группированию
Страница по Манипуляциям с данными