15  Flusso di lavoro per la pulizia dei dati

In questo capitolo imparerai a
  • verificare, pulire e trasformare i dati per l’analisi
  • garantire riservatezza eliminando informazioni sensibili
  • documentare il dataset con un dizionario e note esplicative
  • assicurare validità, unicità e organizzazione dei dati
  • applicare regole coerenti per denominazione e codifica
Prerequisiti
Preparazione del Notebook
here::here("code", "_common.R") |> 
  source()

# Load packages
if (!requireNamespace("pacman")) install.packages("pacman")
pacman::p_load(mice, labelled, haven, pointblank, mice)

15.1 Introduzione

Nonostante la fase più interessante di un progetto di analisi dei dati sia quella in cui si riesce a rispondere alla domanda che ha dato avvio all’indagine, gran parte del tempo di un analista è in realtà dedicata a una fase preliminare: la pulizia e il preprocessing dei dati, operazioni che vengono svolte ancor prima dell’analisi esplorativa.

In questo capitolo, esamineremo un caso concreto di data cleaning e preprocessing, seguendo il tutorial di Crystal Lewis. Il problema viene presentato come segue:

I am managing data for a longitudinal randomized controlled trial (RCT) study. For this RCT, schools are randomized to either a treatment or control group. Students who are in a treatment school receive a program to boost their math self-efficacy. Data is collected on all students in two waves (wave 1 is in the fall of a school year, and wave 2 is collected in the spring). At this point in time, we have collected wave 1 of our student survey on a paper form and we set up a data entry database for staff to enter the information into. Data has been double-entered, checked for entry errors, and has been exported in a csv format (“w1_mathproj_stu_svy_raw.csv”) to a folder (called “data”) where it is waiting to be cleaned.

Crystal Lewis elenca i seguenti passaggi da seguire nel processo di data cleaning:

  1. Revisione dei dati.
  2. Regolazione del numero di casi.
  3. De-identificazione dei dati.
  4. Eliminazione delle colonne irrilevanti.
  5. Divisione delle colonne, se necessario.
  6. Ridenominazione delle variabili.
  7. Trasformazione/normalizzazione delle variabili.
  8. Standardizzazione delle variabili.
  9. Aggiornamento dei tipi di variabili, se necessario.
  10. Ricodifica delle variabili.
  11. Creazione di eventuali variabili necessarie.
  12. Gestione dei valori mancanti, se necessario.
  13. Aggiunta di metadati, se necessario.
  14. Validazione dei dati.
  15. Fusione e/o unione dei dati, se necessario.
  16. Trasformazione dei dati, se necessario.
  17. Salvataggio dei dati puliti.

Sebbene l’ordine di questi passaggi sia flessibile e possa essere adattato alle esigenze specifiche, c’è un passaggio che non dovrebbe mai essere saltato: il primo, ovvero la revisione dei dati. Senza una revisione preliminare, l’analista rischia di sprecare ore a pulire i dati per poi scoprire che mancano dei partecipanti, che i dati non sono organizzati come previsto o, peggio ancora, che si sta lavorando con i dati sbagliati.

15.2 Tutorial

Questo tutorial segue i passaggi descritti da Crystal Lewis per illustrare le buone pratiche nella gestione e pulizia dei dati.

15.2.1 Organizzazione dei Dati

Un principio fondamentale nella gestione dei dati è preservare l’integrità dei dati grezzi. I dati originali non devono mai essere modificati direttamente. È quindi consigliabile strutturare i dati in una directory denominata data, suddivisa in due sottocartelle:

  • raw: contiene i dati originali, mantenuti inalterati.
  • processed: destinata ai dati ripuliti e preprocessati.

Ad esempio, importiamo i dati da un file denominato w1_mathproj_stu_svy_raw.csv per avviare il processo di pulizia. Tutte le operazioni dovranno essere effettuate utilizzando percorsi relativi alla home directory del progetto, che definiremo come primo passo.

15.2.2 Passaggi del Tutorial

15.2.2.1 Importare e Esaminare i Dati

Importiamo i dati utilizzando la funzione import() della libreria rio e visualizziamo i primi valori di ciascuna colonna per verificarne la corretta importazione:

# Importa i dati
svy <- rio::import(here::here("data", "w1_mathproj_stu_svy_raw.csv"))

# Esamina la struttura del dataset
glimpse(svy)
#> Rows: 6
#> Columns: 7
#> $ stu_id      <int> 1347, 1368, 1377, 1387, 1347, 1399
#> $ svy_date    <IDate> 2023-02-13, 2023-02-13, 2023-02-13, 2023-02-13, 2023-0…
#> $ grade_level <int> 9, 10, 9, 11, 9, 12
#> $ math1       <int> 2, 3, 4, 3, 2, 4
#> $ math2       <chr> "1", "2", "\n4", "3", "2", "1"
#> $ math3       <int> 3, 2, 4, NA, 4, 3
#> $ math4       <int> 3, 2, 4, NA, 2, 1

Per controllare visivamente i dati, possiamo esaminare le prime e le ultime righe del data frame:

# Visualizza le prime righe
svy |> 
  head()
#>   stu_id   svy_date grade_level math1 math2 math3 math4
#> 1   1347 2023-02-13           9     2     1     3     3
#> 2   1368 2023-02-13          10     3     2     2     2
#> 3   1377 2023-02-13           9     4   \n4     4     4
#> 4   1387 2023-02-13          11     3     3    NA    NA
#> 5   1347 2023-02-14           9     2     2     4     2
#> 6   1399 2023-02-14          12     4     1     3     1

# Visualizza le ultime righe
svy |> 
  tail()
#>   stu_id   svy_date grade_level math1 math2 math3 math4
#> 1   1347 2023-02-13           9     2     1     3     3
#> 2   1368 2023-02-13          10     3     2     2     2
#> 3   1377 2023-02-13           9     4   \n4     4     4
#> 4   1387 2023-02-13          11     3     3    NA    NA
#> 5   1347 2023-02-14           9     2     2     4     2
#> 6   1399 2023-02-14          12     4     1     3     1

15.2.2.2 Individuare e Rimuovere i Duplicati

In questa fase, eseguiamo alcune modifiche necessarie al data frame, come rimuovere duplicati e ordinare i dati:

  • Verifica duplicati: controlliamo i record duplicati nel dataset.
  • Rimuovi duplicati: manteniamo solo la prima occorrenza.
  • Ordina per data: organizziamo i record in ordine crescente rispetto alla variabile svy_date.
  • Esamina i dati puliti: controlliamo il risultato delle modifiche.
