Il file dati.csv è stato esportato da un foglio elettronico in italiano: le colonne sono separate dal punto e virgola e i numeri decimali usano la virgola (ad esempio 1500,50). Quale delle seguenti istruzioni lo importa correttamente?

read_delim del package readr permette di indicare il separatore delle colonne (delim) e, attraverso l'argomento locale, il separatore decimale. Lo stesso risultato si ottiene con le funzioni pensate per i CSV "all'italiana": read_csv2 di readr oppure read.csv2 di base.

read_excel serve per i file in formato Excel (.xls, .xlsx), non per i file di testo. read.csv è la più insidiosa: è una funzione di importazione per file CSV, ma per default usa la virgola come separatore delle colonne e il punto come separatore decimale, per cui l'intero contenuto di ogni riga finirebbe in un'unica colonna. La quarta confonde l'importazione di un file con l'installazione di un package.

  • True
  • False
  • False
  • False

Il file t.csv contiene le righe seguenti:

nome;eta;reddito
Anna;23;1500,50
Luca;25;1200,00

Che cosa si ottiene con l'istruzione read.table("t.csv", sep = ";")?

In read.table l'argomento header vale FALSE per default: la prima riga del file viene trattata come una riga di dati e le colonne ricevono i nomi V1, V2, V3. Poiché ogni colonna contiene anche il testo dell'intestazione, tutte le colonne sono di tipo character. Per un risultato corretto servono header = TRUE e dec = "," (oppure si usa read.csv2).

La seconda opzione è errata: read.table legge qualunque file di testo delimitato, indipendentemente dall'estensione. La terza è la più insidiosa: è il risultato che si otterrebbe specificando header = TRUE e dec = ",", ma non con i valori di default. La quarta non ha fondamento: read.table restituisce sempre un data frame.

  • False
  • False
  • True
  • False

Il file n.csv ha come intestazione la riga Anno di nascita;Voto (su 30);Codice Fiscale. Quali nomi delle colonne si ottengono con names(read.csv2("n.csv"))?

Per default le funzioni di importazione di base (read.table, read.csv, read.csv2) usano check.names = TRUE: i nomi delle colonne vengono trasformati in nomi validi sostituendo con un punto ogni carattere non ammesso, come spazi e parentesi.

"V1" "V2" "V3" sono i nomi assegnati quando la prima riga non viene letta come intestazione, ma read.csv2 usa header = TRUE per default. La terza opzione è il risultato che si ottiene con le funzioni di readr (ad esempio read_csv2), che conservano i nomi originali anche se non validi. La quarta è il risultato di clean_names del package janitor, non di read.csv2.

  • False
  • False
  • True
  • False

Il file t.csv contiene le righe seguenti:

nome;eta;reddito
Anna;23;1500,50
Luca;25;1200,00

Il file viene importato con l'istruzione seguente:

read_delim("t.csv", delim = ";")$reddito

Che cosa si ottiene?

Con il locale di default readr usa il punto come separatore decimale e la virgola come separatore delle migliaia. I valori 1500,50 e 1200,00 vengono interpretati come numeri in cui la virgola separa le migliaia, e diventano 150050 e 120000. R non segnala nulla: il messaggio Column specification indica soltanto che la colonna è stata letta come numero. È un errore silenzioso, che si evita indicando locale = locale(decimal_mark = ",") oppure usando read_csv2.

La seconda opzione descrive un comportamento ragionevole, che si verifica quando almeno un valore non è interpretabile come numero, ma non è il caso di questi valori. La terza è il risultato corretto che si otterrebbe specificando il separatore decimale. La quarta è errata: proprio l'assenza di un errore rende questo comportamento pericoloso.

  • False
  • False
  • False
  • True

Qual è la differenza tra gli oggetti restituiti da read.csv2("t.csv") e da read_csv2("t.csv")?

Le funzioni di readr restituiscono una tibble: class() riporta "spec_tbl_df" "tbl_df" "tbl" "data.frame", a indicare che la tibble è un data frame con alcuni comportamenti diversi (stampa più compatta, nessuna modifica dei nomi delle colonne, nessuna semplificazione con [ , ]). Le funzioni di base restituiscono un semplice data.frame.

