Annidamento e disannidamento dei data frame
Usi nest() e unnest() per lavorare con colonne-lista nei flussi di lavoro tidy.
Annidamento e disannidamento dei data frame è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
List-column e dati annidati
Una list-column è una colonna di un data frame in cui ogni cella contiene un oggetto R (un vettore, un data frame, un modello o una lista). Ciò consente di memorizzare dati secondari strutturati insieme alle altre colonne e abilita potenti flussi di lavoro per gruppo.
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() — Creazione di data frame annidati
nest(df, data = c(col1, col2)) raggruppa le righe in base alle colonne non annidate e inserisce le colonne specificate in una list-column di data frame. Si ottiene una riga per gruppo, ognuna contenente un piccolo data frame.
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() con group_by()
Il modello più comune consiste nell'utilizzare group_by() seguito da nest() per creare una riga per gruppo, inserendo tutte le colonne rimanenti in una list-column data. È equivalente a nest(.by = group_col) nelle versioni più recenti di 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() con data frame annidati
Una volta annidati i dati, utilizzi purrr::map() per applicare una funzione a ogni piccolo data frame. La funzione riceve un data frame alla volta e i risultati diventano una nuova list-column, spesso contenente un modello adattato.
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)Estrazione dei risultati dei modelli con map()
Dopo aver adattato i modelli per ogni gruppo, utilizzi map() con funzioni come broom::tidy() o coef() per estrarre i risultati di ciascun modello. L'output è un'altra list-column, che in seguito può essere denormalizzata.
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() — Espansione delle list-column
unnest(df, cols = data) è l'inverso di nest(). Espande la list-column riportandola a colonne regolari e ripete le colonne identificative quando necessario. Utilizzi cols per specificare quale list-column denormalizzare.
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() — Espansione di una lista in righe
unnest_longer(df, col) espande una list-column in modo che ogni elemento della lista diventi una riga. A differenza di unnest(), che si aspetta data frame, unnest_longer() funziona con liste di vettori o scalari.
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() — Espansione di una lista in colonne
unnest_wider(df, col) espande ogni elemento della lista in un insieme di nuove colonne. La lista deve contenere elementi denominati: i nomi diventano i nomi delle colonne. È utile per strutture annidate simili a 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)Schema completo del flusso di lavoro con dati annidati
Il flusso di lavoro completo con data frame annidati è: group_by() + nest() → applicazione delle funzioni con map() → estrazione dei risultati → unnest() per tornare a un data frame piatto. Questo schema consente di eseguire qualsiasi analisi per gruppo.
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)Annidamento di più colonne
Può scegliere in modo selettivo quali colonne inserire nel data frame annidato. Le specifichi esplicitamente in nest(data = c(...)). Le colonne non specificate rimangono colonne regolari nel data frame esterno, accanto alla list-column.
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)Quando utilizzare i data frame annidati
I data frame annidati sono particolarmente efficaci quando deve: adattare lo stesso modello a più gruppi, eseguire simulazioni per gruppo, applicare trasformazioni complesse a sottoinsiemi o lavorare con dati gerarchici simili a JSON. Mantengono organizzati i dati specifici del gruppo insieme ai metadati a livello di gruppo.
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)Verifica rapida
Qual è il modo corretto per espandere una list-column di data frame e tornare a un data frame piatto?
Riepilogo: annidamento e denormalizzazione
Punti chiave dei flussi di lavoro con data frame annidati:
nest(data = c(cols))— inserisce le colonne in una list-column di data frame, una per gruppogroup_by() + nest()— lo schema standard per annidare i dati per gruppomap(nested$data, fn)— applica una funzione a ogni data frame annidatounnest(cols = data)— espande una list-column di data frame tornando al formato piattounnest_longer(col)— espande una lista di vettori o scalari in righeunnest_wider(col)— espande una lista denominata in colonne- È ideale per la modellazione per gruppo, il bootstrapping e l'elaborazione di dati 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)Domande Frequenti
La lezione «Annidamento e disannidamento dei data frame» è gratuita?
Sì — il testo completo di «Annidamento e disannidamento dei data frame» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «Annidamento e disannidamento dei data frame»?
Usi nest() e unnest() per lavorare con colonne-lista nei flussi di lavoro tidy. Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Annidamento e disannidamento dei data frame»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Da formato wide a long con pivot_longer()
- Da formato long a wide con pivot_wider()
- separate() e unite() per le colonne di testo
- Annidamento e disannidamento dei data frame