# Identifica i duplicati basati su 'stu_id'
duplicates <- 
  svy[duplicated(svy$stu_id) | duplicated(svy$stu_id, fromLast = TRUE), ]
# Visualizza i duplicati trovati
duplicates
#>   stu_id   svy_date grade_level math1 math2 math3 math4
#> 1   1347 2023-02-13           9     2     1     3     3
#> 5   1347 2023-02-14           9     2     2     4     2
# Ordina per 'svy_date' in ordine crescente
svy <- svy[order(svy$svy_date), ]
# Rimuove i duplicati mantenendo la prima occorrenza
svy <- svy[!duplicated(svy$stu_id), ]
# Esamina il dataset finale
print(svy)
#>   stu_id   svy_date grade_level math1 math2 math3 math4
#> 1   1347 2023-02-13           9     2     1     3     3
#> 2   1368 2023-02-13          10     3     2     2     2
#> 3   1377 2023-02-13           9     4   \n4     4     4
#> 4   1387 2023-02-13          11     3     3    NA    NA
#> 6   1399 2023-02-14          12     4     1     3     1

Verifichiamo le dimensioni del dataset pulito per assicurarci che le operazioni siano state eseguite correttamente:

# Controlla il numero di righe e colonne
svy |> 
  dim()
#> [1] 5 7

15.2.2.3 De-identificazione dei Dati

# Rimuovi la colonna 'svy_date'
svy <- svy |>
  dplyr::select(-svy_date)

# Mostra i nomi delle colonne rimaste
names(svy)
#> [1] "stu_id"      "grade_level" "math1"       "math2"       "math3"      
#> [6] "math4"

15.2.2.4 Rimuovere le Colonne non Necessarie

Nel caso presente, la rimozione di colonne non è necessaria. Tuttavia, in molti progetti di analisi dei dati, soprattutto quando i dati vengono raccolti utilizzando software di terze parti o strumenti specifici per esperimenti psicologici, è comune trovarsi con colonne che non sono pertinenti allo studio in corso.

Queste colonne possono includere dati come identificatori interni, timestamp generati automaticamente, informazioni di debug, o variabili che non sono rilevanti per l’analisi che si intende condurre. Quando tali colonne sono irrilevanti per la ricerca, possono essere rimosse per semplificare il dataset e ridurre il rischio di confusione o errori durante l’analisi. Rimuovere le colonne non necessarie non solo rende il dataset più gestibile, ma aiuta anche a focalizzare l’analisi sulle variabili che realmente importano per rispondere alle domande di ricerca.

15.2.2.5 Dividere le Colonne Secondo Necessità

Nel caso presente, questa operazione non è necessaria. Tuttavia, se si lavora con un dataset che include una colonna chiamata “NomeCompleto”, contenente sia il nome che il cognome di uno studente, per esempio, è buona pratica separare questa colonna in due colonne distinte, “Nome” e “Cognome”. Questa suddivisione facilita l’analisi e la manipolazione dei dati, rendendoli più organizzati e accessibili.

15.2.2.6 Rinominare le Colonne

È importante assegnare nomi chiari alle colonne del dataset. Utilizzare nomi di variabili comprensibili aiuta a rendere l’analisi dei dati più intuitiva e a ridurre il rischio di errori interpretativi.

Esempi di buone pratiche:

  • Evita nomi di colonne come “x” o acronimi incomprensibili. Questi possono creare confusione durante l’analisi, specialmente se il dataset viene condiviso con altri ricercatori o se viene ripreso dopo un lungo periodo di tempo.
  • Invece, cerca di utilizzare nomi di variabili che descrivano chiaramente il contenuto della colonna. Ad esempio, invece di “x1” o “VAR123”, un nome come “ansia_base” o “liv_autoefficacia” è molto più comprensibile e immediato.
  • Per i nomi composti, utilizza un separatore come il trattino basso _. Ad esempio, se stai lavorando con dati relativi a un test psicologico, potresti avere colonne chiamate “test_ansia_pre” e “test_ansia_post” per indicare i risultati del test di ansia prima e dopo un intervento.

Esempi di nomi di colonne ben scelti:

  • Nome generico: TS, AE
    • Nome migliore: tempo_studio, auto_efficacia
  • Nome generico: S1, S2
    • Nome migliore: stress_situazione1, stress_situazione2
  • Nome generico: Q1, Q2
    • Nome migliore: qualità_sonno_sett1, qualità_sonno_sett2

15.2.2.7 Trasformare le Variabili

Nel caso presente non si applica, ma è un passo importante in molte analisi dei dati.

Esempi di trasformazione delle variabili:

  • Logaritmo di una variabile: Immaginiamo di avere una variabile che misura i tempi di reazione dei partecipanti a un esperimento. Se i tempi di reazione hanno una distribuzione fortemente asimmetrica (con alcuni valori molto elevati), potrebbe essere utile applicare una trasformazione logaritmica per rendere la distribuzione più simmetrica e migliorare l’interpretabilità dei risultati.

  • Codifica delle variabili categoriche: Se è presente una variabile categorica come il “tipo di intervento” con valori come “cognitivo”, “comportamentale” e “farmacologico”, potrebbe essere necessario trasformare questa variabile in variabili dummy (ad esempio, intervento_cognitivo, intervento_comportamentale, intervento_farmacologico), dove ogni variabile assume il valore 0 o 1 a seconda della presenza o meno di quel tipo di intervento. Questo è utile quando si utilizzano tecniche di regressione.

15.2.2.8 Standardizzazione delle Variabili

La standardizzazione è utile quando si desidera rendere comparabili variabili misurate su scale diverse, ad esempio per confronti tra gruppi o per inclusione in modelli di regressione.

Esempio. Supponiamo di avere una variabile che misura il livello di ansia su una scala da 0 a 100. Per standardizzarla:

  1. Sottrai la media del campione dalla variabile.
  2. Dividi per la deviazione standard.

Il risultato è una variabile con media pari a 0 e deviazione standard pari a 1.

Vantaggi della standardizzazione:

  • facilita l’interpretazione dei coefficienti in un modello di regressione;
  • permette un confronto diretto tra variabili che hanno unità di misura diverse.

15.2.2.9 Normalizzazione delle Variabili

La normalizzazione consiste nel ridimensionare i dati su una scala predefinita, spesso compresa tra 0 e 1. Questo processo è particolarmente utile in analisi multivariate, dove variabili con scale molto diverse potrebbero influenzare in modo sproporzionato i risultati.

Esempio. Hai dati su:

  • Ore di sonno (misurate in ore, da 0 a 24).
  • Livello di stress (misurato su una scala da 1 a 50).
  • Auto-efficacia (misurata su una scala da 0 a 100).