La seconda opzione è errata: nessuna delle due restituisce una matrice. La terza è la più insidiosa: le due funzioni hanno nomi quasi identici e argomenti di default simili (; come separatore e , come decimale), ma appartengono a package diversi e producono oggetti di classe diversa. La quarta confonde la lettura con la scrittura, che si fa con funzioni come write_csv2.

  • True
  • False
  • False
  • False

Quale funzione del package readxl restituisce i nomi dei fogli contenuti in un file Excel?

excel_sheets() restituisce un vettore di stringhe con i nomi dei fogli del file. Il foglio da importare si indica poi nell'argomento sheet di read_excel, per nome (sheet = "Esami") o per posizione (sheet = 2).

read_csv è pensata per i file di testo delimitati e non legge il formato Excel. La terza opzione è la più insidiosa: read_excel importa un solo foglio alla volta (per default il primo) e restituisce una tibble, non l'elenco dei fogli. La quarta richiama una funzione che non esiste.

  • False
  • False
  • True
  • False

Nel foglio Esami del file esami.xlsx la prima riga contiene un titolo, la seconda è vuota e l'intestazione delle colonne si trova nella terza riga. Quale istruzione importa correttamente i dati?

L'argomento skip indica quante righe saltare prima di iniziare la lettura: saltando le prime due, la terza riga viene letta come intestazione. Senza skip, il titolo diventerebbe il nome della prima colonna e tutte le colonne sarebbero di tipo character.

Con col_names = FALSE la lettura parte comunque dalla prima riga e il titolo e l'intestazione vengono trattati come dati. La terza opzione è la più insidiosa: saltando tre righe si salta anche l'intestazione, per cui la prima riga di dati verrebbe usata come nomi delle colonne. La quarta legge al massimo due righe di dati, senza risolvere il problema.

  • False
  • False
  • False
  • True

Una tibble ha le colonne Anno di nascita, Voto (su 30), CodiceFiscale e % Presenze. Quali nomi si ottengono dopo l'applicazione della funzione clean_names() del package janitor?

clean_names() trasforma i nomi in snake case: lettere minuscole, parole separate da _, nessuno spazio né carattere speciale. Le parentesi vengono eliminate, le parole unite in CamelCase vengono separate (CodiceFiscale diventa codice_fiscale) e alcuni simboli vengono tradotti in parole (% diventa percent).

La seconda opzione corrisponde alla trasformazione fatta da make.names(), cioè da check.names = TRUE nelle funzioni di importazione di base. La terza è la più insidiosa: applica alcune regole (minuscole, _) ma non le altre, mentre le parentesi non sono ammesse in un nome valido e la separazione del CamelCase è automatica. La quarta descrive i nomi di default di read.table senza intestazione.

  • False
  • False
  • True
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Quante righe ha il risultato di inner_join(studenti, esami, by = "id")?

inner_join conserva solo le righe con corrispondenza in entrambe le tabelle. Anna (id 1) ha due esami e compare due volte, Luca (id 2) ne ha uno, mentre Sara (id 3) e l'esame con id 4 non hanno corrispondenza e vengono esclusi: 2 + 1 = 3 righe.

7 è la somma delle righe delle due tabelle, come se il join le accodasse. 2 è la risposta più insidiosa: è il numero di studenti con corrispondenza, ma il join produce una riga per ogni coppia studente-esame, e Anna ha due esami. 4 è il numero di righe di esami, cioè di left_join(esami, studenti).

  • False
  • True
  • False
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Quante righe ha il risultato di left_join(studenti, esami, by = "id"), e cosa contiene la riga di Sara?

left_join conserva tutte le righe della prima tabella (studenti) e vi aggiunge le colonne della seconda. Anna ha due esami e compare due volte, Luca una volta, Sara non ha esami e compare una volta con voto pari a NA: 4 righe in totale. L'esame con id 4 viene escluso perché non corrisponde a nessuno studente.

