Le funzioni di gtools per l’estrazione di campioni

Alla fine di questa puntata…

  • dovreste avere imparato le funzioni disponibili nel package `gtools` per estrarre campioni ordinati e non ordinati usando un processo di estrazioni con e senza rimessa
  • dovreste essere in grado di estrarre campioni usando un identificativo generico o effettuando un campionamento a partire dai valori di una variabile osservata
  • dovreste essere in grado di gestire la struttura dati convertendolo in maniera opportuna

Prima di cominciare… prerequisiti

Sul tuo PC ipotizzo che tu abbia installato sia R che RStudio. Se ti servono istruzioni al riguardo consulta la pagina con le istruzioni disponibile a questo link.

Cosa utilizzeremo in questa lezione?

Se non lo hai già fatto, è necessario installare sul tuo PC queste librerie aggiuntive:

install.packages("gtools")      # per le funzioni di campionamento
install.packages("tidyverse")   # per sfruttare l'approccio orientato ai dati tidy
install.packages("janitor")     # per la funzione tabyl (tabelle di frequenze)

Una volta effettuta l’installazione è necessario caricare le librerie in memoria:

library(gtools)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(janitor)

Attaching package: 'janitor'

The following objects are masked from 'package:stats':

    chisq.test, fisher.test

Non ti preoccupare se vedi questi messaggi a video: ti avvisano solo che nelle librerie aggiuntive che hai caricato (tidyverse e janitor per la precisione) ci sono alcune funzione

Campioni, campioni e solo campioni…

Per mostrare le varie funzioni che permettono di simulare un processo di campionamento ipotizziamo consideriamo una ragionevole dimensione della popolazione e del campione da estrarre:

N <- 10
n <- 3

Campioni con rimessa tenendo conto dell’ordine

E’ facile calcolare il numero di possibili campioni che possono essere estratti utilizzando un procedimento di estrazione con rimessa e tenendo conto dell’ordine delle unità all’interno del campione:

N ^ n
[1] 1000

La funzione permutations con l’argomento repeats.allowed impostato a TRUE permette di ottenere tali campioni:

ordinati_con_rip <- permutations(n = N, r = n, repeats.allowed = TRUE)

come è possibile facilmente verificare andando ad ispezionare il numero di righe della tabella ottenuta:

dim(ordinati_con_rip)
[1] 1000    3

Le funzioni del package gtools restituiscono oggetti atomici di classe matrix:

class(ordinati_con_rip)
[1] "matrix" "array" 

Stampando a video le prime righe della tabella si vede come il processo di campionamento avviene per default sfruttando un indicatore numerico associato alla posizione dell’unità estratta all’interno della popolazione:

head(ordinati_con_rip)
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    1    1    2
[3,]    1    1    3
[4,]    1    1    4
[5,]    1    1    5
[6,]    1    1    6

Campioni con rimessa senza tenere conto dell’ordine

Per calcolare il numero di campioni che possono essere ottenuti usando un procedimento con ripetizione ma senza tener conto dell’ordine possiamo calcolare una sequenza con il numero di elementi che è possibile estrarre in ciascuna posizione del campione:

seq(N, N - n + 1)
[1] 10  9  8

per calcolarne la produttoria:

prod(seq(N, N - n + 1))
[1] 720

Si può in alternativa sfruttare la regola di conteggio:

factorial(N) / factorial(N - n)
[1] 720

L’estrazione dei campioni si ottiene sfruttando sempre la funzione permutations ma impostando a FALSE l’argomento repeats.allowed:

ordinati_senza_rip <- permutations(n = N, r = n, repeats.allowed = FALSE)
dim(ordinati_senza_rip)
[1] 720   3

Campioni senza rimessa tenendo conto dell’ordine

La funzione choose permette di calcolare il coefficiente binomiale. Questo il numero di campioni ordinati che è possibile ottenere sfruttando un campionamento senza rimessa:

choose(N + n - 1, n)
[1] 220

Per estrarre tali campioni si può sfruttare la funzione combinations:

non_ordinati_con_rip <- combinations(n = N, r = n, repeats.allowed = TRUE)
dim(non_ordinati_con_rip)
[1] 220   3

Campioni senza rimessa senza tener conto dell’ordine

Calcoliamo infine il numero di campioni che è possibile ottenere usando un procedimento senza rimessa senza tener conto dell’ordine:

choose(N, n)
[1] 120

che possiamo estrarre sempre sfruttando la funzione combinations ma impostando l’argomento repeats.allowed a FALSE:

non_ordinati_senza_rip <- combinations(n = N, r = n, repeats.allowed = FALSE)
dim(non_ordinati_senza_rip)
[1] 120   3

Campioni estraendo da un vettore di identificatori

Negli esempi sopra abbiamo sfruttato solo gli argomenti n, r e repeats.allowed delle due funzioni permutations e combinations: i campioni ottenuti mostravano un identificatore da 1 ad N per indicare la particolare unità estratta. E’ anche possibile sfruttare un argomento aggiuntivo v che indica il vettore sorgente da cui effettuare l’estrazione.