Per garantire che ogni variabile abbia lo stesso peso nell’analisi, puoi normalizzarle usando una formula come:

\[ x_{\text{norm}} = \frac{x - \text{min}(x)}{\text{max}(x) - \text{min}(x)} . \]

Perché Standardizzare o Normalizzare?

Trasformare le variabili è cruciale per:

  1. Gestire scale diverse: Riduce il rischio che variabili con valori numericamente più grandi dominino i risultati.
  2. Garantire validità e interpretabilità: Facilita il confronto tra dati provenienti da fonti o gruppi diversi.
  3. Evitare problemi numerici nei modelli statistici: Alcuni algoritmi di machine learning o tecniche di ottimizzazione richiedono che i dati siano su scale simili per funzionare correttamente.

In conclusione, la scelta tra standardizzazione e normalizzazione dipende dal contesto dell’analisi e dagli obiettivi specifici. Entrambi i processi sono strumenti indispensabili per garantire che i dati siano trattati in modo adeguato, portando a risultati robusti e facilmente interpretabili.

15.2.2.10 Aggiornare i Tipi delle Variabili

Nel caso presente non è necessario. Supponiamo invece di avere una colonna in un dataset psicologico che contiene punteggi di un questionario, ma i dati sono stati importati come stringhe (testo) invece che come numeri. Per eseguire calcoli statistici, sarà necessario convertire questa colonna da stringa a numerico.

In R, si potrebbe usare il seguente codice:

# Supponiamo di avere un data frame chiamato 'df' con una colonna 'punteggio' importata come carattere
df$punteggio <- as.numeric(df$punteggio)

# Ora la colonna 'punteggio' è stata convertita in un tipo numerico ed è possibile eseguire calcoli su di essa

In questo esempio, la funzione as.numeric() viene utilizzata per convertire la colonna punteggio in un formato numerico, permettendo di eseguire analisi quantitative sui dati.

Un altro caso molto comune si verifica quando si importano dati da file Excel. Spesso capita che, all’interno di una cella di una colonna che dovrebbe contenere solo valori numerici, venga inserito erroneamente uno o più caratteri alfanumerici. Di conseguenza, l’intera colonna viene interpretata come di tipo alfanumerico, anche se i valori dovrebbero essere numerici. In questi casi, è fondamentale individuare la cella problematica, correggere manualmente il valore errato, e poi riconvertire l’intera colonna da alfanumerica a numerica.

15.2.2.11 Ricodificare le Variabili

Anche se in questo caso non è necessario, la ricodifica delle variabili è una pratica molto comune nelle analisi dei dati psicologici.

Per esempio, consideriamo una variabile categoriale con modalità descritte da stringhe poco comprensibili, che vengono ricodificate con nomi più chiari e comprensibili.

Supponiamo di avere un DataFrame chiamato df con una colonna tipo_intervento che contiene le modalità "CT", "BT", e "MT" per rappresentare rispettivamente “Terapia Cognitiva”, “Terapia Comportamentale” e “Terapia Mista”. Queste abbreviazioni potrebbero non essere immediatamente chiare a chiunque analizzi i dati, quindi decidiamo di ricodificarle con nomi più espliciti. Ecco come farlo in R:

# Tibble chiamato 'df' con una colonna 'tipo_intervento'
df <- tibble(tipo_intervento = c("CT", "BT", "MT", "CT", "BT"))
df
#> # A tibble: 5 × 1
#>   tipo_intervento
#>   <chr>          
#> 1 CT             
#> 2 BT             
#> 3 MT             
#> 4 CT             
#> 5 BT
# Ricodifica delle modalità della variabile 'tipo_intervento' in nomi più comprensibili
df <- df %>%
  mutate(tipo_intervento_ricodificato = dplyr::recode(
    tipo_intervento,
    "CT" = "Terapia Cognitiva",
    "BT" = "Terapia Comportamentale",
    "MT" = "Terapia Mista"
  ))

# Mostra il tibble con la nuova colonna ricodificata
df
#> # A tibble: 5 × 2
#>   tipo_intervento tipo_intervento_ricodificato
#>   <chr>           <chr>                       
#> 1 CT              Terapia Cognitiva           
#> 2 BT              Terapia Comportamentale     
#> 3 MT              Terapia Mista               
#> 4 CT              Terapia Cognitiva           
#> 5 BT              Terapia Comportamentale

15.2.2.12 Aggiungere Nuove Variabili nel Data Frame

Nel caso presente non è richiesto, ma aggiungere nuove variabili a un DataFrame è un’operazione comune durante l’analisi dei dati. Un esempio è il calcolo dell’indice di massa corporea (BMI).

Supponiamo di avere un DataFrame chiamato df che contiene le colonne peso_kg (peso in chilogrammi) e altezza_m (altezza in metri) per ciascun partecipante a uno studio psicologico. Per arricchire il dataset, possiamo calcolare il BMI per ogni partecipante e aggiungerlo come una nuova variabile.

Il BMI si calcola con la formula:

\[ \text{BMI} = \frac{\text{peso in kg}}{\text{altezza in metri}^2} .\]

Ecco come aggiungere la nuova colonna.

# Supponiamo di avere un tibble chiamato 'df' con le colonne 'peso_kg' e 'altezza_m'
df <- tibble(
  peso_kg = c(70, 85, 60, 95),
  altezza_m = c(1.75, 1.80, 1.65, 1.90)
)
df
#> # A tibble: 4 × 2
#>   peso_kg altezza_m
#>     <dbl>     <dbl>
#> 1      70      1.75
#> 2      85      1.8 
#> 3      60      1.65
#> 4      95      1.9
# Calcola il BMI e aggiungilo come una nuova colonna 'BMI'
df <- df %>%
  mutate(BMI = peso_kg / (altezza_m^2))

# Mostra il tibble con la nuova variabile aggiunta
df
#> # A tibble: 4 × 3
#>   peso_kg altezza_m   BMI
#>     <dbl>     <dbl> <dbl>
#> 1      70      1.75  22.9
#> 2      85      1.8   26.2
#> 3      60      1.65  22.0
#> 4      95      1.9   26.3

15.2.3 Affrontare il Problema dei Dati Mancanti

I dati mancanti sono un problema comune nelle ricerche psicologiche e in molte altre discipline. Quando mancano delle informazioni in un dataset, possono verificarsi gravi problemi per l’analisi statistica, come risultati distorti, riduzione della precisione delle stime o, in alcuni casi, l’impossibilità di applicare alcuni algoritmi.

15.2.3.1 Perché i Dati Mancanti Sono un Problema?