La seconda opzione descrive inner_join. La terza è la più insidiosa: left_join conserva tutte le righe della prima tabella, ma non ne conserva il numero quando la relazione è "uno a molti", perché ogni studente viene ripetuto per ciascun esame. La quarta confonde il join con l'accodamento delle righe (union_all o bind_rows).

  • False
  • False
  • True
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Quante righe ha il risultato di full_join(studenti, esami, by = "id")?

full_join conserva tutte le righe di entrambe le tabelle: le 3 righe con corrispondenza (due per Anna e una per Luca), la riga di Sara senza esami (con voto pari a NA) e la riga dell'esame con id 4 senza studente (con nome pari a NA): 3 + 1 + 1 = 5.

4 è il numero di righe di left_join (o di right_join): si dimentica uno dei due gruppi di righe senza corrispondenza. 3 è il numero di righe di inner_join. 12 è il prodotto del numero di righe delle due tabelle, cioè il risultato di un cross_join, che abbina ogni riga della prima tabella a ogni riga della seconda.

  • False
  • False
  • True
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Quale delle seguenti istruzioni produce le stesse righe di left_join(studenti, esami, by = "id"), a meno dell'ordine delle colonne?

right_join(x, y) conserva tutte le righe di y, cioè della seconda tabella. Scambiando l'ordine delle tabelle, right_join(esami, studenti) conserva tutte le righe di studenti, esattamente come left_join(studenti, esami). Cambia solo l'ordine delle colonne: prima quelle di esami, poi quelle di studenti.

inner_join esclude Sara, che non ha esami. La terza è la più insidiosa: lascia le tabelle nello stesso ordine e conserva quindi tutte le righe di esami, includendo l'esame con id 4 ed escludendo Sara. La quarta è una chiamata incompleta, perché manca la seconda tabella.

  • False
  • True
  • False
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Che differenza c'è tra semi_join(studenti, esami, by = "id") e inner_join(studenti, esami, by = "id")?

semi_join è un filtering join: filtra le righe della prima tabella tenendo quelle che hanno almeno una corrispondenza nella seconda, senza aggiungere colonne e senza duplicare righe. Anna e Luca compaiono una sola volta ciascuno: 2 righe. inner_join è un mutating join: aggiunge le colonne di esami e ripete Anna per ciascuno dei suoi due esami: 3 righe.

La seconda opzione nega una differenza che c'è. La terza è la più insidiosa: è corretto che semi_join non aggiunga colonne, ma non duplica nemmeno le righe. La quarta descrive anti_join.

  • False
  • False
  • True
  • False

Si considerino le due tibble seguenti:

studenti <- tibble(id = c(1, 2, 3), nome = c("Anna", "Luca", "Sara"))
esami    <- tibble(id = c(1, 1, 2, 4), voto = c(28, 30, 24, 27))

Che cosa restituisce l'istruzione anti_join(studenti, esami, by = "id")?

anti_join(x, y) restituisce le righe della prima tabella che non hanno corrispondenza nella seconda: lo studente con id 3, Sara. È utile per individuare dati mancanti o incoerenti, come gli iscritti che non hanno ancora sostenuto esami.

La seconda opzione descrive semi_join. La terza è la più insidiosa: anti_join non è simmetrico e considera solo le righe della prima tabella; l'esame con id 4 si individua con anti_join(esami, studenti, by = "id"). La quarta non ha fondamento.

  • False
  • False
  • False
  • True

Nella tabella esami la matricola si trova nella colonna matr, nella tabella anagrafica nella colonna matricola. Quale istruzione unisce correttamente le due tabelle?

Quando le colonne chiave hanno nomi diversi, la corrispondenza si indica con join_by(): a sinistra di == la colonna della prima tabella, a destra quella della seconda. Una sintassi equivalente è by = c("matr" = "matricola"), cioè un vettore con nomi.

