Qual è la principale differenza tra una matrice e un data frame?

La matrice è un oggetto atomico: tutti gli elementi devono avere la stessa modalità, e mescolando numeri e stringhe tutto viene convertito in character. Il data frame è invece un oggetto non atomico: internamente è una lista di vettori della stessa lunghezza (le colonne), ciascuno con la propria modalità. È per questo la struttura naturale per una matrice dei dati statistica, in cui le variabili possono essere di tipo diverso.

La seconda opzione inventa un limite che non esiste. La terza è la più insidiosa: anche una matrice può avere i nomi delle colonne (attributo dimnames), ma resta un oggetto atomico; la differenza sta nella struttura, non nei nomi. La quarta è del tutto errata: un data frame può contenere colonne di qualunque modalità.

  • False
  • True
  • False
  • False

Si considerino le seguenti istruzioni, in cui df è un data.frame e tb una tibble con lo stesso contenuto (prova le istruzioni in R prima di rispondere):

df <- data.frame(nome = c("Anna", "Luca", "Sara"), voto = c(28, 24, 30))
tb <- tibble::tibble(nome = c("Anna", "Luca", "Sara"), voto = c(28, 24, 30))
df[, 2]
tb[, 2]

Che cosa restituiscono le ultime due istruzioni?

Con un data.frame, estraendo una sola colonna con la notazione [riga, colonna] R "semplifica" il risultato e restituisce un vettore. Una tibble non semplifica mai: tb[, 2] restituisce ancora una tibble, con una sola colonna. Per ottenere il vettore da una tibble si usano tb[[2]], tb[["voto"]] oppure tb$voto.

La seconda opzione confonde il puntamento di una colonna con quello di un singolo elemento: lasciare vuoto l'indice di riga significa "tutte le righe". La terza è la più plausibile: tibble e data frame sono molto simili (una tibble è anche un data frame), ma differiscono proprio in comportamenti come questo. La quarta è errata: le colonne si possono indicare sia per posizione sia per nome.

  • False
  • False
  • True
  • False

Si eseguono le seguenti istruzioni:

l <- list(1:3, "a", TRUE)
class(l[2])
class(l[[2]])

Che cosa restituiscono le ultime due istruzioni, nell'ordine?

La singola parentesi quadra applicata a una lista restituisce una sotto-lista: l[2] è una lista con un solo elemento. La doppia parentesi quadra estrae invece l'elemento stesso: l[[2]] è il vettore di caratteri "a". Un'immagine utile: se la lista è un treno, l[2] è il secondo vagone (ancora attaccato alla struttura di treno), mentre l[[2]] è il contenuto del secondo vagone.

La seconda opzione inverte i due comportamenti. La terza è l'errore più frequente: le due notazioni sembrano equivalenti ma restituiscono oggetti di classe diversa. La quarta riporta le classi del primo e del terzo elemento della lista.

  • True
  • False
  • False
  • False

Si eseguono le seguenti istruzioni:

studente <- list(nome = "Anna", voti = c(28, 30, 27))
studente$voti[2]

Che cosa restituisce l'ultima istruzione?

L'operatore $ estrae dalla lista l'elemento con il nome indicato, cioè il vettore c(28, 30, 27); equivale a studente[["voti"]]. A questo vettore si applica poi [2], che ne estrae il secondo elemento: 30. Le due operazioni sono valutate in sequenza, da sinistra a destra.

La seconda opzione ignora l'indice [2]. La terza è la più insidiosa: voti è effettivamente il secondo elemento della lista, ma l'indice [2] è applicato al vettore estratto con $, non alla lista. La quarta confonde il contenuto dell'elemento con il suo nome.

  • True
  • False
  • False
  • False

Dato il data frame

df <- data.frame(nome = c("Anna", "Luca", "Sara"), voto = c(28, 24, 30))

quale delle seguenti istruzioni non restituisce il vettore numerico 28 24 30?