Immagina di voler capire il rendimento medio di una classe in un test, ma alcuni studenti hanno lasciato delle risposte in bianco. Se ignoriamo le risposte mancanti o eliminiamo gli studenti con dati incompleti, rischiamo di ottenere una stima che non rappresenta correttamente la realtà. Questo succede perché:

  • Bias dei risultati: Se i dati mancanti non sono casuali (ad esempio, i dati mancanti sono presenti più spesso in studenti con basso rendimento), le conclusioni possono essere errate.
  • Riduzione della potenza statistica: Eliminare dati incompleti riduce il numero totale di osservazioni, rendendo più difficile trovare risultati significativi.
  • Impossibilità di applicare alcuni metodi: Molti algoritmi statistici richiedono dati completi e non funzionano con valori mancanti.

15.2.3.2 Come Gestire i Dati Mancanti?

Ci sono diversi modi per affrontare i dati mancanti. Vediamo prima i metodi più semplici e poi quelli più avanzati.

Esaminiamo il data frame iniziale:

svy |> 
  summary()
#>      stu_id      grade_level       math1        math2          
#>  Min.   :1347   Min.   : 9.0   Min.   :2.0   Length:5          
#>  1st Qu.:1368   1st Qu.: 9.0   1st Qu.:3.0   Class :character  
#>  Median :1377   Median :10.0   Median :3.0   Mode  :character  
#>  Mean   :1376   Mean   :10.2   Mean   :3.2                     
#>  3rd Qu.:1387   3rd Qu.:11.0   3rd Qu.:4.0                     
#>  Max.   :1399   Max.   :12.0   Max.   :4.0                     
#>                                                                
#>      math3          math4     
#>  Min.   :2.00   Min.   :1.00  
#>  1st Qu.:2.75   1st Qu.:1.75  
#>  Median :3.00   Median :2.50  
#>  Mean   :3.00   Mean   :2.50  
#>  3rd Qu.:3.25   3rd Qu.:3.25  
#>  Max.   :4.00   Max.   :4.00  
#>  NA's   :1      NA's   :1

Si noti la presenza di dati mancanti sulle variabili math3 e math4.

dim(svy)
#> [1] 5 6
  1. Esclusione dei Casi Incompleti (Complete Case Analysis).
    Un approccio comune, ma spesso non ideale, è quello di analizzare solo i casi completi, eliminando tutte le righe con valori mancanti. In R, questo si può fare con il seguente comando:

    svy_comp <- svy |>
      drop_na()

    In questo modo abbiamo escluso tutte le righe nelle quali sono presenti dei dati mancanti (in questo caso, una sola riga).

    dim(svy_comp)
    #> [1] 4 6

    Limite: Questo metodo può introdurre bias se i dati mancanti non sono casuali e riduce il campione, compromettendo l’affidabilità delle analisi.

  2. Imputazione Semplice
    Sostituire i valori mancanti con stime semplici:

    • Media o mediana: Per le variabili numeriche, sostituire i valori mancanti con la media o la mediana. Questo metodo è facile da implementare, ma può ridurre la variabilità nei dati.
    • Moda: Per le variabili categoriche, sostituire i valori mancanti con il valore più frequente. Tuttavia, può introdurre distorsioni se i dati sono molto eterogenei.
  3. Imputazione Multipla
    Un approccio più avanzato è l’imputazione multipla, che utilizza modelli statistici per stimare i valori mancanti in modo iterativo. L’idea di base è semplice: ogni valore mancante viene stimato tenendo conto delle relazioni con tutte le altre variabili.

    Vantaggi:

    • Mantiene la variabilità dei dati.
    • Preserva le relazioni tra le variabili.
    • Riduce il rischio di bias rispetto ai metodi semplici.

15.2.3.3 Applicazione Pratica: Imputazione Multipla con mice in R

Supponiamo di avere un dataset con alcune colonne numeriche che contengono valori mancanti. Possiamo utilizzare il pacchetto mice per imputare i dati mancanti.

Selezioniamo le colonne numeriche da imputare.

numeric_columns <- c("math1", "math2", "math3", "math4")
svy <- svy %>%
  mutate(across(all_of(numeric_columns), as.numeric))

Eseguiamo l’imputazione multipla.

imputed <- mice(
  svy[numeric_columns], 
  m = 1, 
  maxit = 10, 
  method = "norm.predict", 
  seed = 123
)
#> 
#>  iter imp variable
#>   1   1  math3  math4
#>   2   1  math3  math4
#>   3   1  math3  math4
#>   4   1  math3  math4
#>   5   1  math3  math4
#>   6   1  math3  math4
#>   7   1  math3  math4
#>   8   1  math3  math4
#>   9   1  math3  math4
#>   10   1  math3  math4

Ottieniamo il dataset con i valori imputati.

svy_imputed <- complete(imputed)

Arrotondiamo i valori imputati (se necessario).

svy_imputed <- svy_imputed %>%
  mutate(across(everything(), round))

Sostituiamo i valori imputati nel dataset originale.

svy[numeric_columns] <- svy_imputed

Esaminiamo il risultato ottenuto.

svy |> 
  summary()
#>      stu_id      grade_level       math1         math2         math3    
#>  Min.   :1347   Min.   : 9.0   Min.   :2.0   Min.   :1.0   Min.   :2.0  
#>  1st Qu.:1368   1st Qu.: 9.0   1st Qu.:3.0   1st Qu.:1.0   1st Qu.:3.0  
#>  Median :1377   Median :10.0   Median :3.0   Median :2.0   Median :3.0  
#>  Mean   :1376   Mean   :10.2   Mean   :3.2   Mean   :2.2   Mean   :3.2  
#>  3rd Qu.:1387   3rd Qu.:11.0   3rd Qu.:4.0   3rd Qu.:3.0   3rd Qu.:4.0  
#>  Max.   :1399   Max.   :12.0   Max.   :4.0   Max.   :4.0   Max.   :4.0  
#>      math4    
#>  Min.   :1.0  
#>  1st Qu.:2.0  
#>  Median :3.0  
#>  Mean   :2.8  
#>  3rd Qu.:4.0  
#>  Max.   :4.0

15.2.3.4 Come Funziona l’Imputazione Multipla?

  1. Ogni variabile con valori mancanti viene modellata come funzione delle altre variabili.
  2. I valori mancanti vengono stimati iterativamente. In ogni iterazione, si utilizza l’output precedente come input per migliorare le stime.
  3. Dopo un numero sufficiente di iterazioni, le stime si stabilizzano (convergenza).