Senza by, il join usa le colonne con lo stesso nome nelle due tabelle; qui non ce ne sono e R restituisce l'errore `by` must be supplied when `x` and `y` have no common variables. La terza è la più insidiosa: un vettore senza nomi chiede di usare come chiavi due colonne, matr e matricola, che dovrebbero esistere entrambe in entrambe le tabelle. La quarta passa due vettori al posto di due tabelle.

  • False
  • False
  • True
  • False

Le tibble lab_r e lab_python hanno entrambe le colonne matricola, cognome e nome. Che cosa accade eseguendo inner_join(lab_r, lab_python) senza specificare l'argomento by?

Se by non è specificato, dplyr esegue un cosiddetto natural join, usando come chiave tutte le colonne presenti con lo stesso nome in entrambe le tabelle, e stampa un messaggio con la chiave utilizzata. Due righe vengono abbinate solo se coincidono in tutte e tre le colonne: basta un errore di battitura nel nome per perdere la corrispondenza. Per questo è buona pratica indicare sempre la chiave in modo esplicito.

L'errore si ha solo quando le tabelle non hanno colonne in comune. La terza è la più insidiosa: matricola sarebbe la chiave più sensata, ma R non può saperlo e usa tutte le colonne comuni. La quarta descrive union_all, non un join.

  • False
  • False
  • True
  • False

Le tibble lab_r e lab_python hanno entrambe le colonne matricola, cognome e nome. Quali sono i nomi delle colonne del risultato di inner_join(lab_r, lab_python, by = "matricola")?

Le colonne con lo stesso nome che non sono usate come chiave compaiono in entrambe le tabelle: per distinguerle, dplyr aggiunge per default il suffisso .x a quelle della prima tabella e .y a quelle della seconda. I suffissi si possono scegliere con l'argomento suffix, ad esempio suffix = c("_r", "_python").

La seconda opzione è il risultato del join su tutte e tre le colonne. La terza è la più insidiosa: una tabella non può avere due colonne con lo stesso nome, ed è proprio per questo che servono i suffissi. La quarta applica i suffissi alla chiave, che invece compare una sola volta.

  • False
  • False
  • False
  • True

Si considerino le tibble:

x <- tibble(id = 1:2, nome = c("Nicolò", "Luca"))
y <- tibble(id = 1:2, nome = c("Nicolo", "Luca"))

Quante righe ha il risultato di intersect(x, y)?

Le operazioni su insiemi di dplyr confrontano le righe intere: due righe sono considerate uguali solo se coincidono in tutte le colonne. La riga con id 2 è identica nelle due tabelle, mentre quella con id 1 differisce per l'accento sul nome: il risultato contiene solo la riga di Luca.

0 trascura che la riga di Luca è identica. 2 è la risposta più insidiosa: è il risultato che si otterrebbe confrontando solo la colonna id, ad esempio con semi_join(x, y, by = "id"). 4 è la somma delle righe delle due tabelle, cioè union_all.

  • False
  • False
  • True
  • False

Le tibble a e b hanno le stesse colonne; a ha 12 righe, b ne ha 9, e 3 righe sono presenti (identiche) in entrambe. Quante righe hanno, nell'ordine, union(a, b) e union_all(a, b)?

union restituisce le righe presenti in almeno una delle due tabelle, senza duplicati: 12 + 9 − 3 = 18. union_all accoda semplicemente le righe della seconda tabella a quelle della prima, conservando i duplicati: 12 + 9 = 21.

La seconda opzione inverte i due risultati. La terza è la più insidiosa: trascura che union, come l'unione insiemistica, conta una sola volta gli elementi comuni. La quarta attribuisce a union il risultato dell'intersezione.

  • False
  • False
  • False
  • True

Si considerino le tibble a <- tibble(n = c("A", "B", "C")) e b <- tibble(n = c("B", "C", "D", "E")). Che cosa restituisce setdiff(b, a)?

setdiff(x, y) restituisce le righe di x che non compaiono in y. Con b come prima tabella si ottengono le righe di b assenti in a, cioè D ed E. L'operazione non è simmetrica: setdiff(a, b) restituirebbe invece la sola riga A.

