La console interattiva è in genere comoda, ma spesso è meglio scrivere il codice in un unico file di testo: questo darà vita ad uno
script R. Farlo è davvero semplice, basta scrivere nel testo tutti i comandi che digiteremmo da console interattiva,
ed una volta salvato potrà essere avviato con Rscript, l'esecutore da riga di comando.
All'interno dello script si possono usare commenti per aumentare la leggibilità del codice. Esistono anche funzioni che producono un output testuale su console, come print
e message
.
Esempio
Vediamo un esempio completo che offrirà anche l'opportunità di vedere qualche altra interessante funzionalità di R. Supponiamo che:
- su un nostro server vengano caricati dei file in CSV, all'interno di una cartella denominata in;
- i file sono costituiti da due colonne separate da un punto e virgola, in cui la prima contiene il codice di un'agenzia commerciale di un'azienda (ad esempio AG001, AG002, etc.) e la seconda un elenco di importi incassati dall'agenzia:
"AG002";149.12 "AG001";301.8 "AG001";146.53 "AG004";110.69 "AG003";292.62
- ogni file CSV contiene importi misti, relativi ad agenzie diverse.
Creiamo uno script R che recupera tutti i file presenti nella cartella con estensione .csv, ed opera una sorta di smistamento, dando vita ad una serie di file ognuno relativo ad un'agenzia. Nella cartella out, verranno raccolti tutti i file così generati.
# fissiamo le cartelle di origine e destinazione dei dati
dir.root <- "D:\\dati"
dir.origine <- paste(dir.root, "in", sep="\\")
dir.destinazione <- paste(dir.root, "out", sep="\\")
# selezioniamo tutti i file della cartella origine il cui nome termina con il suffisso csv
files <- list.files(path=dir.origine, pattern="csv$")
# cicliamo su ogni file
for (f in files)
{
# leggiamo il file
nomefile <- paste(dir.origine, f, sep="\\")
df <- read.table(nomefile, sep=";")
colnames(df) <- c("Agenzia", "Importo")
# prendiamo l'elenco, senza duplicati, dei codici di agenzia
agenzie <- unique(df$Agenzia)
# per ogni codice selezioniamo dal file origine i record dell'agenzia e li salviamo su file CSV
for (k in agenzie)
{
# costruiamo il nome del file destinazione usando il codice agenzia
nomefile.dest=paste(k,"csv", sep=".");
nomefile.completo=paste(dir.destinazione, nomefile.dest, sep="\\")
# estraiamo solo i dati relativi all'agenzia trattata in questa iterazione
sub <- subset(df, Agenzia==k)
# salviamo su file
write.table(sub, nomefile.completo, append=TRUE, row.names=FALSE, col.names=FALSE, sep=";")
}
}
Oltre a quello che riguarda strettamente i file CSV, nello script
appaiono - per la prima volta in questa guida - i cicli for.
Come si vede, la sintassi in R è piuttosto immediata:
for ( ... in .... )
{
# operazioni da svolgere
}
L'operatore in
seleziona elementi dall'insieme alla sua destra e li tratta, uno alla volta, referenziandoli
con la variabile definita alla sua sinistra. Il primo ciclo permette di scansionare ogni singolo file CSV
posto nella cartella di origine. Si noti che la funzione list.files
elenca tutti i file nella
cartella indicata dal parametro path il cui nome combaci con l'espressione regolare indicata in pattern.
Andiamo a recuperare il contenuto del file CSV e lo poniamo nel data.frame. A quest'ultimo, rinomineremo le colonne con col.names utilizzando le stringhe che più ci aggradano ed infine estraiamo un elenco - senza duplicati - della colonna che contiene i codici agenzia. Questa operazione serve perchè supponiamo che il set di agenzie in attività possa essere in espansione e pertanto non sappiamo a priori tutti i codici che possono trovarsi al suo interno.
Con il ciclo interno, per ogni codice recuperato, creeremo un subset di record in modo da filtrare solo
quelli etichettati con la sigla che stiamo attualmente analizzando ed infine lo salviamo in un file.
Si faccia attenzione che si richiede una scrittura con append in maniera tale da non cancellare il lavoro
svolto dalle precedenti iterazioni.
Si potrà verificare nella cartella out che si è scelta che ci saranno tanti file quanti erano i codici
agenzia nominati nei dati in ingresso: ogni file conterrà solo i dati relativi all'agenzia che riguarda.
Usare file di input
Prima di concludere, vediamo in che modo abbiamo generato i dati usati per il nostro esercizio, quelli presenti nella cartella di origine:
num.righe <- 20
num.file <- 5
dir.destinazione <- "D:\\dati\\in"
agenzie <- c("AG001","AG002","AG003","AG004")
for (i in 1:num.file)
{
# generiamo colonna di agenzie
ag <- sample(agenzie, size=num.righe, replace=TRUE)
# generiamo colonna importi
imp <- round(runif(num.righe)*300+50, digits=2)
# rendiamo i due vettori colonne di data.frame
df <- data.frame(ag, imp)
# file destinazione con percorso
nome <- paste(dir.destinazione,paste(i,"csv",sep="."), sep="\\")
# salviamo data.frame su file
write.table(df, nome, row.names=FALSE, col.names=FALSE, sep=";")
}
Abbiamo fatto uso di molte funzioni di R che generano valori casuali.
La funzione sample produce una serie casuale di elementi prelevati da un campione.
In questo caso, dal vettore agenzie vengono recuperati i codici che vogliamo usare ed estratti casualmente
per venti volte: ciò ci darà un primo vettore. Il secondo vettore viene prodotto con runif: estraiamo venti numeri
casuali compresi tra 0 e 1 e tali valori vengono espansi con dei coefficienti in modo di avere un importo
che vada da 50 a 350 euro, poi arrotondati a due cifre con la funzione round.
È interessante notare che la funzione round
viene applicata ad ogni singolo
elemento dello stesso, come avviene in Python, Matlab e altri linguaggi di programmazione in grado di gestire operazioni vettoriali.