In conclusione, l’imputazione multipla è una tecnica avanzata che permette di gestire i dati mancanti preservando la qualità delle analisi. Rispetto ai metodi semplici, consente di mantenere la variabilità e ridurre il rischio di bias, rendendola una scelta ideale per analisi psicologiche e di ricerca.

15.2.3.5 Aggiungere i Metadati

I metadati sono informazioni che descrivono i dati stessi, come etichette di variabili, etichette di valori, informazioni sull’origine dei dati, unità di misura e altro ancora. Questi metadati sono essenziali per comprendere, documentare e condividere correttamente un dataset.

In R, i metadati sono gestiti in modo molto dettagliato e strutturato attraverso pacchetti come haven, labelled, e Hmisc. Questi pacchetti consentono di associare etichette ai dati, come etichette di variabili e di valori, e persino di gestire i valori mancanti con etichette specifiche.

  • Etichette di variabili: Si possono aggiungere direttamente alle colonne di un DataFrame usando funzioni come labelled::set_variable_labels().
  • Etichette di valori: Possono essere aggiunte a variabili categoriali utilizzando labelled::labelled().
  • Valori mancanti: In R, è possibile etichettare specifici valori come mancanti usando labelled::na_values<-.

Questi strumenti rendono molto facile documentare un dataset all’interno del processo di analisi, assicurando che tutte le informazioni critiche sui dati siano facilmente accessibili e ben documentate.

Esaminiamo un esempio pratico. Consideriamo nuovamente il data set svy:

glimpse(svy)
#> Rows: 5
#> Columns: 6
#> $ stu_id      <int> 1347, 1368, 1377, 1387, 1399
#> $ grade_level <int> 9, 10, 9, 11, 12
#> $ math1       <dbl> 2, 3, 4, 3, 4
#> $ math2       <dbl> 1, 2, 4, 3, 1
#> $ math3       <dbl> 3, 2, 4, 4, 3
#> $ math4       <dbl> 3, 2, 4, 4, 1

Si noti che la variabile math2 contiene un valore inamissibile, probabilmente un errore di battitura. Questo fa in modo che math2 sia di tipo char mentre dovrebbe essere una variabile numerica. Correggiamo.

# Correzione di `math2`: Rimuovi valori non validi e converti in numerico
svy$math2 <- gsub("\\n", "", svy$math2)  # Rimuovi caratteri non validi come '\n'
svy$math2 <- as.numeric(svy$math2)      # Converte la variabile in numerico

# Visualizzazione del dataset corretto
print(svy)
#>   stu_id grade_level math1 math2 math3 math4
#> 1   1347           9     2     1     3     3
#> 2   1368          10     3     2     2     2
#> 3   1377           9     4     4     4     4
#> 4   1387          11     3     3     4     4
#> 6   1399          12     4     1     3     1

Definiamo le etichette di valore per le variabili math1:math4.

value_labels_math <- set_names(
  as.numeric(names(c(
    `1` = "strongly disagree",
    `2` = "disagree",
    `3` = "agree",
    `4` = "strongly agree"
  ))),
  c("strongly disagree", "disagree", "agree", "strongly agree")
)

Aggiungiamo le etichette di valore alle colonne math1:math4.

svy <- svy %>%
  mutate(across(starts_with("math"), ~ labelled(., labels = value_labels_math)))

Verifica delle etichette.

val_labels(svy$math1)
#> strongly disagree          disagree             agree    strongly agree 
#>                 1                 2                 3                 4
svy
#>   stu_id grade_level math1 math2 math3 math4
#> 1   1347           9     2     1     3     3
#> 2   1368          10     3     2     2     2
#> 3   1377           9     4     4     4     4
#> 4   1387          11     3     3     4     4
#> 6   1399          12     4     1     3     1
15.2.3.5.1 Utilizzo delle Etichette in R con Variabili Numeriche

Le etichette dei valori (value labels) vengono utilizzate per rendere più leggibili e interpretabili le variabili numeriche, associando ad ogni valore un’etichetta descrittiva. Questo approccio è particolarmente utile in ambiti come la ricerca psicologica, dove le risposte ai questionari sono spesso codificate con numeri (ad esempio, 1 = “Strongly Disagree”, 2 = “Disagree”, ecc.) ma rappresentano concetti qualitativi.

Vantaggi dell’Uso delle Etichette

  1. Chiarezza nelle Analisi: Le etichette descrittive rendono i dati più facilmente comprensibili senza dover ricordare il significato numerico di ciascun valore.
  2. Documentazione Integrata: Permettono di incorporare metadati direttamente nelle variabili, migliorando la trasparenza e riducendo il rischio di interpretazioni errate.
  3. Compatibilità con Software Statistici: Molti strumenti (ad esempio, SPSS o Stata) utilizzano etichette di valori. Il pacchetto haven in R consente di gestire facilmente i dati etichettati esportati/importati da questi software.

Manipolazione di Variabili Etichettate

Anche se una variabile numerica è etichettata con labelled (ad esempio, tramite il pacchetto haven), essa conserva la sua natura numerica e può essere utilizzata in calcoli, modelli statistici, e trasformazioni. Le etichette non alterano il valore sottostante, ma lo arricchiscono con informazioni aggiuntive.

In conclusione, le etichette dei valori migliorano l’interpretabilità dei dati senza comprometterne la manipolabilità. Questo approccio è ideale per mantenere le variabili numeriche pienamente funzionali per analisi statistiche, mentre le etichette descrittive forniscono un contesto chiaro e leggibile.

15.2.3.6 Validazione dei Dati

La validazione dei dati è un passaggio fondamentale per garantire che il dataset soddisfi i criteri previsti e sia pronto per le analisi successive. Questo processo include il controllo della coerenza e della correttezza dei dati in base a specifiche regole definite dal dizionario dei dati. Alcune verifiche comuni includono:

  • Unicità delle righe: Assicurarsi che ogni riga sia unica, verificando l’assenza di ID duplicati.
  • Validità degli ID: Controllare che gli ID rientrino in un intervallo previsto (es. numerico).
  • Valori accettabili nelle variabili categoriali: Verificare che variabili come grade_level, int e le colonne math contengano esclusivamente valori appartenenti a un set di valori validi.

Il pacchetto pointblank fornisce strumenti flessibili e intuitivi per eseguire verifiche di validazione e generare report dettagliati. Questo pacchetto consente di:

  • Definire le regole di validazione: Specificare controlli come unicità, intervalli di valori e appartenenza a insiemi predefiniti.
  • Eseguire i controlli: Applicare le regole di validazione su un dataset per identificare eventuali discrepanze.
  • Generare report interattivi: Creare un riepilogo chiaro e visivo dei controlli, evidenziando eventuali errori o anomalie.

