Вложенные и развёрнутые таблицы данных
Используйте nest() и unnest() для работы со столбцами-списками в аккуратных рабочих процессах.
«Вложенные и развёрнутые таблицы данных» — бесплатный урок R Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения R Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс R Academy содержит 4 уроков всего.
Столбцы-списки и вложенные данные
Столбец-список — это столбец таблицы данных, в каждой ячейке которого содержится объект R (вектор, таблица данных, модель или список). Это позволяет хранить структурированные подданные рядом с другими столбцами и выполнять мощные операции по группам.
library(tidyr)
library(dplyr)
# A simple data frame with a list-column
df <- data.frame(
group = c('A','B','C'),
n = c(3, 2, 4)
)
df$values <- list(c(1,2,3), c(4,5), c(6,7,8,9))
print(df)
print(df$values[[1]]) # Access the first list elementnest() — создание вложенных таблиц данных
nest(df, data = c(col1, col2)) группирует строки по столбцам, не включённым во вложенные данные, и упаковывает указанные столбцы в столбец-список из таблиц данных. Для каждой группы создаётся одна строка, содержащая небольшую таблицу данных.
library(tidyr)
library(dplyr)
df <- data.frame(
region = c('East','East','East','West','West'),
month = c(1,2,3,1,2),
sales = c(100,120,110,200,190)
)
nested <- df %>%
nest(data = c(month, sales))
print(nested)
print(nested$data[[1]]) # East region's datanest() с group_by()
Наиболее распространённый шаблон: используйте group_by(), а затем nest(), чтобы создать по одной строке на группу, упаковав все остальные столбцы в столбец-список data. В новых версиях tidyr это эквивалентно nest(.by = group_col).
library(tidyr)
library(dplyr)
df <- data.frame(
category = c('A','A','A','B','B','C','C','C','C'),
x = c(1,2,3,4,5,6,7,8,9),
y = c(2,4,3,8,7,5,6,9,8)
)
nested <- df %>%
group_by(category) %>%
nest()
print(nested)
cat('Rows per category B:', nrow(nested$data[[2]]))map() с вложенными таблицами данных
После вложения данных используйте purrr::map(), чтобы применить функцию к каждой небольшой таблице данных. Функция получает по одной таблице данных за раз, а результаты становятся новым столбцом-списком — часто содержащим подогнанную модель.
library(tidyr)
library(dplyr)
library(purrr)
df <- data.frame(
group = c('A','A','A','B','B','B'),
x = c(1,2,3,1,2,3),
y = c(2.1,4.0,5.9,3.2,5.8,9.1)
)
models <- df %>%
group_by(group) %>%
nest() %>%
mutate(model = map(data, ~lm(y ~ x, data = .x)))
print(models)Извлечение результатов моделей с помощью map()
После построения моделей для каждой группы используйте map() с такими функциями, как broom::tidy() или coef(), чтобы извлечь результаты каждой модели. Результатом будет ещё один столбец-список, который позднее можно развернуть.
library(tidyr)
library(dplyr)
library(purrr)
df <- data.frame(
group = c('A','A','A','B','B','B'),
x = c(1,2,3,1,2,3),
y = c(2.1,4.0,5.9,3.2,5.8,9.1)
)
df %>%
group_by(group) %>%
nest() %>%
mutate(
model = map(data, ~lm(y ~ x, data = .x)),
r_squared = map_dbl(model, ~summary(.x)$r.squared),
intercept = map_dbl(model, ~coef(.x)[1]),
slope = map_dbl(model, ~coef(.x)[2])
) %>%
select(group, r_squared, intercept, slope)unnest() — разворачивание столбцов-списков
unnest(df, cols = data) является обратной операцией по отношению к nest(). Она разворачивает столбец-список обратно в обычные столбцы, при необходимости повторяя столбцы с идентификаторами. Используйте cols, чтобы указать, какой столбец-список нужно развернуть.
library(tidyr)
library(dplyr)
nested <- data.frame(
region = c('East','West')
)
nested$data <- list(
data.frame(month=1:3, sales=c(100,120,110)),
data.frame(month=1:2, sales=c(200,190))
)
unnested <- unnest(nested, cols = data)
print(unnested)unnest_longer() — разворачивание списка в строки
unnest_longer(df, col) разворачивает столбец-список так, чтобы каждый элемент списка стал отдельной строкой. В отличие от unnest(), ожидающей таблицы данных, unnest_longer() работает со списками векторов или отдельных значений.
library(tidyr)
df <- data.frame(
person = c('Alice','Bob','Carol')
)
df$skills <- list(
c('R','Python','SQL'),
c('Excel','Tableau'),
c('R','Julia','Stan','BUGS')
)
unnest_longer(df, skills)unnest_wider() — разворачивание списка в столбцы
unnest_wider(df, col) разворачивает каждый элемент списка в набор новых столбцов. Список должен содержать именованные элементы — их имена становятся именами столбцов. Это полезно для вложенных структур, подобных JSON.
library(tidyr)
df <- data.frame(id = 1:3)
df$info <- list(
list(name='Alice', age=30, city='NYC'),
list(name='Bob', age=25, city='LA'),
list(name='Carol', age=35, city='Chicago')
)
unnest_wider(df, info)Полный шаблон работы с вложенными данными
Полный рабочий процесс с вложенной таблицей данных: group_by() + nest() → применение функций с помощью map() → извлечение результатов → unnest() для возврата к плоской таблице данных. Этот шаблон позволяет выполнять любой анализ отдельно для каждой группы.
library(tidyr)
library(dplyr)
library(purrr)
df <- data.frame(
region = c('East','East','East','West','West','West'),
month = c(1,2,3,1,2,3),
revenue = c(100,120,115,200,195,210)
)
df %>%
group_by(region) %>%
nest() %>%
mutate(
mean_rev = map_dbl(data, ~mean(.x$revenue)),
trend = map_dbl(data, ~coef(lm(revenue~month, data=.x))[2])
) %>%
select(region, mean_rev, trend)Вложение нескольких столбцов
Вы можете выборочно указать, какие столбцы должны войти во вложенную таблицу данных. Явно укажите их в nest(data = c(...)). Неуказанные столбцы останутся обычными столбцами внешней таблицы данных рядом со столбцом-списком.
library(tidyr)
library(dplyr)
df <- data.frame(
region = c('East','East','West','West'),
year = c(2023,2024,2023,2024),
q1 = c(100,110,200,210),
q2 = c(105,115,195,215),
target = c(105,112,198,212)
)
# Only nest quarterly data, keep target as outer column
nested <- df %>%
group_by(region, year) %>%
nest(quarters = c(q1, q2))
print(nested)Когда использовать вложенные таблицы данных
Вложенные таблицы данных особенно полезны, когда нужно обучить одну и ту же модель для разных групп, выполнить симуляции по группам, применить сложные преобразования к подмножествам или работать с иерархическими данными, подобными JSON. Они позволяют хранить данные групп рядом с метаданными на уровне группы.
library(tidyr)
library(dplyr)
library(purrr)
# Bootstrap confidence interval per group
df <- data.frame(
group = c('A','A','A','A','B','B','B','B'),
value = c(10,12,11,13,20,22,19,21)
)
set.seed(42)
df %>%
group_by(group) %>%
nest() %>%
mutate(
boot_means = map(data, function(d) {
replicate(100, mean(sample(d$value, replace=TRUE)))
}),
ci_low = map_dbl(boot_means, ~quantile(.x, 0.025)),
ci_high = map_dbl(boot_means, ~quantile(.x, 0.975))
) %>%
select(group, ci_low, ci_high)Быстрая проверка
Как правильно развернуть столбец-список из таблиц данных обратно в плоскую таблицу данных?
Итоги: вложение и разворачивание
Главные выводы о работе с вложенными таблицами данных:
nest(data = c(cols))— упаковывает столбцы в столбец-список из таблиц данных, по одной на группуgroup_by() + nest()— стандартный шаблон вложения данных по группамmap(nested$data, fn)— применяет любую функцию к каждой вложенной таблице данныхunnest(cols = data)— разворачивает столбец-список из таблиц данных обратно в плоский форматunnest_longer(col)— разворачивает список векторов или отдельных значений в строкиunnest_wider(col)— разворачивает именованный список в столбцы- Идеально подходит для моделирования по группам, бутстрепа и обработки данных JSON
library(tidyr)
library(dplyr)
library(purrr)
data.frame(
team = c('A','A','B','B'),
x = c(1,2,1,2),
y = c(2,4,3,6)
) %>%
group_by(team) %>%
nest() %>%
mutate(
model = map(data, ~lm(y ~ x, data = .x)),
slope = map_dbl(model, ~coef(.x)['x'])
) %>%
select(team, slope)Изучай R с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 43
- Уроки
- 159
Часто задаваемые вопросы
Урок «Вложенные и развёрнутые таблицы данных» бесплатный?
Да — полный текст урока «Вложенные и развёрнутые таблицы данных» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс R Academy, подпишись на CoddyKit PRO. Курс R Academy содержит 4 уроков всего.
Чему я научусь в уроке «Вложенные и развёрнутые таблицы данных»?
Используйте nest() и unnest() для работы со столбцами-списками в аккуратных рабочих процессах. Ты практикуешь R Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать R Academy?
Предыдущий опыт не требуется. R Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Вложенные и развёрнутые таблицы данных»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке R Academy?
Да. Каждый урок R Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Из широкого формата в длинный с pivot_longer()
- Из длинного формата в широкий с pivot_wider()
- separate() и unite() для строковых столбцов
- Вложенные и развёрнутые таблицы данных