La seconda opzione è il risultato di setdiff(a, b), cioè con le tabelle in ordine inverso. La terza è la più insidiosa: contiene le righe presenti in una sola delle due tabelle, ed è il risultato di symdiff(a, b). La quarta è l'intersezione.

  • False
  • False
  • False
  • True

Le tibble lab_r e lab_python contengono gli iscritti a due laboratori, con le stesse colonne. Quale operazione restituisce gli studenti iscritti a uno solo dei due laboratori?

symdiff (differenza simmetrica) restituisce le righe presenti in una sola delle due tabelle, cioè in lab_r ma non in lab_python oppure in lab_python ma non in lab_r. Il numero di righe del risultato è pari a quello di union meno quello di intersect.

union_all accoda le righe delle due tabelle, conservando anche i duplicati. La terza è la più insidiosa: setdiff restituisce solo gli iscritti al laboratorio di R che non frequentano quello di Python, e trascura chi è iscritto soltanto a Python. La quarta restituisce l'esatto contrario, cioè gli iscritti a entrambi i laboratori.

  • False
  • False
  • True
  • False

Si considerino le istruzioni:

a <- tibble(n = c("A", "B", "C"))
setequal(a, arrange(a, desc(n)))
identical(a, arrange(a, desc(n)))

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

arrange(a, desc(n)) contiene le stesse righe di a in ordine inverso. setequal verifica se due tabelle contengono le stesse righe, indipendentemente dall'ordine: restituisce TRUE. identical verifica che i due oggetti siano esattamente uguali, ordine compreso: restituisce FALSE.

La seconda opzione inverte i due comportamenti. La terza è la più insidiosa: le due tabelle sono uguali come insiemi di righe, ma non come oggetti. La quarta è errata: il risultato di una funzione può sempre essere passato come argomento a un'altra.

  • True
  • False
  • False
  • False

Che cosa restituisce la seguente istruzione?

levels(factor(c("medio", "alto", "basso", "alto")))

Per default factor() usa come livelli i valori distinti del vettore in ordine alfabetico. Per ottenere un ordine diverso, ad esempio quello naturale "basso" "medio" "alto", bisogna indicarlo esplicitamente con l'argomento levels.

La seconda opzione riporta i valori del vettore, non i livelli: i livelli sono i valori distinti. La terza è la più insidiosa: è l'ordine "naturale" che un lettore si aspetta, ma R non può conoscerlo e usa l'ordine alfabetico. La quarta è il numero di livelli, che si ottiene con nlevels().

  • False
  • True
  • False
  • False

Che cosa restituisce la seguente istruzione?

factor(c("medio", "alto", "Basso"), levels = c("basso", "medio", "alto"))

Quando si specifica l'argomento levels, i valori che non corrispondono esattamente a nessuno dei livelli indicati diventano NA, senza alcun errore né avvertimento. Poiché R distingue tra maiuscole e minuscole, "Basso" non corrisponde al livello "basso".

La seconda opzione immagina che R aggiunga automaticamente i valori mancanti ai livelli. La terza è la più insidiosa: suppone che R ignori la differenza tra maiuscole e minuscole e corregga il valore. La quarta è errata: la conversione avviene in silenzio, ed è proprio per questo che conviene controllare il numero di NA dopo aver creato un factor.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

factor(c("F", "M", "F"), levels = c("F", "M"), labels = c("Femmina", "Maschio"))

L'argomento levels indica quali valori sono presenti nei dati e in quale ordine; labels indica le etichette con cui quei livelli verranno mostrati, nello stesso ordine. Il risultato è un factor con i valori Femmina Maschio Femmina e i livelli Femmina e Maschio: i codici originali F e M non sono più visibili.

La seconda opzione combina valori e livelli in modo incoerente: i valori di un factor sono sempre etichette dei suoi livelli. La terza è la più insidiosa: le etichette sostituiscono i livelli e non vengono conservate a parte. La quarta riporta solo i livelli, non i valori del vettore, che ha lunghezza 3.

  • False
  • True
  • False
  • False

Che cosa restituisce l'ultima delle seguenti istruzioni?

o <- factor(c("basso", "alto", "medio"),
            levels = c("basso", "medio", "alto"),
            ordered = TRUE)