Con pointblank, è possibile integrare la validazione dei dati come parte di un workflow strutturato, garantendo la qualità dei dati in modo sistematico e ripetibile.

create_agent(svy) %>%
  rows_distinct(columns = vars(stu_id)) %>%
  col_vals_between(columns = c(stu_id), 
                   left = 1300, right = 1400, na_pass = TRUE) %>%
  col_vals_in_set(columns = c(grade_level), 
                  set = c(9, 10, 11, 12, NA)) %>%
  col_vals_in_set(columns = c(int),
                  set = c(0, 1, NA)) %>%
  col_vals_in_set(columns = c(math1:math4),
                  set = c(1, 2, 3, 4, NA)) %>%
  interrogate()
Pointblank Validation
[2025-03-09|21:35:45]
data frame svy
STEP COLUMNS VALUES TBL EVAL UNITS PASS FAIL W S N EXT

1
rows_distinct
 rows_distinct()

stu_id

5 5
1
0
0

2
col_vals_between
 col_vals_between()

stu_id

[1,300, 1,400]

5 5
1
0
0

3
col_vals_in_set
 col_vals_in_set()

grade_level

9, 10, 11, 12, NA

5 5
1
0
0

4
col_vals_in_set
 col_vals_in_set()

int

0, 1, NA

💥

5
col_vals_in_set
 col_vals_in_set()

math1

1, 2, 3, 4, NA

5 5
1
0
0

6
col_vals_in_set
 col_vals_in_set()

math2

1, 2, 3, 4, NA

5 5
1
0
0

7
col_vals_in_set
 col_vals_in_set()

math3

1, 2, 3, 4, NA

5 5
1
0
0

8
col_vals_in_set
 col_vals_in_set()

math4

1, 2, 3, 4, NA

5 5
1
0
0
2025-03-09 21:35:45 CET < 1 s 2025-03-09 21:35:45 CET

Il dataset ripulito soddisfa tutte le aspettative delineate da Crystal Lewis.

  • Completo: Tutti i dati raccolti sono stati inseriti e/o recuperati. Non dovrebbero esserci dati estranei che non appartengono al dataset (come duplicati o partecipanti non autorizzati).
  • Valido: Le variabili rispettano i vincoli definiti nel tuo dizionario dei dati. Ricorda che il dizionario dei dati specifica i nomi delle variabili, i tipi, i range, le categorie e altre informazioni attese.
  • Accurato: Sebbene non sia sempre possibile determinare l’accuratezza dei valori durante il processo di pulizia dei dati (ovvero, se un valore è realmente corretto o meno), in alcuni casi è possibile valutarla sulla base della conoscenza pregressa riguardante quel partecipante o caso specifico.
  • Coerente: I valori sono allineati tra le varie fonti. Ad esempio, la data di nascita raccolta attraverso un sondaggio studentesco dovrebbe avere un formato corrispondere alla data di nascita raccolta dal distretto scolastico.
  • Uniforme: I dati sono standardizzati attraverso i moduli e nel tempo. Ad esempio, lo stato di partecipazione ai programmi di pranzo gratuito o a prezzo ridotto è sempre fornito come una variabile numerica con la stessa rappresentazione, oppure il nome della scuola è sempre scritto in modo coerente in tutto il dataset.
  • De-identificato: Tutte le informazioni personali identificabili (PII) sono state rimosse dal dataset per proteggere la riservatezza dei partecipanti (se richiesto dal comitato etico/consenso informato).
  • Interpretabile: I dati hanno nomi di variabili leggibili sia da umani che dal computer, e sono presenti etichette di variabili e valori laddove necessario per facilitare l’interpretazione.
  • Analizzabile: Il dataset è in un formato rettangolare (righe e colonne), leggibile dal computer e conforme alle regole di base della struttura dei dati.

Una volta completati i 14 passaggi precedenti, è possibile esportare questo dataset ripulito nella cartella processed per le successive analisi statistiche.

15.2.3.7 Unire e/o aggiungere dati se necessario

In questo passaggio, è possibile unire o aggiungere colonne o righe presenti in file diversi. È importante eseguire nuovamente i controlli di validazione dopo l’unione/aggiunta di nuovi dati.

15.2.3.8 Trasformare i dati se necessario

Esistono vari motivi per cui potrebbe essere utile memorizzare i dati in formato long o wide. In questo passaggio, è possibile ristrutturare i dati secondo le esigenze.

15.2.3.9 Salvare il dataset pulito finale

L’ultimo passaggio del processo di pulizia consiste nell’esportare o salvare il dataset pulito. Come accennato in precedenza, può essere utile esportare/salvare il dataset in più di un formato di file (ad esempio, un file .csv e un file .parquet).

15.3 Organizzazione dei file e informazioni aggiuntive

Infine, è essenziale includere una documentazione adeguata per garantire che le informazioni siano interpretate correttamente, sia da altri utenti che da te stesso, se dovessi tornare a lavorare su questo progetto in futuro. La documentazione minima da fornire dovrebbe includere:

  • Documentazione a livello di progetto: Questa sezione fornisce informazioni contestuali sul perché e come i dati sono stati raccolti. È utile per chiunque voglia comprendere lo scopo e la metodologia del progetto.
  • Metadati a livello di progetto: Se condividi i dati in un repository pubblico o privato, è importante includere metadati a livello di progetto. Questi metadati forniscono informazioni dettagliate che facilitano la ricerca, la comprensione e la consultabilità dei dati. I metadati a livello di progetto possono includere descrizioni generali del progetto, parole chiave, e riferimenti bibliografici.
  • Dizionario dei dati: Un documento che descrive tutte le variabili presenti nel dataset, inclusi i loro nomi, tipi, range di valori, categorie e qualsiasi altra informazione rilevante. Questo strumento è fondamentale per chiunque voglia comprendere o analizzare i dati.
  • README: Un file che fornisce una panoramica rapida dei file inclusi nel progetto, spiegando cosa contengono e come sono interconnessi. Il README è spesso il primo documento consultato e serve a orientare l’utente tra i vari file e risorse del progetto. Questa documentazione non solo aiuta a mantenere il progetto organizzato, ma è anche cruciale per facilitare la collaborazione e l’archiviazione a lungo termine.

15.4 Dizionario dei Dati

Approfondiamo qui il problema della creazione del Dizionario dei dati.

Un dizionario dei dati è un documento che descrive le caratteristiche di ciascuna variabile in un dataset. Include informazioni come il nome della variabile, il tipo di dato, il range di valori, le categorie (per le variabili categoriche), e altre informazioni rilevanti. Questo strumento è essenziale per comprendere e analizzare correttamente il dataset.

