2.7 Data frame

I data.frame sono strutture tipo matrice, in cui le colonne possono essere vettori di tipi differenti. La funzione usata per generare un data frame è data.frame(), che permette di unire più vettori di uguale lunghezza come colonne del data frame, ognuno dei quali si riferisce ad una diversa variabile. Ad esempio,

df <- data.frame(
  face = c("ace", "two", "six"),
  suit = c("clubs", "clubs", "clubs"),
  value = c(1, 2, 3)
)
df
#>   face  suit value
#> 1  ace clubs     1
#> 2  two clubs     2
#> 3  six clubs     3

L’estrazione di dati da un data.frame può essere effettuata in maniera simile a quanto avviene per i vettori. Ad esempio, per estrarre la variabile value dal data.frame df si può indicare l’indice della terza colonna:

df[, 3]
#> [1] 1 2 3

Dal momento che le colonne sono delle variabili, è possibile estrarle anche indicando nome della variabile, scrivendo nome_data_frame$nome_variabile:

df$value
#> [1] 1 2 3

Per fare un esempio, creiamo un data.frame che contenga tutte le informazioni di un mazzo di carte da poker (Grolemund 2014). In tale data.frame, ciascuna riga corrisponde ad una carta – in un mazzo da poker ci sono 52 carte, perciò il data.frame avrà 52 righe. Il vettore face indica con una stringa di caratteri il valore di ciascuna carta, il vettore suit indica il seme e il vettore value indica con un numero intero il valore di ciascuna carta. Quindi, il data.frame avrà 3 colonne.