o > "medio"

In un ordered factor i livelli hanno un ordine (basso < medio < alto) e gli operatori relazionali confrontano le posizioni dei livelli. Solo "alto" segue "medio", quindi il risultato è FALSE TRUE FALSE.

La seconda opzione è il risultato del confronto tra stringhe in ordine alfabetico, cioè di as.character(o) > "medio": né "basso" né "alto" seguono "medio" nell'alfabeto. La terza è la più insidiosa: è ciò che accade con un factor non ordinato (creato senza ordered = TRUE), per il quale il confronto non ha significato. La quarta restituisce l'elemento che soddisfa la condizione, che si otterrebbe con o[o > "medio"].

  • False
  • True
  • False
  • False

Il data frame df ha una colonna genere di tipo character. Si esegue l'istruzione seguente, senza alcuna assegnazione:

mutate(df, genere = factor(genere))

Che cosa restituisce poi class(df$genere)?

mutate restituisce una nuova tabella con la colonna modificata, senza alterare l'oggetto di partenza: il risultato viene stampato in console e poi perso. Per rendere permanente la conversione bisogna assegnare il risultato, ad esempio df <- mutate(df, genere = factor(genere)), che equivale a df$genere <- factor(df$genere).

La seconda opzione confonde la classe della colonna con quella della tabella. La terza è l'errore più frequente: in R le funzioni non modificano gli oggetti ricevuti come argomento, e anche le funzioni di dplyr seguono questa regola. La quarta è priva di fondamento: mutate sostituisce la colonna con lo stesso nome, non la elimina.

  • False
  • False
  • True
  • False

Che cosa restituisce la seguente istruzione?

df <- tibble(prezzo = c(10, 4), quantita = c(3, 5))
mutate(df, totale = prezzo * quantita, iva = totale * 0.22)

All'interno di mutate le colonne della tabella si indicano direttamente con il loro nome. Le operazioni sono vettoriali, cioè eseguite riga per riga: totale vale 10 × 3 = 30 e 4 × 5 = 20. Le nuove colonne vengono create nell'ordine in cui sono scritte, per cui iva può già usare totale.

La seconda opzione è errata: df$prezzo funzionerebbe, ma non è necessario, perché mutate cerca i nomi tra le colonne della tabella. La terza è la più insidiosa: le colonne create da mutate sono subito disponibili per le espressioni successive nella stessa chiamata. La quarta confonde il prodotto riga per riga con un prodotto scalare.

  • True
  • False
  • False
  • False

Si aggiunge a una tabella la colonna log_reddito = log(reddito) all'interno di mutate(). La colonna reddito contiene, tra gli altri, i valori 1, 0 e -1. Quali valori assume log_reddito in corrispondenza di questi tre valori?

log(1) vale 0. Il logaritmo di 0 tende a meno infinito e R restituisce -Inf. Il logaritmo di un numero negativo non è definito nei reali e R restituisce NaN, con un avvertimento. Prima di applicare una trasformazione logaritmica conviene quindi verificare il campo di variazione della variabile: valori nulli o negativi producono -Inf o NaN, che si propagano poi in calcoli come la media.

La seconda opzione immagina che R lasci invariati i valori problematici. La terza è la più insidiosa: -Inf e NaN sono valori riservati diversi da NA (anche se is.na() restituisce TRUE per NaN). La quarta è errata: il calcolo viene comunque eseguito.

  • False
  • True
  • False
  • False

Che cosa restituisce la seguente istruzione?

if_else(c(30, 25) > 28, "alto", 0)

if_else di dplyr è "stretta" sui tipi: i valori per il caso vero (true) e per il caso falso (false) devono avere lo stesso tipo, e qui sono character e double. R restituisce l'errore Can't combine `true` <character> and `false` <double>. Il controllo serve a evitare conversioni silenziose: per un risultato di tipo carattere bisogna scrivere "0".