Si presti particolare attenzione alle guide di stile per la denominazione delle variabili e la codifica dei valori delle risposte.

15.4.1 Esempio in R

Ecco come tradurre i passi per creare un dizionario dei dati in R, utilizzando il pacchetto tibble per creare il dizionario e writexl o readr per esportarlo in formato .xlsx o .csv.

  1. Identificare le variabili: Elencare tutte le variabili presenti nel dataset.
  2. Descrivere ogni variabile: Per ciascuna variabile, definire il tipo (ad esempio, integer, numeric, character), il range di valori accettabili o le categorie, e fornire una descrizione chiara.
  3. Salvare il dizionario dei dati: Il dizionario può essere salvato in un file .csv o .xlsx per una facile consultazione.
svy
#>   stu_id grade_level math1 math2 math3 math4
#> 1   1347           9     2     1     3     3
#> 2   1368          10     3     2     2     2
#> 3   1377           9     4     4     4     4
#> 4   1387          11     3     3     4     4
#> 6   1399          12     4     1     3     1

Creeremo un dizionario dei dati per un dataset di esempio e lo salveremo sia in formato CSV che Excel.

library(tibble)
library(readr)
library(writexl)

# Creazione del Dizionario dei Dati
data_dict <- tibble(
  `Variable Name` = c(
    "stu_id",
    "svy_date",
    "grade_level",
    "math1",
    "math2",
    "math3",
    "math4"
  ),
  `Type` = c(
    "integer",
    "datetime",
    "integer",
    "integer",
    "integer",
    "numeric",
    "numeric"
  ),
  `Description` = c(
    "Student ID",
    "Survey Date",
    "Grade Level",
    "Math Response 1 (1: Strongly Disagree, 4: Strongly Agree)",
    "Math Response 2 (1: Strongly Disagree, 4: Strongly Agree)",
    "Math Response 3 (1: Strongly Disagree, 4: Strongly Agree)",
    "Math Response 4 (1: Strongly Disagree, 4: Strongly Agree)"
  ),
  `Range/Values` = c(
    "1347-1399",
    "2023-02-13 to 2023-02-14",
    "9-12",
    "1-4",
    "1-4",
    "1.0-4.0 (NA allowed)",
    "1.0-4.0 (NA allowed)"
  )
)

# Visualizza il Dizionario dei Dati
print(data_dict)
#> # A tibble: 7 × 4
#>   `Variable Name` Type     Description                       `Range/Values` 
#>   <chr>           <chr>    <chr>                             <chr>          
#> 1 stu_id          integer  Student ID                        1347-1399      
#> 2 svy_date        datetime Survey Date                       2023-02-13 to …
#> 3 grade_level     integer  Grade Level                       9-12           
#> 4 math1           integer  Math Response 1 (1: Strongly Dis… 1-4            
#> 5 math2           integer  Math Response 2 (1: Strongly Dis… 1-4            
#> 6 math3           numeric  Math Response 3 (1: Strongly Dis… 1.0-4.0 (NA al…
#> 7 math4           numeric  Math Response 4 (1: Strongly Dis… 1.0-4.0 (NA al…

# Salva il Dizionario dei Dati in un file CSV
write_csv(data_dict, here::here("data", "processed", "data_dictionary.csv"))

# Salva il Dizionario dei Dati in un file Excel
write_xlsx(data_dict, here::here("data", "processed", "data_dictionary.xlsx"))

Output Atteso: file CSV (data_dictionary.csv).

data_dict <- rio::import(
  here::here("data", "processed", "data_dictionary.csv")
)
print(data_dict)
#>   Variable Name     Type
#> 1        stu_id  integer
#> 2      svy_date datetime
#> 3   grade_level  integer
#> 4         math1  integer
#> 5         math2  integer
#> 6         math3  numeric
#> 7         math4  numeric
#>                                                 Description
#> 1                                                Student ID
#> 2                                               Survey Date
#> 3                                               Grade Level
#> 4 Math Response 1 (1: Strongly Disagree, 4: Strongly Agree)
#> 5 Math Response 2 (1: Strongly Disagree, 4: Strongly Agree)
#> 6 Math Response 3 (1: Strongly Disagree, 4: Strongly Agree)
#> 7 Math Response 4 (1: Strongly Disagree, 4: Strongly Agree)
#>               Range/Values
#> 1                1347-1399
#> 2 2023-02-13 to 2023-02-14
#> 3                     9-12
#> 4                      1-4
#> 5                      1-4
#> 6     1.0-4.0 (NA allowed)
#> 7     1.0-4.0 (NA allowed)

15.4.1.1 Uso del pacchetto dataMeta

Il pacchetto dataMeta è progettato per generare metadati e dizionari dei dati in modo strutturato.

library(dataMeta)
library(tibble)

# Descrizioni delle variabili
variable_descriptions <- c(
  "Student ID",
  "Grade Level",
  "Math Response 1 (1: Strongly Disagree, 4: Strongly Agree)",
  "Math Response 2 (1: Strongly Disagree, 4: Strongly Agree)",
  "Math Response 3 (1: Strongly Disagree, 4: Strongly Agree)",
  "Math Response 4 (1: Strongly Disagree, 4: Strongly Agree)"
)

var_type <- c(1, 0, 0, 0, 0, 0)

linker <- build_linker(
  svy, 
  variable_description = variable_descriptions, 
  variable_type = var_type
)

dict <- build_dict(
  my.data = svy, 
  linker = linker, 
  option_description = NULL, 
  prompt_varopts = FALSE
)

kable(dict, format = "html", caption = "Data dictionary for original dataset")
Data dictionary for original dataset
variable_name variable_description variable_options
grade_level Grade Level 9 to 12
math1 Math Response 1 (1: Strongly Disagree, 4: Strongly Agree) 2 to 4
math2 Math Response 2 (1: Strongly Disagree, 4: Strongly Agree) 1 to 4
math3 Math Response 3 (1: Strongly Disagree, 4: Strongly Agree) 2 to 4
math4 Math Response 4 (1: Strongly Disagree, 4: Strongly Agree) 1 to 4
stu_id Student ID 1347
1368
1377
1387
1399

15.4.1.2 Uso del pacchetto skimr

Il pacchetto skimr è utile per generare riassunti dettagliati delle variabili, che possono essere utilizzati come base per un dizionario.

library(skimr)

# Riassunto del dataset
skim_dict <- skim(svy)