Un data frame è una lista di colonne, quindi valgono le stesse regole delle liste: df["voto"], con la singola parentesi quadra e un solo indice, restituisce un data frame con la sola colonna voto, non il vettore. Tutte le altre istruzioni restituiscono il vettore 28 24 30: $ e [[ ]] estraggono l'elemento (la colonna), mentre df[, "voto"], con la notazione a due indici, semplifica il risultato in un vettore perché si seleziona una sola colonna.

In questa domanda la risposta corretta è l'istruzione che si comporta diversamente dalle altre: le tre istruzioni che restituiscono il vettore sono i distrattori. Tra queste df[, "voto"] è la più insidiosa, perché usa anch'essa la singola parentesi quadra.

  • True
  • False
  • False
  • False

Si eseguono le seguenti istruzioni:

studente <- list(nome = "Anna", voti = c(28, 30))
studente$voti <- NULL
length(studente)

Che cosa restituisce l'ultima istruzione?

NULL rappresenta l'oggetto vuoto, l'assenza di qualunque oggetto. Assegnare NULL a un elemento di una lista (o a una colonna di un data frame) ha l'effetto di eliminarlo: la lista resta con il solo elemento nome e la sua lunghezza diventa 1.

La seconda opzione immagina che l'assegnazione aggiunga un elemento. La terza è il fraintendimento più naturale: ci si aspetta che l'elemento rimanga "vuoto", ma NULL non è un valore che possa essere contenuto: è l'assenza di oggetto, e l'elemento viene rimosso. La quarta confonde il divieto di usare una parola riservata come nome (NULL <- 1 dà errore) con la possibilità di usarla come valore.

  • False
  • False
  • False
  • True

Quale delle seguenti istruzioni rispetta le regole di stile del tidyverse style guide adottate nel corso?

Le regole principali: i nomi degli oggetti sono scritti in minuscolo con le parole separate da _ (snake case); per l'assegnazione si usa <-; si lascia uno spazio attorno agli operatori (<-, =, +, ...) e dopo ogni virgola, mentre non si mettono spazi subito dentro le parentesi.

La seconda opzione è codice funzionante, ma viola quasi tutte le regole: nome in CamelCase, = per l'assegnazione, nessuno spazio. La terza è la più insidiosa: il nome è corretto e gli spazi dopo le virgole ci sono, ma usa = per l'assegnazione e inserisce spazi dentro le parentesi. La quarta non è nemmeno codice valido: media voti contiene uno spazio e non è un nome ammesso.

  • True
  • False
  • False
  • False

In uno script R aperto in RStudio, quale delle seguenti righe crea una sezione che compare nel pannello di navigazione dello script (document outline)?

In uno script R tutto ciò che segue il simbolo # è un commento e non viene eseguito. Un commento che termina con almeno quattro trattini (----, ma valgono anche ==== o ####) viene riconosciuto da RStudio come etichetta di sezione: compare nel document outline e permette di navigare lo script. Si inserisce rapidamente con CTRL/CMD + SHIFT + R.

La seconda opzione usa la sintassi dei commenti di altri linguaggi (C, Java): in R // non è un commento e produce un errore. La terza è la più plausibile: è un commento valido, ma senza i trattini finali non viene riconosciuto come sezione (il doppio # richiama i titoli di Markdown e Quarto, non degli script R). La quarta chiama una funzione che non esiste.

  • False
  • False
  • True
  • False

Che cosa restituiscono, nell'ordine, le seguenti istruzioni?

length(c(1, NULL, 3))
length(c(1, NA, 3))

NA è un valore (mancante): occupa una posizione nel vettore, che quindi ha lunghezza 3. NULL invece è l'oggetto vuoto, ha lunghezza 0: combinandolo con c() non aggiunge nulla, e il vettore risultante 1 3 ha lunghezza 2.