La seconda opzione restituisce il risultato della sola condizione. La terza è la più insidiosa: è il comportamento della funzione ifelse di base, che converte silenziosamente il numero in stringa. La quarta restituisce un solo valore, mentre if_else restituisce un valore per ogni elemento della condizione.

  • False
  • False
  • True
  • False

Che cosa restituisce la seguente istruzione?

if_else(c(5, NA, 1) > 3, "alto", "basso")

Il confronto NA > 3 restituisce NA: per quell'elemento non si sa se la condizione sia vera o falsa, e if_else restituisce NA. Per assegnare un valore specifico ai casi con condizione mancante si usa l'argomento missing, ad esempio missing = "n.d.".

La seconda opzione restituisce un solo valore. La terza è la più insidiosa: tratta il valore mancante come se la condizione fosse falsa, ma per R una condizione NA non è né vera né falsa. La quarta è il risultato che si otterrebbe con missing = "n.d.", argomento che qui non è stato specificato.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

v <- c(30, 25, 18)
case_when(
  v >= 18 ~ "sufficiente",
  v >= 26 ~ "buono",
  v >= 29 ~ "ottimo"
)

case_when valuta le condizioni nell'ordine in cui sono scritte e, per ogni elemento, usa la prima condizione vera. Tutti e tre i voti soddisfano già la prima condizione (v >= 18), quindi le successive non vengono mai applicate. Le condizioni vanno scritte dalla più restrittiva alla meno restrittiva: prima v >= 29, poi v >= 26, infine v >= 18.

La seconda opzione è il risultato corretto con le condizioni nell'ordine giusto: 25 è minore di 26 e quindi "sufficiente". La terza è la più insidiosa: corrisponde a ciò che si "intende" scrivendo le condizioni, ma ignora la regola della prima condizione vera e attribuisce anche a 25 il giudizio "buono". La quarta associa le etichette alle posizioni.

  • True
  • False
  • False
  • False

Che cosa restituisce la seguente istruzione?

case_when(c(30, 15) >= 18 ~ "superato")

Agli elementi che non soddisfano nessuna condizione case_when assegna NA. Per assegnare un valore a tutti i casi rimanenti si usa l'argomento .default, ad esempio .default = "non superato".

La seconda opzione restituisce un solo valore, mentre case_when restituisce un valore per ogni elemento. La terza è la più insidiosa: è il risultato con .default = "non superato", ma R non può indovinare l'etichetta da assegnare. La quarta è errata: non è necessario coprire tutti i casi.

  • False
  • False
  • False
  • True

Si considerino le istruzioni:

s <- c("TP", "PT", "XX")
recode_values(s, "TP" ~ "Tempo pieno", "PT" ~ "Part-time")
replace_values(s, "TP" ~ "Tempo pieno", "PT" ~ "Part-time")

In che cosa differiscono i due risultati?

recode_values costruisce un vettore nuovo a partire dalle regole indicate: i valori non previsti diventano NA, a meno di specificare l'argomento default. replace_values sostituisce solo i valori indicati e lascia invariati tutti gli altri. Si usa quindi recode_values per ricodificare completamente una variabile e replace_values per correggere alcuni valori, ad esempio un errore di battitura.

La seconda opzione è errata: nessuna delle due modifica s; per conservare il risultato bisogna assegnarlo. La terza è la più insidiosa: per i valori previsti dalle regole le due funzioni producono lo stesso risultato, e la differenza emerge solo per i valori non previsti. La quarta è errata: entrambe restituiscono un vettore di caratteri.

  • False
  • True
  • False
  • False

Che cosa restituisce la seguente istruzione?

cut(c(0, 5, 10), breaks = c(0, 5, 10))

Per default cut crea intervalli chiusi a destra e aperti a sinistra (right = TRUE): (0,5] e (5,10]. Il valore 0 coincide con l'estremo sinistro del primo intervallo, che è escluso, e diventa quindi NA, senza alcun avvertimento. Per includerlo si usa include.lowest = TRUE, che produce [0,5] [0,5] (5,10].

