0Pricing
R Academy · Lezione

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 element

nest() — 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 data

nest() 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 gruppo
  • group_by() + nest() — lo schema standard per annidare i dati per gruppo
  • map(nested$data, fn) — applica una funzione a ogni data frame annidato
  • unnest(cols = data) — espande una list-column di data frame tornando al formato piatto
  • unnest_longer(col) — espande una lista di vettori o scalari in righe
  • unnest_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

  1. Da formato wide a long con pivot_longer()
  2. Da formato long a wide con pivot_wider()
  3. separate() e unite() per le colonne di testo
  4. Annidamento e disannidamento dei data frame
← Torna a R Academy