deck <- data.frame(
  face = c(
    "king", "queen", "jack", "ten", "nine", "eight",
    "seven", "six", "five", "four", "three", "two", "ace",
    "king", "queen", "jack", "ten", "nine", "eight", "seven",
    "six", "five", "four", "three", "two", "ace", "king",
    "queen", "jack", "ten", "nine", "eight", "seven", "six",
    "five", "four", "three", "two", "ace", "king", "queen",
    "jack", "ten", "nine", "eight", "seven", "six", "five",
    "four", "three", "two", "ace"
  ),
  suit = c(
    "spades", "spades", "spades", "spades",
    "spades", "spades", "spades", "spades", "spades",
    "spades", "spades", "spades", "spades", "clubs", "clubs",
    "clubs", "clubs", "clubs", "clubs", "clubs", "clubs",
    "clubs", "clubs", "clubs", "clubs", "clubs", "diamonds",
    "diamonds", "diamonds", "diamonds", "diamonds",
    "diamonds", "diamonds", "diamonds", "diamonds",
    "diamonds", "diamonds", "diamonds", "diamonds", "hearts",
    "hearts", "hearts", "hearts", "hearts", "hearts",
    "hearts", "hearts", "hearts", "hearts", "hearts",
    "hearts", "hearts"
  ),
  value = c(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
)

Avendo salvato tutte queste informazioni nell’oggetto deck, possiamo stamparle sullo schermo semplicemente digitando il nome dell’oggetto che le contiene:

deck
#>     face     suit value
#> 1   king   spades    13
#> 2  queen   spades    12
#> 3   jack   spades    11
#> 4    ten   spades    10
#> 5   nine   spades     9
#> 6  eight   spades     8
#> 7  seven   spades     7
#> 8    six   spades     6
#> 9   five   spades     5
#> 10  four   spades     4
#> 11 three   spades     3
#> 12   two   spades     2
#> 13   ace   spades     1
#> 14  king    clubs    13
#> 15 queen    clubs    12
#> 16  jack    clubs    11
#> 17   ten    clubs    10
#> 18  nine    clubs     9
#> 19 eight    clubs     8
#> 20 seven    clubs     7
#> 21   six    clubs     6
#> 22  five    clubs     5
#> 23  four    clubs     4
#> 24 three    clubs     3
#> 25   two    clubs     2
#> 26   ace    clubs     1
#> 27  king diamonds    13
#> 28 queen diamonds    12
#> 29  jack diamonds    11
#> 30   ten diamonds    10
#> 31  nine diamonds     9
#> 32 eight diamonds     8
#> 33 seven diamonds     7
#> 34   six diamonds     6
#> 35  five diamonds     5
#> 36  four diamonds     4
#> 37 three diamonds     3
#> 38   two diamonds     2
#> 39   ace diamonds     1
#> 40  king   hearts    13
#> 41 queen   hearts    12
#> 42  jack   hearts    11
#> 43   ten   hearts    10
#> 44  nine   hearts     9
#> 45 eight   hearts     8
#> 46 seven   hearts     7
#> 47   six   hearts     6
#> 48  five   hearts     5
#> 49  four   hearts     4
#> 50 three   hearts     3
#> 51   two   hearts     2
#> 52   ace   hearts     1

Si noti che, a schermo, R stampa un numero progressivo che corrisponde al numero della riga.

2.7.1 Selezione di elementi

Una volta creato un data.frame, ad esempio quello che contiene un mazzo virtuale di carte, è necessario sapere come manipolarlo. La funzione head() mostra le prime sei righe del data.frame:

head(deck)
#>    face   suit value
#> 1  king spades    13
#> 2 queen spades    12
#> 3  jack spades    11
#> 4   ten spades    10
#> 5  nine spades     9
#> 6 eight spades     8

Poniamoci ora il problema di mescolare il mazzo di carte e di estrarre alcune carte dal mazzo. Queste operazioni possono essere eseguite usando il sistema notazionale di R.

Il sistema di notazione di R consente di estrarre singoli elementi dagli oggetti definiti da R. Per estrarre un valore da un data.frame, per esempio, dobbiamo scrivere il nome del data.frame seguito da una coppia di parentesi quadre:

deck[, ]

All’interno delle parentesi quadre ci sono due indici separati da una virgola. R usa il primo indice per selezionare un sottoinsieme di righe del data.frame e il secondo indice per selezionare un sottoinsieme di colonne. L’indice è il numero d’ordine che etichetta progressivamente ognuno dei valori del vettore. Per esempio,

deck[9, 2]
#> [1] "spades"

restituisce l’elemento che si trova nella nella nona riga della seconda colonna di deck.

In R ci sono sei modi diversi per specificare gli indici di un oggetto: interi positivi, interi negativi, zero, spazi vuoti, valori logici e nomi. Esaminiamoli qui di seguito.

2.7.2 Interi positivi

Gli indici \(i, j\) possono essere degli interi positivi che identificano l’elemento nella \(i\)-esima riga e nella \(j\)-esima colonna del data.frame. Per l’esempio relativo al mazzo di carte, l’istruzione

deck[1, 1]
#> [1] "king"

ritorna il valore nella prima riga e nella prima colonna. Per estrarre più di un valore, usiamo un vettore di interi positivi. Per esempio, la prima riga di deck si trova con

deck[1, c(1:3)]
#>   face   suit value
#> 1 king spades    13

Tale sistema notazionale non si applica solo ai data.frame ma può essere usato anche per gli altri oggetti di R.

L’indice usato da R inizia da 1. In altri linguaggi di programmazione, per esempio C, inizia da 0.

2.7.3 Interi negativi

Gli interi negativi fanno l’esatto contrario degli interi positivi: R ritornerà tutti gli elementi tranne quelli specificati dagli interi negativi. Per esempio, la prima riga del data.frame può essere specificata nel modo seguente

deck[-(2:52), 1:3]
#>   face   suit value
#> 1 king spades    13

ovvero, escludendo tutte le righe seguenti.

2.7.4 Zero

Quando lo zero viene usato come indice, R non ritorna nulla dalla dimensione a cui lo zero si riferisce. L’istruzione

deck[0, 0]
#> data frame with 0 columns and 0 rows

ritorna un data.frame vuoto. Non molto utile.

2.7.5 Spazio

Uno spazio viene usato quale indice per comunicare a R di estrarre tutti i valori in quella dimensione. Questo è utile per estrarre intere colonne o intere righe da un data.frame. Per esempio, l’istruzione

deck[3, ]
#>   face   suit value
#> 3 jack spades    11

ritorna la terza riga del data.frame deck.

2.7.6 Valori booleani

Se viene fornito un vettore di stringhe TRUE, FALSE, R selezionerà gli elementi riga o colonna corrispondenti ai valori booleani TRUE usati quali indici. Per esempio, l’istruzione

deck[3, c(TRUE, TRUE, FALSE)]
#>   face   suit
#> 3 jack spades

ritorna i valori delle prime due colonne della terza riga di deck.

2.7.7 Nomi

È possibile selezionare gli elementi del data.frame usando i loro nomi. Per esempio,

deck[1, c("face", "suit", "value")]
#>   face   suit value
#> 1 king spades    13
deck[, "value"]
#>  [1] 13 12 11 10  9  8  7  6  5  4  3  2  1 13 12 11 10  9  8  7  6  5  4  3  2
#> [26]  1 13 12 11 10  9  8  7  6  5  4  3  2  1 13 12 11 10  9  8  7  6  5  4  3
#> [51]  2  1

References

Grolemund, Garrett. 2014. Hands-on Programming with R: Write Your Own Functions and Simulations. O’Reilly Media, Inc.