La seconda opzione inverte i due comportamenti. La terza è la più insidiosa: tratta NULL come un valore mancante al pari di NA, mentre la differenza tra "valore che manca" e "oggetto che non c'è" è proprio il punto della domanda. La quarta riporta un risultato senza alcun fondamento.

  • True
  • False
  • False
  • False

Che cosa restituisce la seguente istruzione?

c(1/0, 0/0, -1/0)

R segue le regole dell'aritmetica in virgola mobile: dividere un numero positivo per zero dà Inf (infinito), un numero negativo dà -Inf, mentre 0/0 è una forma indeterminata e restituisce NaN (Not a Number). Nessuna delle tre operazioni produce un errore.

La seconda opzione non ha fondamento matematico. La terza è la più insidiosa: tratta anche 0/0 come infinito, ignorando che si tratta di una forma indeterminata. La quarta applica a R il comportamento di una calcolatrice o di altri linguaggi che interrompono il calcolo.

  • True
  • False
  • False
  • False

Che cosa restituisce la seguente istruzione?

is.na(c(1, NA, NaN))

is.na() verifica, elemento per elemento, se il valore è mancante e restituisce un vettore logico della stessa lunghezza. In R anche NaN viene considerato un valore mancante, quindi is.na() restituisce TRUE sia per NA sia per NaN. Il viceversa non vale: is.nan() restituisce TRUE solo per NaN.

La seconda opzione conta i valori mancanti (cosa che si otterrebbe con sum(is.na(...)), e il risultato sarebbe comunque 2). La terza è la più plausibile: NaN e NA sono valori riservati diversi, ma is.na() li considera entrambi mancanti. La quarta risponde se il vettore "contiene" valori mancanti, non quali elementi lo siano.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

mean(c(2, NA, 4))

Per default, un valore mancante si propaga nei calcoli: se uno dei valori non è noto, non è nota neppure la media, e R restituisce NA. Per calcolare la media dei soli valori disponibili si usa l'argomento na.rm (NA remove): mean(c(2, NA, 4), na.rm = TRUE) restituisce 3.

La seconda opzione, (2 + 0 + 4) / 3, tratta il dato mancante come uno zero: un errore concettuale grave in statistica. La terza è la più plausibile, perché è il risultato che si ottiene con na.rm = TRUE, ma non è il comportamento di default. La quarta è errata: la funzione restituisce NA, non un errore.

  • False
  • True
  • False
  • False

Si vuole verificare quali elementi del vettore x <- c(3, NA) sono mancanti. Che cosa restituisce l'istruzione x == NA?

NA significa "valore non noto". Chiedersi se 3 sia uguale a un valore non noto ha come risposta "non si sa", cioè NA; lo stesso vale per il secondo confronto: due valori non noti non si possono dire uguali, quindi anche NA == NA restituisce NA. Per individuare i valori mancanti si usa la funzione is.na(), che restituisce FALSE TRUE.

La seconda opzione restituisce un singolo valore, ma il confronto è vettoriale e produce un risultato per ogni elemento. La terza è l'errore più frequente: è esattamente il risultato desiderato, ma si ottiene con is.na(x), non con ==. La quarta è errata: il confronto è lecito e non produce errori.

  • False
  • True
  • False
  • False

Quale istruzione salva soltanto gli oggetti x e y nel file dati.RData?

save() salva gli oggetti elencati nel file indicato dall'argomento file; save.image() salva invece l'intero workspace, mentre load() serve a ricaricare in memoria gli oggetti contenuti in un file .RData.

La seconda opzione usa la funzione di caricamento al posto di quella di salvataggio. La terza è la più insidiosa ed è un esempio di passaggio degli argomenti: gli oggetti da salvare sono raccolti dall'argomento ..., che accetta un numero qualunque di valori, per cui la stringa "dati.RData", passata senza nome, viene interpretata come il nome di un terzo oggetto da salvare; R restituisce l'errore object 'dati.RData' not found. Dopo ... gli argomenti vanno sempre passati per nome. La quarta non ha relazione con il salvataggio di oggetti R.

  • True
  • False
  • False
  • False