kable(skim_dict, format = "html", caption = "Data dictionary for original dataset")
Data dictionary for original dataset
skim_type skim_variable n_missing complete_rate numeric.mean numeric.sd numeric.p0 numeric.p25 numeric.p50 numeric.p75 numeric.p100 numeric.hist
numeric stu_id 0 1 1375.6 19.7180 1347 1368 1377 1387 1399 ▃▁▇▃▃
numeric grade_level 0 1 10.2 1.3038 9 9 10 11 12 ▇▃▁▃▃
numeric math1 0 1 3.2 0.8367 2 3 3 4 4 ▃▁▇▁▇
numeric math2 0 1 2.2 1.3038 1 1 2 3 4 ▇▃▁▃▃
numeric math3 0 1 3.2 0.8367 2 3 3 4 4 ▃▁▇▁▇
numeric math4 0 1 2.8 1.3038 1 2 3 4 4 ▃▃▁▃▇

15.5 Riflessioni Conclusive

Nel processo di analisi dei dati, la fase di pulizia e pre-elaborazione è cruciale per garantire la qualità e l’integrità dei risultati finali. Sebbene questa fase possa sembrare meno interessante rispetto all’analisi vera e propria, essa costituisce la base su cui si costruiscono tutte le successive elaborazioni e interpretazioni. Attraverso una serie di passaggi strutturati, come quelli illustrati in questo capitolo, è possibile trasformare dati grezzi e disordinati in un dataset pulito, coerente e pronto per l’analisi. La cura nella gestione dei dati, dalla rimozione di duplicati alla creazione di un dizionario dei dati, è fondamentale per ottenere risultati affidabili e riproducibili.

15.6 Esercizi

In questo esercizio, applicherai le tecniche di pulizia e preprocessing dei dati utilizzando il dataset SWLS. Il tuo compito è seguire i passaggi descritti per trasformare il dataset in una forma pronta per l’analisi.

Istruzioni

  1. Importa i dati SWLS (Survey of Life Satisfaction Scale). Introduci almeno due dati mancanti nei dati e almeno un duplicato.
  2. Controlla i dati: verifica la struttura e individua eventuali anomalie.
  3. Pulisci i dati:
    • Rimuovi eventuali duplicati.
    • Gestisci i valori mancanti in modo appropriato.
    • Rinomina le variabili per una maggiore chiarezza.
    • Standardizza alcune variabili per l’analisi.
  4. Documenta le modifiche effettuate.
  5. Esporta il dataset pulito.

Consegna

  • Salva il tuo file Quarto con il nome swls_cleaning.qmd.

  • Usa questo header YAML:

    ---
    title: "Assegnamento: Pulizia e Preprocessing dei Dati SWLS"
    author: "Nome Studente"
    date: "2025-03-09"
    format: html
    ---
  • Assicurati che il codice sia commentato e spiegato chiaramente.

  • Esporta il dataset pulito e allegalo alla consegna.

Informazioni sull’Ambiente di Sviluppo

sessionInfo()
#> R version 4.4.2 (2024-10-31)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Sequoia 15.3.1
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
#> 
#> locale:
#> [1] C/UTF-8/C/C/C/C
#> 
#> time zone: Europe/Rome
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#>  [1] skimr_2.1.5       dataMeta_0.1.1    writexl_1.5.1     pointblank_0.12.2
#>  [5] haven_2.5.4       labelled_2.14.0   mice_3.17.0       thematic_0.1.6   
#>  [9] MetBrewer_0.2.0   ggokabeito_0.1.0  see_0.10.0        gridExtra_2.3    
#> [13] patchwork_1.3.0   bayesplot_1.11.1  psych_2.4.12      scales_1.3.0     
#> [17] markdown_1.13     knitr_1.49        lubridate_1.9.4   forcats_1.0.0    
#> [21] stringr_1.5.1     dplyr_1.1.4       purrr_1.0.4       readr_2.1.5      
#> [25] tidyr_1.3.1       tibble_3.2.1      ggplot2_3.5.1     tidyverse_2.0.0  
#> [29] rio_1.2.3         here_1.0.1       
#> 
#> loaded via a namespace (and not attached):
#>  [1] Rdpack_2.6.2      mnormt_2.1.1      rlang_1.1.5       magrittr_2.0.3   
#>  [5] compiler_4.4.2    vctrs_0.6.5       pkgconfig_2.0.3   shape_1.4.6.1    
#>  [9] crayon_1.5.3      fastmap_1.2.0     backports_1.5.0   utf8_1.2.4       
#> [13] blastula_0.3.5    rmarkdown_2.29    tzdb_0.4.0        nloptr_2.1.1     
#> [17] bit_4.6.0         xfun_0.51         glmnet_4.1-8      jomo_2.7-6       
#> [21] jsonlite_1.9.1    pan_1.9           broom_1.0.7       parallel_4.4.2   
#> [25] R6_2.6.1          stringi_1.8.4     boot_1.3-31       rpart_4.1.24     
#> [29] Rcpp_1.0.14       iterators_1.0.14  base64enc_0.1-3   pacman_0.5.1     
#> [33] R.utils_2.13.0    Matrix_1.7-2      splines_4.4.2     nnet_7.3-20      
#> [37] timechange_0.3.0  tidyselect_1.2.1  rstudioapi_0.17.1 codetools_0.2-20 
#> [41] lattice_0.22-6    withr_3.0.2       evaluate_1.0.3    survival_3.8-3   
#> [45] xml2_1.3.7        pillar_1.10.1     foreach_1.5.2     reformulas_0.4.0 
#> [49] generics_0.1.3    vroom_1.6.5       rprojroot_2.0.4   hms_1.1.3        
#> [53] munsell_0.5.1     commonmark_1.9.2  minqa_1.2.8       glue_1.8.0       
#> [57] tools_4.4.2       data.table_1.17.0 lme4_1.1-36       grid_4.4.2       
#> [61] rbibutils_2.3     colorspace_2.1-1  nlme_3.1-167      repr_1.1.7       
#> [65] cli_3.6.4         gt_0.11.1         gtable_0.3.6      R.methodsS3_1.8.2
#> [69] sass_0.4.9        digest_0.6.37     htmlwidgets_1.6.4 farver_2.1.2     
#> [73] htmltools_0.5.8.1 R.oo_1.27.0       lifecycle_1.0.4   mitml_0.4-5      
#> [77] bit64_4.6.0-1     MASS_7.3-65

Bibliografia

Buchanan, E. M., Crain, S. E., Cunningham, A. L., Johnson, H. R., Stash, H., Papadatou-Pastou, M., Isager, P. M., Carlsson, R., & Aczel, B. (2021). Getting started creating data dictionaries: How to create a shareable data set. Advances in Methods and Practices in Psychological Science, 4(1), 2515245920928007.