La seconda opzione è il risultato con right = FALSE (intervalli chiusi a sinistra), in cui a restare escluso è il valore 10. La terza è la più insidiosa: è il risultato con include.lowest = TRUE, ma non con i valori di default. La quarta restituisce i valori originali, ignorando la classificazione.

  • False
  • False
  • True
  • False

Il vettore z <- c(1, 2, 3, 4, 5, 6, 7, 8, 100) deve essere suddiviso in 3 classi contenenti lo stesso numero di osservazioni. Quale funzione del package ggplot2 è adatta allo scopo?

cut_number costruisce n classi che contengono (approssimativamente) lo stesso numero di osservazioni, usando come estremi i quantili: qui 3 osservazioni per classe. È utile con variabili asimmetriche o con valori anomali.

cut_width costruisce classi di ampiezza fissa, 3 in questo caso, quindi molte classi quasi tutte vuote. La terza è la più insidiosa: cut_interval costruisce n classi della stessa ampiezza, non con lo stesso numero di osservazioni; a causa del valore 100 restituisce classi con 8, 0 e 1 osservazioni. La quarta usa una funzione che ordina le righe di una tabella e non accetta un vettore.

  • False
  • False
  • False
  • True

La tibble t3 ha le colonne a, b, c e d, in quest'ordine. Quale ordine delle colonne si ottiene con relocate(t3, d, .after = a)?

relocate sposta le colonne indicate senza eliminare le altre: con .after = a la colonna d viene collocata subito dopo a, e le altre colonne mantengono il loro ordine relativo.

La seconda opzione è il risultato di relocate(t3, d), senza .after: per default le colonne indicate vengono spostate all'inizio. La terza è la più insidiosa, perché suppone che l'operazione lasci la tabella invariata. La quarta confonde relocate con la selezione di una colonna, che elimina le altre.

  • False
  • False
  • False
  • True

Che cosa restituisce la seguente istruzione?

arrange(tibble(x = c(3, NA, 7)), desc(x))$x

desc() ordina in senso decrescente. arrange colloca sempre i valori mancanti in fondo, sia nell'ordinamento crescente sia in quello decrescente.

La seconda opzione è la più insidiosa: ragiona come se l'ordine decrescente fosse l'esatto contrario di quello crescente, e quindi porta in testa i valori mancanti. La terza tratta NA come il valore più piccolo e ignora desc. La quarta lascia la tabella nell'ordine originale.

  • False
  • True
  • False
  • False

Quale istruzione rinomina la colonna voto_laurea_su_110 della tibble anagrafica in voto_triennale?

In rename la sintassi è nuovo_nome = vecchio_nome, come in un'assegnazione: a sinistra il nome che si vuole ottenere, a destra quello attuale. Il risultato va poi assegnato per rendere permanente la modifica.

La seconda opzione non indica quale colonna rinominare. La terza è la più insidiosa: inverte i due nomi, e R restituisce l'errore Can't rename columns that don't exist, perché cerca una colonna voto_triennale che non esiste. La quarta assegna un unico nome a tutta la tabella: la prima colonna verrebbe rinominata voto_triennale e le altre resterebbero senza nome.

  • True
  • False
  • False
  • False

Si vuole usare un assistente AI per ottenere il codice R che aggiunge una colonna a una tabella. Quale dei seguenti modi di procedere è il più appropriato?

Un assistente AI è più utile quanto più è preciso il contesto: nomi reali delle tabelle e delle colonne, tipi di dato, package e funzioni da preferire. Il codice ottenuto va sempre eseguito e controllato sui dati, ad esempio contando i valori mancanti o verificando alcune righe "a mano". Chi lo inserisce nello script ne è responsabile e deve essere in grado di spiegarlo.

La seconda opzione è una generalizzazione infondata: il codice generato è spesso utile come punto di partenza. La terza è la più insidiosa: l'assenza di errori non garantisce la correttezza; un codice può funzionare e produrre un risultato sbagliato, ad esempio classificando male alcuni casi o trasformando silenziosamente dei valori in NA. La quarta confonde l'aiuto nella scrittura del codice con l'analisi dei dati, che va eseguita e controllata da chi la svolge.

  • False
  • True
  • False
  • False