Che cosa restituisce la seguente istruzione?

x <- c(2, 5, 8)
x > 3 & x < 7

Gli operatori relazionali (>, <) e l'operatore logico & (and) agiscono elemento per elemento. x > 3 dà FALSE TRUE TRUE, x < 7 dà TRUE TRUE FALSE; combinandoli con &, il risultato è TRUE solo dove entrambe le condizioni sono vere: FALSE TRUE FALSE.

La seconda opzione restituisce il valore che soddisfa la condizione: si otterrebbe con x[x > 3 & x < 7], cioè usando il vettore logico per il puntamento. La terza è il risultato di x > 3 | x < 1, cioè confonde and (&) con or (|), oppure considera la sola prima condizione. La quarta tratta il confronto come se restituisse un unico valore per l'intero vettore.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

sum(c(3, 8, 1, 9) > 5)

c(3, 8, 1, 9) > 5 produce il vettore logico FALSE TRUE FALSE TRUE. Quando un valore logico è usato in un'operazione aritmetica, R lo converte in numero: TRUE diventa 1 e FALSE diventa 0. La somma conta quindi quanti elementi soddisfano la condizione: 2. Allo stesso modo, mean() applicata a un vettore logico restituisce la proporzione di TRUE.

La seconda opzione ignora il confronto. La terza è la più insidiosa: è la somma degli elementi maggiori di 5, che si ottiene con sum(x[x > 5]), cioè usando il vettore logico per il puntamento e non per la somma. La quarta è errata proprio a causa della conversione automatica dei valori logici in numeri.

  • False
  • False
  • True
  • False

Che cosa restituisce la seguente istruzione?

c(17 %/% 5, 17 %% 5)

%/% è l'operatore di divisione intera: restituisce la parte intera del quoziente, 17 %/% 5 è 3. %% è l'operatore modulo: restituisce il resto della divisione intera, 17 %% 5 è 2 (infatti 17 = 3 × 5 + 2). L'operatore %% è utile ad esempio per verificare se un numero è pari: x %% 2 == 0.

La seconda opzione tratta entrambi gli operatori come la divisione ordinaria 17 / 5. La terza è la più insidiosa: i valori sono quelli giusti, ma attribuiti agli operatori sbagliati. La quarta interpreta gli operatori come prodotto e somma.

  • False
  • True
  • False
  • False

Che cosa restituisce la seguente istruzione?

v <- c(4, 10, 6, 12)
v[v > mean(v)]

La media di v è 8. L'espressione v > mean(v) produce il vettore logico FALSE TRUE FALSE TRUE; usato tra parentesi quadre, questo vettore seleziona gli elementi di v in corrispondenza dei TRUE, cioè 10 e 12.

La seconda opzione restituisce la media stessa. La terza è la più plausibile: è il risultato del solo confronto v > mean(v), prima che venga usato per il puntamento. La quarta restituisce le posizioni degli elementi che soddisfano la condizione, che si otterrebbero con which(v > mean(v)), non i loro valori.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

v <- c(4, 10, 6, 12)
v[c(TRUE, FALSE)]

Quando il vettore logico usato per il puntamento è più corto del vettore da indicizzare, R lo ricicla: c(TRUE, FALSE) diventa c(TRUE, FALSE, TRUE, FALSE). Vengono quindi selezionati il primo e il terzo elemento, cioè gli elementi in posizione dispari: 4 6.

La seconda opzione tratta il vettore logico come se indicasse un numero di elementi. La terza è la più insidiosa: è il risultato che si avrebbe se R non applicasse la regola del riciclo, cioè con v[c(TRUE, FALSE, FALSE, FALSE)]. La quarta è errata: R non segnala nemmeno un avvertimento in questo caso.

  • False
  • False
  • False
  • True