Zagnieżdżanie i rozpakowywanie ramek danych
Używaj nest() i unnest() do pracy z kolumnami listowymi w uporządkowanych przepływach pracy.
Zagnieżdżanie i rozpakowywanie ramek danych to bezpłatna lekcja R Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
Kolumny listowe i dane zagnieżdżone
Kolumna listowa to kolumna w ramce danych, w której każda komórka zawiera obiekt R (wektor, ramkę danych, model lub listę). Umożliwia to przechowywanie uporządkowanych danych podrzędnych obok innych kolumn i tworzenie zaawansowanych przepływów pracy wykonywanych w ramach grup.
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() — Tworzenie zagnieżdżonych ramek danych
nest(df, data = c(col1, col2)) grupuje wiersze według kolumn niezagnieżdżonych i umieszcza wskazane kolumny w kolumnie listowej zawierającej ramki danych. Powstaje jeden wiersz na grupę, a w każdym z nich znajduje się mała ramka danych.
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() z group_by()
Najczęściej stosowany schemat to użycie group_by(), a następnie nest(), aby utworzyć jeden wiersz na grupę i umieścić wszystkie pozostałe kolumny w kolumnie listowej data. Odpowiada to wyrażeniu nest(.by = group_col) w nowszych wersjach tidyr.
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() ze zagnieżdżonymi ramkami danych
Po zagnieżdżeniu danych należy użyć purrr::map(), aby zastosować funkcję do każdej małej ramki danych. Funkcja otrzymuje po jednej ramce danych, a wyniki stają się nową kolumną listową — często zawierającą dopasowany model.
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)Wyodrębnianie wyników modeli za pomocą map()
Po dopasowaniu modeli dla poszczególnych grup należy użyć map() wraz z funkcjami takimi jak broom::tidy() lub coef(), aby wyodrębnić wyniki z każdego modelu. Dane wyjściowe są kolejną kolumną listową, którą można później rozwinąć.
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() — Rozwijanie kolumn listowych
unnest(df, cols = data) jest odwrotnością funkcji nest(). Rozwija kolumnę listową z powrotem do zwykłych kolumn, powtarzając kolumny identyfikatorów w razie potrzeby. Argument cols służy do wskazania kolumny listowej, którą należy rozwinąć.
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() — Rozwijanie listy do wierszy
unnest_longer(df, col) rozwija kolumnę listową tak, aby każdy element listy stał się osobnym wierszem. W przeciwieństwie do unnest(), która oczekuje ramek danych, funkcja unnest_longer() działa z listami wektorów lub wartości skalarnych.
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() — Rozwijanie listy do kolumn
unnest_wider(df, col) rozwija każdy element listy do zestawu nowych kolumn. Lista musi zawierać nazwane elementy — ich nazwy stają się nazwami kolumn. Jest to przydatne w przypadku struktur przypominających zagnieżdżony 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)Pełny schemat pracy z danymi zagnieżdżonymi
Kompletny schemat pracy z zagnieżdżoną ramką danych: group_by() + nest() → zastosowanie funkcji za pomocą map() → wyodrębnienie wyników → unnest() w celu uzyskania płaskiej ramki danych. Schemat ten umożliwia przeprowadzenie dowolnej analizy osobno dla każdej grupy.
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)Zagnieżdżanie wielu kolumn
Można wybrać, które kolumny mają zostać umieszczone w zagnieżdżonej ramce danych. Należy wskazać je jawnie w wyrażeniu nest(data = c(...)). Niewskazane kolumny pozostają zwykłymi kolumnami w zewnętrznej ramce danych, obok kolumny listowej.
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)Kiedy używać zagnieżdżonych ramek danych
Zagnieżdżone ramki danych sprawdzają się szczególnie wtedy, gdy trzeba dopasować ten sam model dla wielu grup, przeprowadzić symulacje dla poszczególnych grup, zastosować złożone przekształcenia do podzbiorów lub pracować z hierarchicznymi danymi przypominającymi JSON. Pozwalają uporządkować dane dotyczące grup obok metadanych na poziomie grup.
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)Szybkie sprawdzenie
Jaki jest właściwy sposób rozwinięcia kolumny listowej zawierającej ramki danych z powrotem do płaskiej ramki danych?
Podsumowanie: zagnieżdżanie i rozwijanie
Najważniejsze informacje dotyczące pracy z zagnieżdżonymi ramkami danych:
nest(data = c(cols))umieszcza kolumny w kolumnie listowej zawierającej ramki danych, po jednej dla każdej grupygroup_by() + nest()— standardowy schemat zagnieżdżania danych według grupmap(nested$data, fn)— stosuje dowolną funkcję do każdej zagnieżdżonej ramki danychunnest(cols = data)— rozwija kolumnę listową zawierającą ramki danych z powrotem do płaskiego formatuunnest_longer(col)— rozwija listę wektorów lub wartości skalarnych do wierszyunnest_wider(col)— rozwija nazwaną listę do kolumn- Idealne rozwiązanie do modelowania dla poszczególnych grup, próbkowania bootstrapowego i przetwarzania danych 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)Często zadawane pytania
Czy lekcja „Zagnieżdżanie i rozpakowywanie ramek danych” jest bezpłatna?
Tak — pełny tekst „Zagnieżdżanie i rozpakowywanie ramek danych” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Zagnieżdżanie i rozpakowywanie ramek danych”?
Używaj nest() i unnest() do pracy z kolumnami listowymi w uporządkowanych przepływach pracy. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Zagnieżdżanie i rozpakowywanie ramek danych”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Z układu szerokiego do długiego za pomocą pivot_longer()
- Z układu długiego do szerokiego za pomocą pivot_wider()
- separate() i unite() dla kolumn tekstowych
- Zagnieżdżanie i rozpakowywanie ramek danych