Consideriamo un semplice esempio in cui il vettore sorgente contiene degli identificatori univoci delle unità (caso di campioni di ampiezza 3 estratti da una popolazione di 5 unità):

campioni <- permutations(n = 5, # ampiezza della popolazione
                         r = 3, # taglia del campione
                         # vettore sorgente da cui effettuare le estrazioni
                         v = c("id_1", "id_2", "id_3", "id_4", "id_5"),
                         repeats.allowed = TRUE)

In questo modo, invece degli identificatori numerici, l’oggetto di output contiene gli elementi estratti dal vettore sorgente:

head(campioni)
     [,1]   [,2]   [,3]  
[1,] "id_1" "id_1" "id_1"
[2,] "id_1" "id_1" "id_2"
[3,] "id_1" "id_1" "id_3"
[4,] "id_1" "id_1" "id_4"
[5,] "id_1" "id_1" "id_5"
[6,] "id_1" "id_2" "id_1"

Campioni estraendo da un vettore contenente una variabile

Se il vettore sorgente contiene i valori di una variabile da cui effettuare il campionamento è necessario impostare l’argomento set a FALSE per indicare che il vettore non deve essere considerato come insieme, ovvero senza eliminare le ripetizioni:

campioni <- permutations(n = 5, # ampiezza della popolazione
                         r = 3, # taglia del campione
                         # vettore sorgente da cui effettuare le estrazioni
                         v = c("S", "I", "S", "I", "I"),
                         repeats.allowed = TRUE,
                         # è necessario impostare set = FALSE se il vettore
                         # sorgente contiene valori ripetuti
                         set = FALSE)

L’oggetto di output in questo caso contiene i valori della variabili estratti in ciascun campione:

head(campioni)
     [,1] [,2] [,3]
[1,] "S"  "S"  "S" 
[2,] "S"  "S"  "I" 
[3,] "S"  "S"  "S" 
[4,] "S"  "S"  "I" 
[5,] "S"  "S"  "I" 
[6,] "S"  "I"  "S" 

E’ naturalmente possibile sfruttare una colonna presente in un oggetto tabellare (data.frame o tibble) come vettore sorgente. Consideriamo a titolo di esempio una semplice tabella, che replica una struttura tipica di matrice dei dati:

tab_dati <- data.frame(id = c("id_1", "id_2", "id_3", "id_4", "id_5"),
                       variabile = c("S", "I", "S", "I", "I"))
tab_dati
    id variabile
1 id_1         S
2 id_2         I
3 id_3         S
4 id_4         I
5 id_5         I

Sfruttiamo a questo punto la colonna variabile della tabella come vettore sorgente:

campioni <- permutations(n = 5, # ampiezza della popolazione
                         r = 3, # taglia del campione
                         # vettore sorgente da cui effettuare le estrazioni
                         v = tab_dati$variabile,
                         repeats.allowed = TRUE,
                         # è necessario impostare set = FALSE se il vettore
                         # sorgente contiene valori ripetuti
                         set = FALSE)

Ecco alcuni dei campioni estratti:

head(campioni)
     [,1] [,2] [,3]
[1,] "S"  "S"  "S" 
[2,] "S"  "S"  "I" 
[3,] "S"  "S"  "S" 
[4,] "S"  "S"  "I" 
[5,] "S"  "S"  "I" 
[6,] "S"  "I"  "S" 

Dettagli tecnici: gestione dell’oggetto di output

Per effettuare sintesi più veloci sull’insieme dei possibili campioni (spazio campionario) conviene trasformare la struttura dati da matrice a tabella (data.frame o tibble). La funzione as_tibble, disponibile quando si carica tidyverse, permette di ottenere un oggetto tabellare:

tb_campioni <- as_tibble(campioni)
Warning: The `x` argument of `as_tibble.matrix()` must have unique column names if
`.name_repair` is omitted as of tibble 2.0.0.
ℹ Using compatibility `.name_repair`.
tb_campioni
# A tibble: 125 × 3
   V1    V2    V3   
   <chr> <chr> <chr>
 1 S     S     S    
 2 S     S     I    
 3 S     S     S    
 4 S     S     I    
 5 S     S     I    
 6 S     I     S    
 7 S     I     I    
 8 S     I     S    
 9 S     I     I    
10 S     I     I    
# ℹ 115 more rows

Possiamo verificare velocemente come ciascuna colonna, ovvero le v.c. osservazioni campionarie, replichino esattamente la proporzione di insuccessi (I) e successi (S) presenti nella popolazione, rispettivamente pari a 3 / 5 = 0.6 e 2 / 5 = 0.4:

tabyl(tb_campioni, V1)
 V1  n percent
  I 75     0.6
  S 50     0.4
tabyl(tb_campioni, V2)
 V2  n percent
  I 75     0.6
  S 50     0.4
tabyl(tb_campioni, V3)
 V3  n percent
  I 75     0.6
  S 50     0.4