Come funziona la stampa in R
R ha un'abitudine che nessun altro linguaggio diffuso condivide: in console non ti serve affatto un'istruzione di stampa. Scrivi il nome di una variabile, premi invio e R ne stampa il valore. È la stampa automatica (auto-printing), ed è il motivo per cui i tutorial di R sono pieni di espressioni isolate.
Ma la stampa automatica ha un confine rigido: scatta solo per le espressioni al livello più esterno. Dentro un ciclo for o il corpo di una funzione, un valore isolato viene valutato e buttato via in silenzio:
La x da sola viene stampata (è al livello più esterno), il primo ciclo non stampa proprio niente, e il secondo stampa 1, 2, 3 perché lo chiede in modo esplicito. "Il mio ciclo gira ma non mostra niente" è una delle domande più frequenti su R, e questa è tutta la risposta: dentro cicli e funzioni, stampare è sempre compito tuo. (Lo stesso vale quando esegui uno script con Rscript: ciò che funzionava riga per riga in console può ammutolire dentro un ciclo.)
print(): quella formale
print() mostra un valore come lo vede R, il che lo rende lo strumento giusto per ispezionare i dati e quello sbagliato per un output curato:
Saltano all'occhio due cose. Le stringhe mantengono le virgolette: print() ti mostra una rappresentazione fedele, e le virgolette ti dicono che è un valore di tipo carattere. E ogni riga inizia con un numero tra parentesi quadre come [1]: è l'indice del primo elemento su quella riga, quindi quando un vettore lungo va a capo, la parentesi di ogni riga ti dice da quale elemento riprende. È un aiuto alla lettura per i vettori, non rumore.
Se vuoi un output in stile print() ma senza virgolette, lo fanno sia print(x, quote = FALSE) sia noquote(x), ma di solito a quel punto quello che vuoi davvero è cat().
cat(): output per le persone
cat() (concatena e stampa) scrive testo grezzo: niente virgolette, niente prefissi di indice, e gli argomenti uniti da spazi. Il prezzo di questo controllo è che niente viene aggiunto al posto tuo, nemmeno l'a capo:
Dimenticare il "\n" è il rito di passaggio universale di cat(): senza, il pezzo di output successivo si incolla sulla stessa riga. Fai diventare un riflesso chiudere le chiamate a cat() con "\n".
La differenza di virgolette tra le due funzioni è in realtà una differenza in ciò che mostrano. print() mostra le sequenze di escape come le hai scritte; cat() le interpreta:
print() mostra \t e \n letteralmente tra virgolette: utile quando stai verificando cosa contiene esattamente una stringa. cat() li trasforma in una vera tabulazione e in un vero a capo: utile quando produci output. Scegli in base allo scopo: print() per ispezionare, cat() per presentare.
Report formattati: sprintf() + cat()
Gli argomenti separati da spazi di cat() arrivano fino a un certo punto. Per un output allineato e formattato, con decimali fissi e contatori riempiti, costruisci la stringa con sprintf() e passala a cat():
%-8s riempie ogni nome fino a 8 caratteri e %6.2f dà a ogni punteggio la stessa larghezza e due decimali, così le colonne si allineano. Questa coppia è il cavallo da tiro di R base per messaggi di avanzamento e piccoli report testuali (i codici di formato sono trattati in stringhe).
message() e warning(): l'altro canale
cat() e print() scrivono sullo standard output, il flusso che contiene i risultati del programma. message() e warning() scrivono sullo standard error, il flusso per i commenti sull'esecuzione:
A schermo sembrano simili, ma la separazione conta nel momento in cui l'output viene reindirizzato: manda lo stdout del tuo script in un file e il 42 finisce nel file mentre la nota di stato resta nel terminale. Ecco la regola pratica: risultati su stdout con cat(), commenti su stderr con message(). È anche il motivo per cui message() (e non cat()) è il modo educato con cui funzioni e pacchetti parlano ai loro utenti: chi li chiama può zittirli con suppressMessages() senza perdere l'output vero.
warning() è più forte, del tipo "qualcosa non va, ma sono andato avanti", e quando uno script gira con Rscript gli avvisi vengono raccolti e mostrati tutti insieme alla fine invece che sul momento (vedi debug degli errori per capire come leggerli).
Leggere l'input dell'utente: readline() e readLines()
Per fare una domanda all'utente in una sessione interattiva (la console di R o RStudio), usa readline(). Questi esempi non si possono eseguire nell'editor integrato, perché l'esecutore della pagina non ha un pannello di input, quindi provali in una console locale:
# Interactive sessions only:
name <- readline("What is your name? ")
cat("Hello,", name, "\n")
age <- as.numeric(readline("Your age? "))
cat("Next year you'll be", age + 1, "\n")
Due cose da ricordare. readline() restituisce sempre una stringa: convertila con as.numeric() prima di fare calcoli, e controlla se il risultato è NA nel caso l'utente abbia scritto qualcosa che non è un numero. E in uno script non interattivo, readline() non aspetta affatto l'input: restituisce subito "".
Per uno script eseguito con Rscript che deve leggere input passato con una pipe o digitato, leggi invece dallo standard input:
# In a script run as: echo "Ada" | Rscript greet.R
line <- readLines(con = "stdin", n = 1)
cat("Hello,", line, "\n")
readLines(con = "stdin") senza n legge tutte le righe fino alla fine dell'input: la forma standard per gli script che fanno da filtro. Leggere file di dati è un altro lavoro, con strumenti migliori; parti da read-csv quando il tuo input è un dataset e non una tastiera.
Cosa ti porti a casa
- La stampa automatica avviene solo al livello più esterno: dentro cicli e funzioni, chiama tu
print()ocat(). print()ispeziona: virgolette sulle stringhe, prefissi di indice[1], sequenze di escape mostrate letteralmente.cat()presenta: testo grezzo, argomenti uniti da spazi, e il"\n"lo metti tu.sprintf()+cat()è lo schema di R base per un output formattato e allineato.- I risultati vanno su stdout (
cat), i commenti su stderr (message,warning). readline()per l'input interattivo (sempre una stringa!);readLines(con = "stdin")per Rscript.
Prossimo passo: gli operatori, cioè aritmetici, di confronto e gli operatori logici che guidano ogni condizione che scriverai.
Domande frequenti
Qual è la differenza tra print() e cat() in R?
print() mostra un valore come R lo rappresenta: le stringhe mantengono le virgolette e ogni riga riceve un prefisso di indice come [1]. cat() scrive testo grezzo senza virgolette, senza indici e senza andare a capo da solo (aggiungi tu "\n"). Usa print() per ispezionare oggetti, cat() per produrre output destinato alle persone.
Perché il mio ciclo in R non stampa niente?
La stampa automatica avviene solo per le espressioni al livello più esterno. Dentro un ciclo for o il corpo di una funzione, una x da sola viene valutata e scartata in silenzio. Avvolgila in modo esplicito: print(x) oppure cat(x, "\n").
Come si legge l'input dell'utente in R?
In una sessione interattiva, readline("prompt: ") legge una riga digitata come stringa (convertila con as.numeric() se ti serve un numero). In uno script eseguito con Rscript, readline() non aspetta: leggi invece dallo standard input con readLines(con = "stdin", n = 1).
Come si stampa senza virgolette in R?
Usa cat("hello\n"): non aggiunge mai virgolette. Se vuoi proprio il comportamento di print() senza virgolette, funzionano anche print("hello", quote = FALSE) o noquote("hello").