diff --git a/01-Introduction-get-started.Rmd b/01-Introduction-get-started.Rmd index a13d9e8..cc6271a 100644 --- a/01-Introduction-get-started.Rmd +++ b/01-Introduction-get-started.Rmd @@ -2,13 +2,13 @@ # Introduzione {-} -In questa sezione verranno prima presentate le istruzioni per installare R ed RStudio. Successivamente, svolgeremo le prime oprazioni in R e famiglierizzeremo con dei concetti di base della programmazioene quali gli oggetti e le funzioni. Introdurremmo infine altri concetti relativi alle sessioni di lavoro in R e descriveremo alcune buone regole per nell'utilizzo di R. +In questa sezione verranno prima presentate le istruzioni per installare R ed RStudio. Successivamente, svolgeremo le prime operazioni in R e familiarizzeremo con dei concetti di base della programmazione quali gli oggetti e le funzioni. Introdurremmo infine altri concetti relativi alle sessioni di lavoro in R e descriveremo alcune buone regole per l'utilizzo di R. I capitoli sono così organizzati: -- **Capitolo \@ref(install) - Installare R e RStudio**. Instruzioni passo a passo per installare R e RStudio +- **Capitolo \@ref(install) - Installare R e RStudio**. Istruzioni passo passo per installare R e RStudio. - **Capitolo \@ref(rstudio-gui) - Interfaccia RStudio**. Introduzione all'interfaccia utente di RStudio. -- **Capitolo \@ref(first-comands) - Primi Passi in R**. Operatori matematici, operatori relazionali, operatori logici. -- **Capitolo \@ref(objects-functions) - Due Compagni Inseparabili**. Introduzione dei concetti di oggetti e funzioni in R. -- **Capitolo \@ref(working-environment) - Ambiente di Lavoro**. Introduzione dei concetti di Envieronment, working directory e dei pacchetti di R. -- **Capitolo \@ref(working-session) - Sessione di Lavoro**. Descrizione di buone pratiche nelle sessioni di lavoro e gestione degli errori. +- **Capitolo \@ref(first-commands) - Primi passi in R**. Operatori matematici, operatori relazionali, operatori logici. +- **Capitolo \@ref(objects-functions) - Due compagni inseparabili**. Introduzione dei concetti di oggetti e funzioni in R. +- **Capitolo \@ref(working-environment) - Ambiente di lavoro**. Introduzione dei concetti di Environment, working directory e dei pacchetti di R. +- **Capitolo \@ref(working-session) - Sessione di lavoro**. Descrizione di buone pratiche nelle sessioni di lavoro e gestione degli errori. diff --git a/02-install.Rmd b/02-install.Rmd index acd6ea1..a2d5338 100755 --- a/02-install.Rmd +++ b/02-install.Rmd @@ -1,101 +1,101 @@ # Installare R e RStudio {#install} -R ed R-studio sono due software distinti. R è un linguaggio di programmazione usato in particolare in ambiti quali la statistica. R-studio invece è un'interfaccia *user-friendly* che permette di utilizzare R. -R può essere utilizzato autonomamente tuttavia è consigliato l'utilizzo attraverso R-studio. Entrambi vanno installati separatamente e la procedura varia a seconda del proprio sistema operativo (Windows, MacOS o Linux). Riportiamo le istruzioni solo per Windows e MacOS Linux (Ubuntu). Ovviamente R è disponibile per tutte le principali distribuzioni di Linux. Le istruzioni riportate per Ubuntu (la distribuzione più diffusa) sono valide anche per le distribuzioni derivate. +R ed RStudio sono due software distinti. R è un linguaggio di programmazione usato in particolare in ambiti quali la statistica. RStudio invece è un'interfaccia *user-friendly* che permette di utilizzare R. +R può essere utilizzato autonomamente tuttavia è consigliato l'utilizzo attraverso RStudio. Entrambi vanno installati separatamente e la procedura varia a seconda del proprio sistema operativo (Windows, Mac OS o Linux). Riportiamo le istruzioni solo per Windows, Mac OS e Linux (Ubuntu). Ovviamente R è disponibile per tutte le principali distribuzioni di Linux. Le istruzioni riportate per Ubuntu (la distribuzione più diffusa) sono valide anche per le distribuzioni derivate. ## Installare R {#install-r} -1. Accedere al sito https://www.r-project.org -2. Selezionare la voce **CRAN** (Comprehensive R Archive Network) dal menù di sinistra sotto **Download** +1. Accedere al sito https://www.r-project.org. +2. Selezionare la voce **CRAN** (Comprehensive R Archive Network) dal menù di sinistra sotto **Download**.
![](images/install_CRAN.png){ width=95% }

-3. Selezionare il primo link https://cloud.r-project.org/ +3. Selezionare il primo link https://cloud.r-project.org.
![](images/install_mirror.png){ width=95% }

- -4. Selezionare il proprio sistema operativo + +4. Selezionare il proprio sistema operativo.
![](images/install_OS.png){ width=95% }

-### R Windows +### R per Windows -1. Selezionare la voce **base** +1. Selezionare la voce **base**.
![](images/install-Windows-base.png){ width=95% }

- -2. Selezionare la voce **Download** della versione più recente di R disponibile + +2. Selezionare la voce **Download** della versione più recente di R disponibile.
![](images/install-Windows-version.png){ width=95% }

-3. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione +3. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione. -### R MacOS +### R per Mac OS -1. Selezionare della versione più recente di R disponibile +1. Selezionare la versione più recente di R disponibile .
![](images/install_Mac_version.png){ width=95% }

-2. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione di R -3. Successivamente è necessario installare anche una componente aggiuntiva **XQuartz** premendo il link all'interno del riquadro arancione riportato nella figura precedente -4. Selezionare la voce Download +2. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione di R. +3. Successivamente è necessario installare anche una componente aggiuntiva **XQuartz** premendo il link all'interno del riquadro arancione riportato nella figura precedente. +4. Selezionare la voce **Download**.
![](images/install_Mac_XQuartz.png){ width=95% }

-5. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione +5. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione. -### R Linux +### R per Linux Nonostante la semplicità di installazione di pacchetti su Linux, R a volte potrebbe essere più complicato da installare per via delle diverse distribuzioni, repository e chiavi per riconoscere la repository come sicura. Sul **CRAN** vi è la guida ufficiale con tutti i comandi `apt` da eseguire da terminale. Seguendo questi passaggi non dovrebbero esserci problemi. -1. Andate sul [CRAN](https://cran.r-project.org/) -2. Cliccate `Download R for Linux` -3. Selezionate la vostra distribuzione (Ubuntu in questo caso) -4. Seguite le istruzioni, principalmente eseguendo i comandi da terminale suggeriti +1. Andate sul [CRAN](https://cran.r-project.org/). +2. Cliccate **Download R for Linux**. +3. Selezionate la vostra distribuzione (Ubuntu in questo caso). +4. Seguite le istruzioni, principalmente eseguendo i comandi da terminale suggeriti. Per qualsiasi difficoltà o errore, sopratutto con il mondo Linux, una ricerca su online risolve sempre il problema.
-:::{.design title="R Tools" data-latex="[R Tools]"} -Utilizzi avanzati di R richiedono l'insallazione di una serie ulteriore software definiti **R tools**. +:::{.design title="RTools" data-latex="[RTools]"} +Utilizzi avanzati di R richiedono l'istallazione di una serie ulteriore software definiti **RTools**. -#### Windows{-} +#### Windows {-} -Seleziona la voce **Rtools** e segui le istruzioni per completare l'installazione. +Seleziona la voce **RTools** e segui le istruzioni per completare l'installazione.
![](images/install-Windows-tools.png){ width=95% }

-Nota che sono richieste anche delle operazioni di configurazione affinchè tutto funzioni correttamente. +Nota che sono richieste anche delle operazioni di configurazione affinché tutto funzioni correttamente. -#### MacOS{-} +#### Mac OS {-} Seleziona la voce **tools** e segui le istruzioni riportate. @@ -112,34 +112,34 @@ Nota in particolare che con R 4.0 le seguenti indicazioni sono riportate. ::: -## Installare R Studio +## Installare RStudio -1. Accedere al sito https://rstudio.com -2. Selezionare la voce **DOWNLOAD IT NOW** +1. Accedere al sito https://rstudio.com. +2. Selezionare la voce **DOWNLOAD IT NOW**.
![](images/install_rstudio1.png){ width=95% }

-3. Selezionare la versione gratuita di RStudio Desktop +3. Selezionare la versione gratuita di RStudio Desktop.
![](images/install_rstudio2.png){ width=95% }

-4. Selezionare la versione corretta a seconda del proprio sistema operativo +4. Selezionare la versione corretta a seconda del proprio sistema operativo.
![](images/install_rstudio3.png){ width=95% }

-5. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione +5. Al termine del download, eseguire il file e seguire le istruzioni fino al termine dell'installazione. -### R Studio in Linux +### RStudio per Linux -In questo caso, come su Windows e MacOS l'installazione consiste nello scaricare ed eseguire il file corretto, in base alla distribuzione (ad esempio `.deb` per Ubuntu e derivate). Importante, nel caso di Ubuntu (ma dovrebbe valere anche per le altre distribuzioni) anche versioni successive a quella indicata (es. Ubuntu 16) sono perfettamente compatibili. +In questo caso, come su Windows e Mac OS l'installazione consiste nello scaricare ed eseguire il file corretto, in base alla distribuzione (ad esempio `.deb` per Ubuntu e derivate). Importante, nel caso di Ubuntu (ma dovrebbe valere anche per le altre distribuzioni) anche versioni successive a quella indicata (es. Ubuntu 16) sono perfettamente compatibili. diff --git a/03-rstudio-gui.Rmd b/03-rstudio-gui.Rmd index ccca3c9..a6c66d9 100644 --- a/03-rstudio-gui.Rmd +++ b/03-rstudio-gui.Rmd @@ -8,9 +8,9 @@ knitr::opts_chunk$set( ) ``` -In questo capitolo presenteremo l'interfaccia utente di RStudio. Molti aspetti che introdurremo brevemente qui verranno discussi nei sucessivi capitoli. Adesso ci interessa solo famigliarizzare con l'interfaccia del nostro strumento di lavoro principale ovvero RStudio. +In questo capitolo presenteremo l'interfaccia utente di RStudio. Molti aspetti che introdurremo brevemente qui verranno discussi nei successivi capitoli. Adesso ci interessa solo familiarizzare con l'interfaccia del nostro strumento di lavoro principale ovvero RStudio. -Come abbiamo visto nel Capitolo \@ref(install), R è il vero "motore computazionale" che ci permette di compiere tutte le operazioni di calcolo, analisi statistiche e magie varie. Tuttavia l'interfaccia di base di R, definita **Console** (vedi Figura \@ref(fig:r-console)), è per così dire *démodé* o meglio, solo per veri intenditori. +Come abbiamo visto nel Capitolo \@ref(install), R è il vero "motore computazionale" che ci permette di compiere tutte le operazioni di calcolo, analisi statistiche e magie varie. Tuttavia l'interfaccia di base di R, definita **Console** (vedi Figura \@ref(fig:r-console)), è per così dire *démodé*, o meglio, solo per veri intenditori. ```{r r-console, fig.cap="La console di R, solo per veri intenditori", out.width="85%"} knitr::include_graphics("images/r-console.png") @@ -18,12 +18,12 @@ knitr::include_graphics("images/r-console.png") In genere, per lavorare con R viene utilizzato RStudio. RStudio è un programma (IDE - Integrated Development Environment) che integra in un unica interfaccia utente (GUI - Graphical User Interface) diversi strumenti utili per la scrittura ed esecuzione di codici. L'interfaccia di RStudio è costituita da 4 pannelli principali (vedi Figura \@ref(fig:rstudio-gui)): -```{r rstudio-gui, fig.cap="Interfaccia utente di Rstudio con i suoi 4 pannelli", out.width="85%"} +```{r rstudio-gui, fig.cap="Interfaccia utente di RStudio con i suoi 4 pannelli", out.width="85%"} knitr::include_graphics("images/rstudio-gui.png") ``` -:::{.design title="R-Basic vs RStudio" data-latex="[R-Basic vs RStudio]"} -L'utilizzo di R attraverso l'interfaccia di base piuttosto che RStudio, non è uno scontro tra due scuole di pensiero (o generazioni). Entrambe hanno vantaggi e svantaggi e pertanto vengono scelte a seconda delle dieverse necessità. +:::{.design title="R Console vs RStudio" data-latex="[R Console vs RStudio]"} +L'utilizzo di R attraverso l'interfaccia di base piuttosto che RStudio, non è uno scontro tra due scuole di pensiero (o generazioni). Entrambe hanno vantaggi e svantaggi e pertanto vengono scelte a seconda delle diverse necessità. Quando si è alla ricerca della massima ottimizzazione, l'uso dell'interfaccia di base, grazie alla sua semplicità, permette di minimizzare l'utilizzo della memoria limitandosi allo stretto e necessario. @@ -33,9 +33,9 @@ In altri casi, invece, le funzionalità e strumenti aggiuntivi di RStudio permet #### 1. Console: il cuore di R {-} -Qui ritroviamo la *Console* di R dove vengono effetivemente eseguiti tutti i tuoi codici e comandi. Nota come nell'ulitma riga della *Console* appaia il carattere `>`. Questo è definito *prompt* è ci indica che R in attesa di nuovi comandi da eseguire. +Qui ritroviamo la *Console* di R dove vengono effettivamente eseguiti tutti i tuoi codici e comandi. Nota come nell'ultima riga della *Console* appaia il carattere `>`. Questo è definito *prompt* e ci indica che R è in attesa di nuovi comandi da eseguire. -La *Console* di R è un'interfaccia a linea di comando. A differenza di altri programmi "*punta e clicca*", in R è necessario digitare i comandi utilizzando la tastiera. Per eseguire dei comandi possiamo direttamnte scrivere nella *Console* le operazioni da eseguire e premere `invio`. R eseguirà immediatamente i nostro comando, riporterà il risultato e nella linea successiva apparirà nuovamente il *prompt* indicando che R è pronto ad eseguire un altro comando (vedi Figura \@ref(fig:comand-sequence)). +La *Console* di R è un'interfaccia a linea di comando. A differenza di altri programmi "*punta e clicca*", in R è necessario digitare i comandi utilizzando la tastiera. Per eseguire dei comandi possiamo direttamente scrivere nella *Console* le operazioni da eseguire e premere `invio`. R eseguirà immediatamente i nostro comando, riporterà il risultato e nella linea successiva apparirà nuovamente il *prompt* indicando che R è pronto ad eseguire un altro comando (vedi Figura \@ref(fig:comand-sequence)). ```{r comand-sequence, fig.cap="Esecuzione di comandi direttamente nella console", out.width="95%"} knitr::include_graphics("images/comand-sequence.png") @@ -47,26 +47,26 @@ Nel caso di comandi scritti su più righe, vedi l'esempio di Figura \@ref(fig:mu knitr::include_graphics("images/multiple-line-comand.png") ``` -Come avrai notato facendo alcune prove, i comandi digitati nella *Console* vengono eseguiti immediatamente ma non sono salvati. Per rieseguire un comando, possiamo navigare tra quelli precedentementemente eseguiti usando le freccie della tastiera $\uparrow\downarrow$. Tuttavia, in caso di errori dovremmo riscrivere e rieseguire tutti i comandi. Siccome scrivere codici è un continuo "*try and error*", lavorare unicamente dalla *Console* diventa presto caotico. Abbiamo bisogno quindi di una soluzione che ci permetta di lavrorare più comodamente sui nostri codici e di poter salvare i nostri comandi da eseguire all'occorrenza con il giusto ordine. La soluzione sono gli *Scripts* che introdurremo vedremo nella prossima sezione. +Come avrai notato facendo alcune prove, i comandi digitati nella *Console* vengono eseguiti immediatamente ma non sono salvati. Per rieseguire un comando, possiamo navigare tra quelli precedentemente eseguiti usando le frecce della tastiera $\uparrow\downarrow$. Tuttavia, in caso di errori dovremmo riscrivere e rieseguire tutti i comandi. Siccome scrivere codici è un continuo "*trial and error*", lavorare unicamente dalla *Console* diventa presto caotico. Abbiamo bisogno quindi di una soluzione che ci permetta di lavorare più comodamente sui nostri codici e di poter salvare i nostri comandi da eseguire all'occorrenza con il giusto ordine. La soluzione sono gli *Script* che introdurremo nella prossima sezione. :::{.tip title="Interrompere un comando" data-latex="[Interrompere un comando]"} -Potrebbe accadere che per qualche errore nel digitare un comando o perchè sono richiesti lunghi tempi computazionali, la *Console* di R diventi non responsiva. In questo caso è necessario interrompere la scrittura o l'esecuzione di un comando. Vediamo due situazioni comuni: +Potrebbe accadere che per qualche errore nel digitare un comando o perché sono richiesti lunghi tempi computazionali, la *Console* di R diventi non responsiva. In questo caso è necessario interrompere la scrittura o l'esecuzione di un comando. Vediamo due situazioni comuni: -1. **Continua a comparire il prompt** `+`. Specialmente nel caso di utilizzo di parentesi e lunghi comandi, accade che una volta premuto `invio` R non esegua alcun comando ma resta in attesa mostrando il *prompt* `+` (vedi Figure seguente). Questo è in genere dato da un errore nella sintassi del comando (e.g., un errore nell'uso delle parentesi o delle virgole). Per riprendere la sessione è necessario premere il tasto `esc` della tastiera. L'apprire del *prompt* `>`, indica che R è nuovamente in ascolto pronto per esequire un nuovo comando ma attento a non ripetere lo stesso errore. +1. **Continua a comparire il prompt** `+`. Specialmente nel caso di utilizzo di parentesi e lunghi comandi, accade che una volta premuto `invio` R non esegua alcun comando ma resta in attesa mostrando il *prompt* `+` (vedi Figura seguente). Questo è in genere dato da un errore nella sintassi del comando (ad es. un errore nell'uso delle parentesi o delle virgole). Per riprendere la sessione è necessario premere il tasto `esc` della tastiera. L'apparire del *prompt* `>`, indica che R è nuovamente in ascolto pronto per eseguire un nuovo comando ma attento a non ripetere lo stesso errore. ```{r my-label, out.width="95%"} # fig.cap="Tipica condizione in cui R resta in attesa ed il comando non viene eseguito - Premere esc per riprendere la sessione" -# LaTeX do not support figure in minipage so no add label +# LaTeX does not support figure in minipage so do no add a label knitr::include_graphics("images/comand-esc.png") ``` -2. **R non risponde**. Alcuni calcoli potrebbero richiedere molto tempo o semplicemnte un qualche problema ha mandato in loop la tua sessione di lavoro. In questa situazione la *Console* di R diventa non responsiva. Nel caso fosse necessario interrompere i processi attualmente in esecuzione devi premere il pulsante *STOP* come indicato nella Figura seguente. R si fermerà e ritornerà in attesa di nuovi comandi (*prompt* `>`). +2. **R non risponde**. Alcuni calcoli potrebbero richiedere molto tempo o semplicemente un qualche problema ha mandato in loop la tua sessione di lavoro. In questa situazione la *Console* di R diventa non responsiva. Nel caso fosse necessario interrompere i processi attualmente in esecuzione devi premere il pulsante *STOP* come indicato nella Figura seguente. R si fermerà e ritornerà in attesa di nuovi comandi (*prompt* `>`). ```{r console-stop, out.width="95%"} # fig.cap="Premi il pulsante stop per interrompere l'attuale processo" -# LaTeX do not support figure in minipage so no add label +# LaTeX does not support figure in minipage so do no add a label knitr::include_graphics("images/console-stop.png") ``` @@ -80,29 +80,29 @@ Come ultima soluzione ricorda uno dei principi base dell'informatica "*spegni e #### 2. Source: il tuo blocco appunti {-} -In questa parte vengono mostrati i tuoi *Scripts*. Questi non sono altro che degli speciali documenti (con estensione "**.R**") in cui sono salvati i tuoi codici e comandi che potrai eseguire quando necessario in R. Gli *Scripts* ti permetteranno di lavorare comodamente sui tuoi codici, scrivere i comandi, corregerli, organizzarli, aggiungere dei commenti e soprattutto salvarli. +In questa parte vengono mostrati i tuoi *Script*. Questi non sono altro che degli speciali documenti (con estensione "**.R**") in cui sono salvati i tuoi codici e comandi che potrai eseguire quando necessario in R. Gli *Script* ti permetteranno di lavorare comodamente sui tuoi codici, scrivere i comandi, correggerli, organizzarli, aggiungere dei commenti e soprattutto salvarli. -Dopo aver terminato di scrivere i comandi, posiziona il cursore sulla stessa linea del comando che desideri eseguire e premi `command + invio` (MacOs) o `Ctrl+R` (Windows). Automaticamente il comando verà copiato nella *Console* ed eseguito. In alternativa potrai premere il tasto **Run** indicato dalla freccia in Figura \@ref(fig:script-run). +Dopo aver terminato di scrivere i comandi, posiziona il cursore sulla stessa linea del comando che desideri eseguire e premi `command + invio` (MacOs) o `Ctrl+R` (Windows). Automaticamente il comando verrà copiato nella *Console* ed eseguito. In alternativa potrai premere il tasto **Run** indicato dalla freccia in Figura \@ref(fig:script-run). ```{r script-run, fig.cap="Esecuzione di un comando da script premi `command + invio` (MacOs)/ `Ctrl+R` (Windows) o premi il tasto indicato dalla freccia", out.width="95%"} knitr::include_graphics("images/script-run.png") ``` :::{.tip title="Commenti" data-latex="[Commenti]"} -Se hai guardato con attenzione lo script rappresentato in Figura \@ref(fig:script-run), potresti aver notato delle righe di testo verde precedute dal simbolo `#`. Questo simbolo può essere utlizzato per inserire dei *commenti* all'interno dello script. R ignorerà qualsiasi commento ed eseguirà soltato le parti di codici. +Se hai guardato con attenzione lo script rappresentato in Figura \@ref(fig:script-run), potresti aver notato delle righe di testo verde precedute dal simbolo `#`. Questo simbolo può essere utilizzato per inserire dei *commenti* all'interno dello script. R ignorerà qualsiasi commento ed eseguirà soltanto le parti di codice. -L'utilizzo dei commenti è molto importante nel caso di script complessi poichè ci permette di spiegare e documentare il codice che viene eseguito. Nel Capitolo \@ref(sintax) approfondiremo il loro utilizzo. +L'utilizzo dei commenti è molto importante nel caso di script complessi poiché ci permette di spiegare e documentare il codice che viene eseguito. Nel Capitolo \@ref(syntax) approfondiremo il loro utilizzo. ::: -:::{.design title="Creare e Salvare uno Script" data-latex="[Creare e Salvare uno Script]"} -Per creare un nuovo script è sufficiente premere il pulsante in alto a sinistra come mostrato in Figura e selezionare *"R Script"*. +:::{.design title="Creare e salvare uno script" data-latex="[Creare e Salvare uno Script]"} +Per creare un nuovo script è sufficiente premere il pulsante in alto a sinistra come mostrato in Figura e selezionare "*R Script*".
![](images/script-new.png){ width=75% }

-Unn nuovo script senza nome verrà creato. Per salvare lo script premere l'icona del floppy e indicare il nome. Ricorda di usare l'estensione "**.R**" per salvare gli script. +Un nuovo script senza nome verrà creato. Per salvare lo script premere l'icona del floppy e indicare il nome. Ricorda di usare l'estensione "**.R**" per salvare gli script.
![](images/script-save.png){ width=75% } @@ -113,56 +113,51 @@ Unn nuovo script senza nome verrà creato. Per salvare lo script premere l'icona #### 3. Environment e History: la sessione di lavoro {-} -Qui sono presentati una serie di pannelli utili per valutare informazioni inerenti alla propria sessione di lavoro. I pannelli principali sono *Environment* e *History* (gli altri pannelli presenti in Figura \@ref(fig:environment) riguardanno funzioni avanzate di RStudio). +Qui sono presentati una serie di pannelli utili per valutare informazioni inerenti alla propria sessione di lavoro. I pannelli principali sono *Environment* e *History* (gli altri pannelli presenti in Figura \@ref(fig:environment) riguarderanno funzioni avanzate di RStudio). -- **Environment**: elenco tutti gli oggetti e variabili attualmente presenti nel'ambiente di lavoro. Approfondiremo i concetti di variabili e di ambiente di lavoro rispettivamente nel Capitolo \@ref(objects-section) e Capitolo \@ref(environment). +- **Environment**: elenco di tutti gli oggetti e le variabili attualmente presenti nel'ambiente di lavoro. Approfondiremo i concetti di variabili e di ambiente di lavoro rispettivamente nel Capitolo \@ref(objects-section) e Capitolo \@ref(environment). -```{r environment, fig.cap="*Environment* - Elenco degli oggetti e variabili presenti nel'ambiente di lavoro", out.width="60%"} +```{r environment, fig.cap="\\textit{Environment} - Elenco degli oggetti e variabili presenti nel'ambiente di lavoro", out.width="60%"} knitr::include_graphics("images/environment.png") ``` -- **History**: elenco di tutti i comandi precedentemente eseguiti nella console. Nota che questo no equivale ad uno script, anzi, è semplicemente un elenco non modificabile (e quasi mai usato). +- **History**: elenco di tutti i comandi precedentemente eseguiti nella console. Nota che questo non equivale ad uno script, anzi, è semplicemente un elenco non modificabile (e quasi mai usato). -#### 4. File, Plots, Package, Help: system management{-} +#### 4. File, Plots, Package, Help: system management {-} -In questa parte sono raccolti una serie di pannelli utilizzatti per interfacciarsi con ulteriori risorse del sistema (e.g., file e pacchetti) o produrre output quali grafici e tabelle. +In questa parte sono raccolti una serie di pannelli utilizzati per interfacciarsi con ulteriori risorse del sistema (ad es. file e pacchetti) o produrre output quali grafici e tabelle. -- **Files**: pannello da cui è possibile navigare tra tutti i file del proprio computer +- **Files**: pannello da cui è possibile navigare tra tutti i file del proprio computer. -```{r files, fig.cap="*Files* - permette di navigare tra i file del proprio computer", out.width="60%"} +```{r files, fig.cap="\\textit{Files} - permette di navigare tra i file del proprio computer", out.width="60%"} knitr::include_graphics("images/files.png") ``` -- **Plots**: pannello i cui vengono prodotti i grafici e che è possibil esportare cliccando *Export*. +- **Plots**: pannello i cui vengono prodotti i grafici, che possono essere esportati cliccando *Export*. -```{r plots, fig.cap="*Plots* - presentazione dei grafici", out.width="60%"} +```{r plots, fig.cap="\\textit{Plots} - presentazione dei grafici", out.width="60%"} knitr::include_graphics("images/plots.png") ``` - **Packages**: elenco dei pacchetti di R (questo argomento verrà approfondito nel Capitolo \@ref(packages)). -```{r packages, fig.cap="*Packages* - elenco dei pacchetti di R", out.width="60%"} +```{r packages, fig.cap="\\textit{Packages} - elenco dei pacchetti di R", out.width="60%"} knitr::include_graphics("images/packages.png") ``` - **Help**: utilizzato per navigare la documentazione interna di R (questo argomento verrà approfondito nel Capitolo \@ref(help)). -```{r help, fig.cap="*Help* - documentazione di R", out.width="60%"} +```{r help, fig.cap="\\textit{Help} - documentazione di R", out.width="60%"} knitr::include_graphics("images/help.png") ``` :::{.tip title="Personalizza tema e layout" data-latex="[Personalizza tema e layout]"} -RStudio permette un ampio grado di personalizzazione dell'intrafaccia grafica utilizzata. E' possibile cambiare tema, font e disposizione dei pannelli a seconda dei tuoi gusti ed esigenze. +RStudio permette un ampio grado di personalizzazione dell'interfaccia grafica utilizzata. È possibile cambiare tema, font e disposizione dei pannelli a seconda dei tuoi gusti ed esigenze. -Prova a cambiare il tema dell editor in *Idle Fingers* per utlizzare on background scuro che affatichi meno la vista (vedi Figura seguente). Clicca su RStudio > Preferenze > Appearence (MacOS) o Tools > Options > Appearence (Windows). +Prova a cambiare il tema dell editor in *Idle Fingers* per utilizzare uno sfondo scuro che affatichi meno la vista (vedi Figura seguente). Clicca su *RStudio > Preferenze > Appearance* (Mac OS) o su *Tools > Options > Appearance (Windows)*. ```{r dark-theme, out.width="90%"} knitr::include_graphics("images/dark-theme.png") ``` ::: - - - - - diff --git a/04-first-comands.Rmd b/04-first-commands.Rmd similarity index 73% rename from 04-first-comands.Rmd rename to 04-first-commands.Rmd index 11c6d08..ea46456 100644 --- a/04-first-comands.Rmd +++ b/04-first-commands.Rmd @@ -1,4 +1,4 @@ -# Primi Passi in R {#first-comands} +# Primi passi in R {#first-commands} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -9,13 +9,13 @@ knitr::opts_chunk$set( library(kableExtra) ``` -Ora che abbiamo iniziato a famigliarizzare con il nostro stumento di lavoro possiamo finalmente dare fuoco alle polveri e concentraci sulla scrittura di codici! +Ora che abbiamo iniziato a familiarizzare con il nostro strumento di lavoro possiamo finalmente dare fuoco alle polveri e concentraci sulla scrittura di codici! -In questo capitolo muoveremo i primi passi in R. Inizieremo vedendo come utilizzare operatori matematici, relazionali e logici per compiere semplici operazioni in R. Imparare R è un lungo percorso (scoop: questo percorso non termina mai dato che R è sempre in continuo sviiluppo). Soprattutto all'inizio può sembrare eccessivamente difficile poichè è si incontrano per la prima volta molti comandi e concetti di programmazione. Tuttavia, una volta famigliarizzato con gli apetti di base, la progressione diventa sempre più veloce (inarrestabile direi!). +In questo capitolo muoveremo i primi passi in R. Inizieremo vedendo come utilizzare operatori matematici, relazionali e logici per compiere semplici operazioni in R. Imparare R è un lungo percorso (scoop: questo percorso non termina mai dato che R è sempre in continuo sviluppo). Soprattutto all'inizio può sembrare eccessivamente difficile poiché si incontrano per la prima volta molti comandi e concetti di programmazione. Tuttavia, una volta familiarizzato con gli aperti di base, la progressione diventa sempre più veloce (inarrestabile direi!). In questo capitolo introdurremo per la prima volta molti elementi che saranno poi ripresi e approfonditi nei seguenti capitoli. Quindi non preoccuparti se non tutto ti sarà chiaro fin da subito. Imparare il tuo primo linguaggio di programmazione è difficile ma da qualche parte bisogna pure iniziare. Pronto per le tue prime linee di codice? Let's become a useR! -## Operatori Matematici {#math-operators} +## Operatori matematici {#math-operators} R è un'ottima calcolatrice. Nella Tabella \@ref(tab:table-math-operators) sono elencati i principali operatori matematici e funzioni usate in R. @@ -76,31 +76,31 @@ kableExtra::kable(math_operators, col.names = c("Funzione", "Nome", "Esempio"), ``` :::{.tip title="Le prime funzioni" data-latex="[Le prime funzioni]"} -Nota come per svolgere operazioni come la radice quadrata o il valore assoluto vengono utlizzate delle specifiche funzioni. In R le funzioni sono richiamate digitando `()` (e.g., `sqrt(25)`) indicando all'interno delle parentesi tonde gli argomenti della funzione. Approfondiremo le funzioni nel Capitolo \@ref(functions-def). +Nota come per svolgere operazioni come la radice quadrata o il valore assoluto vengono utilizzate delle specifiche funzioni. In R le funzioni sono richiamate digitando `()` (ad es. `sqrt(25)`) indicando all'interno delle parentesi tonde gli argomenti della funzione. Approfondiremo le funzioni nel Capitolo \@ref(functions-def). ::: -### Ordine Operazioni +### Ordine operazioni Nello svolgere le operazioni, R segue lo stesso l'ordine usato nelle normali espressioni matematiche. Quindi l'ordine di precedenza degli operatori è: 1. `^` (potenza) 2. `%%` (resto della divisione) e `%/%` (divisione intera) 3. `*` (moltiplicazione) e `/`(divisione) -4. `+` (addizione) e `-`(sotttrazione) +4. `+` (addizione) e `-`(sottrazione) -Nota che in presenza di funzioni (e.g., `abs()`, `sin()`), R per prima cosa sostituisca le funzioni con il loro risultato per poi procedere con l'esecuzione delle operazioni nell'ordine indicato precedentemente. +Nota che in presenza di funzioni (ad es. `abs()`, `sin()`), R per prima cosa sostituisce le funzioni con il loro risultato per poi procedere con l'esecuzione delle operazioni nell'ordine indicato precedentemente. -L'ordine di esecuzione delle operazioni può essere controllato attraverso l'uso delle **parentesi tondone** `()`. R eseguirà tutte le operazioni incluse nelle parentesi seguendo lo stesso ordine inndicato sopra. Utilizzando più gruppi di parentesi possiamo ottenere i risultati desiderati. +L'ordine di esecuzione delle operazioni può essere controllato attraverso l'uso delle **parentesi tonde** `()`. R eseguirà tutte le operazioni incluse nelle parentesi seguendo lo stesso ordine indicato sopra. Utilizzando più gruppi di parentesi possiamo ottenere i risultati desiderati. :::{.warning title="Le parentesi" data-latex="[Le parentesi]"} -Nota che in R solo le **parentesi tonde** `()` sono utilizzate per gestire l'ordine con cui sono eseguite le oprazioni. +Nota che in R solo le **parentesi tonde** `()` sono utilizzate per gestire l'ordine con cui sono eseguite le operazioni. -**Parentesi quadre** `[]` e **parentesi graffe** `{}` sono invece speciali operatori utilizzati in R per altre ragioni come la selezione di elementi e la definizione di blocchi di codici. Argomenti che approfondiremo rispettivamente nel Capitolo \@ref(vector-selection) e Capitolo TODO. +**Parentesi quadre** `[]` e **parentesi graffe** `{}` sono invece speciali operatori utilizzati in R per altre ragioni come la selezione di elementi e la definizione di blocchi di codice. Argomenti che approfondiremo rispettivamente nel Capitolo \@ref(vector-selection) e Capitolo \@ref(syntax). ::: -### Esercizi{-} +### Esercizi {-} -Calcola il risultato delle seguenti operazioni utilizzando R ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-03-first-comands.R)): +Calcola il risultato delle seguenti operazioni utilizzando R ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-03-first-commands.R)): 1. $\frac{(45+21)^3+\frac{3}{4}}{\sqrt{32-\frac{12}{17}}}$ @@ -114,19 +114,19 @@ Calcola il risultato delle seguenti operazioni utilizzando R ([soluzioni](https: Note per la risoluzione degli esercizi: -- In R la radice quadrata si ottine con la funzione `sqrt()` mentre per radici di indici diversi si utilizza la notazione esponenziale ($\sqrt[3]{x}$ è dato da `x^(1/3)`). +- In R la radice quadrata si ottiene con la funzione `sqrt()` mentre per radici di indici diversi si utilizza la notazione esponenziale ($\sqrt[3]{x}$ è dato da `x^(1/3)`). - Il valore di $\pi$ si ottiene con `pi`. - Il valore di $e$ si ottiene con `exp(1)`. -- In R per i logaritmi si usa la funzione `log(x, base=a)`, di base viene considerato il logaritmo naturale. +- In R per i logaritmi si usa la funzione `log(x, base=a)`, di default viene considerato il logaritmo naturale. -## Operatori Relazionali e Logici {#operators-rel-log} +## Operatori relazionali e logici {#operators-rel-log} -Queste operazioni al momento potrebbero sembrare non particolrmente interessanti ma si riveleranno molto utili nei capitoli successivi ad esempio per la selezione di elementi (vedi Capitolo \@ref(vector-selection-advanced)) o la definizionne di algoritmi (vedi Capitolo TODO). +Queste operazioni al momento potrebbero sembrare non particolarmente interessanti, ma si riveleranno molto utili nei capitoli successivi, ad esempio per la selezione di elementi (vedi Capitolo \@ref(vector-selection-advanced)) o la definizione di algoritmi (vedi Capitolo \@ref(functions)). -### Operatori Relazionali +### Operatori relazionali -In R è possibile valutare se una data relazione è vera o falsa. Ad esempio, posiamo valutare se "*2 è minore di 10*" o se "*4 numero è un numero pari*". +In R è possibile valutare se una data relazione è vera o falsa. Ad esempio, posiamo valutare se "*2 è minore di 10*" o se "*4 è un numero pari*". R valuterà le proposizioni e ci restituirà il valore `TRUE` se la proposizione è vera oppure `FALSE` se la proposizione è falsa. Nella Tabella \@ref(tab:relational-operators) sono elencati gli operatori relazionali. @@ -160,14 +160,14 @@ kableExtra::kable(logical_operators, col.names = c("Funzione", "Nome", "Esempio" latex_options = c("hold_position")) ``` -:::{.warning title="'==' non è uguale a '='" data-latex="['==' non è uguale a '=']"} -Attenzione che per valutare l'uguaglianza tra due valori non bisogna utilizzare `=` ma `==`. Questo è un'errore molto comune ceh si commmette in continuazione. +:::{.warning title="\\texttt{==} non è uguale a \\texttt{=}" data-latex="[== non è uguale a =]"} +Attenzione che per valutare l'uguaglianza tra due valori non bisogna utilizzare `=` ma `==`. Questo è un'errore molto comune che si commette in continuazione. -L'operatore `=` è utilizzato in R per assegnare un valore ad una variablie. Argomento che vederemo nel Capitolo \@ref(assign). +L'operatore `=` è utilizzato in R per assegnare un valore ad una variabile. Argomento che vederemo nel Capitolo \@ref(assign). ::: -:::{.tip title="TRUE-T-1; FALSE-F-0" data-latex="[TRUE-T-1; FALSE-F-0]"} -Nota che in qualsiasi linguaggio di Programmazione, ai valori TRUE e FALSE sono associati rispettivament i valori numerici 1 e 0. Questi sono definiti [valori booleani](https://it.wikipedia.org/wiki/Variabile_booleana). +:::{.tip title="\\texttt{TRUE}-\\texttt{T}-\\texttt{1} e \\texttt{FALSE}-\\texttt{F}-\\texttt{0}" data-latex="[\\texttt{TRUE}-\\texttt{T}-\\texttt{1} e \\texttt{FALSE}-\\texttt{F}-\\texttt{0}]"} +Nota che in molti linguaggi di programmazione, compreso R, ai valori `TRUE` e `FALSE` sono associati rispettivamente i valori numerici `1` e `0`. Questi sono definiti [valori booleani](https://it.wikipedia.org/wiki/Variabile_booleana). ```{r relational-operators-ex1, echo=TRUE, eval=FALSE} TRUE == 1 # TRUE @@ -177,7 +177,7 @@ FALSE == 0 # TRUE FALSE == 1 # FALSE ``` -In R è possibile anche abbreviare TRUE e FALSE rispettivamente in T e F, sebbene sia una pratica non consigliata poichè potrebbe nonn essere chiara e creare fraintendimenti. Infatti mentre TRUE e FALSE sono parole riservate (vedi Capitolo \@ref(objects-names)) T a F non lo sono. +In R è possibile anche abbreviare `TRUE` e `FALSE` rispettivamente in `T` e `F`, sebbene sia una pratica non consigliata poiché potrebbe non essere chiara e creare fraintendimenti. Infatti mentre `TRUE` e `FALSE` sono parole riservate (vedi Capitolo \@ref(objects-names)), `T` e `F` non lo sono. ```{r relational-operators-ex2, echo=TRUE, eval=FALSE} T == 1 # TRUE @@ -188,9 +188,9 @@ F == FALSE # TRUE ::: -### Operatori Logici +### Operatori logici -In R è possibile congiungere più relazioni per valutare una desiderata proposizione. Ad esempio potremmo valutare se "*17 è maggiore di 10 e minore di 20*". Per unire più relazioni in un'unica proposizione che R valuterà come `TRUE` o `FALSE`, vengono utilizati gli operatori logici riportati in Tabella \@ref(tab:logical-operators). +In R è possibile congiungere più relazioni per valutare una desiderata proposizione. Ad esempio potremmo valutare se "*17 è maggiore di 10 e minore di 20*". Per unire più relazioni in un'unica proposizione che R valuterà come `TRUE` o `FALSE`, vengono utilizzati gli operatori logici riportati in Tabella \@ref(tab:logical-operators). ```{r logical-operators} @@ -223,7 +223,7 @@ kableExtra::kable(logical_operators, col.names = c("Funzione", "Nome", "Esempio" Questi operatori sono anche definiti [operatori booleani](https://it.wikipedia.org/wiki/Espressione_booleana) e seguono le comuni definizioni degli operatori logici. In particolare abbiamo che: -- Nel caso della **congiunzione logica** `&`, affinchè la proposizione sia vera è necessario che entrambe le relazioni siano vere. Negli altri casi la proposizione sarà valutarta falsa (vedi Tabella \@ref(tab:and-operator)). +- Nel caso della **congiunzione logica** `&`, affinché la proposizione sia vera è necessario che entrambe le relazioni siano vere. Negli altri casi la proposizione sarà valutata falsa (vedi Tabella \@ref(tab:and-operator)). ```{r and-operator} @@ -252,7 +252,7 @@ kableExtra::kable(and_operator, col.names = col_names, latex_options = c("hold_position")) ``` -- Nel caso della **disgiunzione inclusiva logica** `|`, affinchè la proposizione sia vera è necessario che almeno una relaziona sia vera. La proposizione sarà valutarta falsa solo quando entrambe le relazioni sono false (vedi Tabella \@ref(tab:or-operator)). +- Nel caso della **disgiunzione inclusiva logica** `|`, affinché la proposizione sia vera è necessario che almeno una relaziona sia vera. La proposizione sarà valutata falsa solo quando entrambe le relazioni sono false (vedi Tabella \@ref(tab:or-operator)). ```{r or-operator} @@ -272,11 +272,11 @@ kableExtra::kable(or_operator, col.names = c("x", "y", "x | y"), :::{.design title="Disgiunzione esclusiva" data-latex="[Disgiunzione esclusiva]"} -Per completezza ricordiamo che tra gli operatori logici esiste anche la **disgiunzione esclusiva**. La proposizione sarà valutata falsa se entrambe le relazioni sono vere oppure false. Affinchè la proposizione sia valutata vera una sola delle relazioni deve essere vera mentre l'altra deve essere falsa. +Per completezza ricordiamo che tra gli operatori logici esiste anche la **disgiunzione esclusiva**. La proposizione sarà valutata falsa se entrambe le relazioni sono vere oppure false. Affinché la proposizione sia valutata vera una sola delle relazioni deve essere vera mentre l'altra deve essere falsa. -In R la disgiunzione esclusiva tra due ralazioni (x e y) è indicata con la funzione `xor(x, y)`. Tuttavia tale funzione è raramente usata. +In R la disgiunzione esclusiva tra due relazioni (x e y) è indicata con la funzione `xor(x, y)`, tuttavia tale funzione è raramente usata. -
+
Table: Disgiunzione esclusiva 'xor(x, y)' | x | y | xor(x, y) | @@ -292,23 +292,23 @@ Table: Disgiunzione esclusiva 'xor(x, y)' Nel valutare le veridicità delle proposizioni R esegue le operazioni nel seguente ordine: -1. operatori matematici (e.g., `^`, `*`, `/`, `+`, `-`, etc.) -2. operatori relazionali (e.g., `<`, `>`, `<=`, `>=`, `==`, `!=`) -3. operatori logici (e.g., `!`, `&`, `|`) +1. operatori matematici (ad es. `^`, `*`, `/`, `+`, `-`, etc.) +2. operatori relazionali (ad es. `<`, `>`, `<=`, `>=`, `==`, `!=`) +3. operatori logici (ad es. `!`, `&`, `|`) La lista completa dell'ordine di esecuzione delle operazioni è riportata al seguente link [https://stat.ethz.ch/R-manual/R-devel/library/base/html/Syntax.html](https://stat.ethz.ch/R-manual/R-devel/library/base/html/Syntax.html). Ricordiamo che, in caso di dubbi riguardanti l'ordine di esecuzione delle operazioni, la cosa migliore è utilizzare le parentesi tonde `()` per disambiguare ogni possibile fraintendimento. -:::{.warning title="L'operatore '%in%'" data-latex="[L'operatore '\\%in\\%']"} -Nota che l'operatore `%in%` che abbiamo precedentemente indicato tra gli operatori relazionali in realtà è un operatore speciale. In particolare, non segue le stesse regole degli altri operatori relazionlali per quanto riguarda l'ordine di esecuzione. +:::{.warning title="L'operatore \\texttt{%in%}" data-latex="[L'operatore \\texttt{\\%in\\%}]"} +Nota che l'operatore `%in%` che abbiamo precedentemente indicato tra gli operatori relazionali in realtà è un operatore speciale. In particolare, non segue le stesse regole degli altri operatori relazionali per quanto riguarda l'ordine di esecuzione. La soluzione migliore? Usa le parentesi! ::: ### Esercizi {-} -Esegui i seguenti esercizi utilizzando gli operatori relazionali e logici ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-03-first-comands.R)): +Esegui i seguenti esercizi utilizzando gli operatori relazionali e logici ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-03-first-commands.R)): -1. Definisici due relazioni false e due vere che ti permettano di valutare i risultati di tutti i possibili incroci che puoi ottenere con gli operatori logici `&` e `|`. -2. Definisci una proposizione che ti permetta di valutare se un numero è pari. Definisci un'altra proposizione per i nueri dispari (tip: cosa ti ricorda `%%`?). +1. Definisci due relazioni false e due vere che ti permettano di valutare i risultati di tutti i possibili incroci che puoi ottenere con gli operatori logici `&` e `|`. +2. Definisci una proposizione che ti permetta di valutare se un numero è pari. Definisci un'altra proposizione per i numeri dispari (suggerimento: cosa ti ricorda `%%`?). 3. Definisci una proposizione per valutare la seguente condizione (ricordati di testare tutti i possibili scenari) "*x è un numero compreso tra -4 e -2 oppure è un numero compreso tra 2 e 4*". 4. Esegui le seguenti operazioni `4 ^ 3 %in% c(2,3,4)` e `4 * 3 %in% c(2,3,4)`. Cosa osservi nell'ordine di esecuzione degli operatori? diff --git a/05-important-concepts.Rmd b/05-important-concepts.Rmd index 5022b32..9606799 100755 --- a/05-important-concepts.Rmd +++ b/05-important-concepts.Rmd @@ -1,4 +1,4 @@ -# Due Compagni Inseparabili {#objects-functions} +# Due compagni inseparabili {#objects-functions} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -9,9 +9,9 @@ knitr::opts_chunk$set( ``` -In questo capitolo introdurremmo i concetti di oggetti e funzioni, due elementi alla base di R (e di ogni linguaggio di programmazione). Potremmo pensare agli oggetti in R come a delle variabili che ci permettono di mantenere in memoria dei valori (e.g., i risultati dei nostri calcoli o i nostri dati). Le funzioni in R, invece, sono analoghe a delle funzioni matematiche che, ricevuti degli oggetti in input, compiono delle azioni e restituiscono dei nuovi oggetti in output. +In questo capitolo introdurremmo i concetti di oggetti e funzioni, due elementi alla base di R (e di ogni linguaggio di programmazione). Potremmo pensare agli oggetti in R come a delle variabili che ci permettono di mantenere in memoria dei valori (ad es. i risultati dei nostri calcoli o i nostri dati). Le funzioni in R, invece, sono analoghe a delle funzioni matematiche che, ricevuti degli oggetti in input, compiono delle azioni e restituiscono dei nuovi oggetti in output. -Questa è una iper-semplificazione (e pure tecnicamente non corretta) che ci permettere però di capire come, partendo dai nostri dati o valori iniziali, possiamo manipolarli applicando delle funzioni per ottenere, attraverso differenti step, i risultati desiderati (e.g., analisi statistiche o grafici e tabelle). +Questa è una ipersemplificazione (e pure tecnicamente non corretta) che ci permettere però di capire come, partendo dai nostri dati o valori iniziali, possiamo manipolarli applicando delle funzioni per ottenere, attraverso differenti step, i risultati desiderati (ad es. analisi statistiche o grafici e tabelle). Qui valuteremo gli aspetti fondamentali riguardanti l'utilizzo degli oggetti e delle funzioni che saranno successivamente approfonditi rispettivamente nel corso della [Seconda Sezione](#second-section) e della [Terza Sezione](#third-section) del libro. @@ -19,7 +19,7 @@ Qui valuteremo gli aspetti fondamentali riguardanti l'utilizzo degli oggetti e d Quando eseguiamo un commando in R, il risultato ottenuto viene immediatamente mostrato in *Console*. Tale risultato, tuttavia, non viene salvato in memoria e quindi non potrà essere riutilizzato in nessuna operazione futura. Condurre delle analisi in questo modo sarebbe estremamente complicato ed inefficiente. La soluzione più ovvia è quella di salvare in memoria i nostri risultati intermedi per poterli poi riutilizzare nel corso delle nostre analisi. Si definisce questo processo come *assegnare* un valore ad un oggetto. -### Assegnare e Richiamare un oggetto {#assign} +### Assegnare e richiamare un oggetto {#assign} Per assegnare il valore numerico 5 all'oggetto `x` è necessario eseguire il seguente comando: @@ -27,7 +27,7 @@ Per assegnare il valore numerico 5 all'oggetto `x` è necessario eseguire il seg x <- 5 ``` -La funzione `<-` ci permette di assegnare i valori che si trovano alla sua destra all'oggetto il cui nome è definito alla sinistra. Abbiamo pertanto il seguente pattern: ` <- `.Notate come in *Console* appaia solo il comando appena eseguito ma non venga mostrato alcun risultato. +La funzione `<-` ci permette di assegnare i valori che si trovano alla sua destra all'oggetto il cui nome è definito alla sinistra. Abbiamo pertanto il seguente pattern: ` <- `. Notate come in *Console* appaia solo il comando appena eseguito ma non venga mostrato alcun risultato. Per utilizzare il valore contenuto nell'oggetto sarà ora sufficiente richiamare nel proprio codice il nome dell'oggetto desiderato. @@ -35,7 +35,7 @@ Per utilizzare il valore contenuto nell'oggetto sarà ora sufficiente richiamare x + 3 ``` -E' inoltre possibile "aggiornare" o "sostituire" il valore contenuto in un oggetto. Ad esempio: +È inoltre possibile "aggiornare" o "sostituire" il valore contenuto in un oggetto. Ad esempio: ```{r, echo = TRUE} # Aggiornare un valore @@ -49,7 +49,7 @@ x Nel primo caso, abbiamo utilizzato il vecchio valore contenuto in `x` per calcolare il nuovo risultato che è stato assegnato a `x`. Nel secondo caso, abbiamo sostituito il vecchio valore di `x` con un nuovo valore (nell'esempio una stringa di caratteri). -:::{.design title="Assegnare valori '<-' vs '='" data-latex="[Assegnare valori '<-' vs '=']"} +:::{.design title="Assegnare valori, \\texttt{<-} vs \\texttt{=}" data-latex="[Assegnare valori, \\texttt{<-} vs \\texttt{=}]"} Esistono due operatori principali che sono usati per assegnare un valore ad un oggetto: l'operatore `<-` e l'operatore `=`. Entrambi sono validi e spesso la scelta tra i due diventa solo una questione di stile personale. ```{r, echo=TRUE} @@ -59,7 +59,7 @@ x_2 = 45 x_1 == x_2 ``` -Esistono, tuttavia, alcune buone ragioni per preferire l'uso di `<-` rispetto a `=` (attenti a non confonderlo con l'operatore relazionale `==`). L'operazione di assegnazione è un'operazione che implica una direzionalità, il chè è reso esplicito dal simbolo `<-` mentre il simbolo `=` non evidenzia questo aspetto e anzi richiama la relazione di uguaglianza in matematica. +Esistono, tuttavia, alcune buone ragioni per preferire l'uso di `<-` rispetto a `=` (attenti a non confonderlo con l'operatore relazionale `==`). L'operazione di assegnazione è un'operazione che implica una direzionalità, il che è reso esplicito dal simbolo `<-` mentre il simbolo `=` non evidenzia questo aspetto e anzi richiama la relazione di uguaglianza in matematica. La decisione su quale operatore adottare è comunque libera, ma ricorda che una buona norma nella programmazione riguarda la *consistenza*: una volta presa una decisione è bene mantenerla per facilitare la comprensione del codice. ::: @@ -74,10 +74,10 @@ Ci sono alcune regole che discriminano nomi validi da nomi non validi. Il nome d - deve iniziare con una lettera e può contenere lettere, numeri, underscore (`_`), o punti (`.`). - potrebbe anche iniziare con un punto (`.`) ma in tal caso non può essere seguito da un numero. - non deve contenere caratteri speciali come `#`, `&`, `$`, `?`, etc. -- non deve essere una parola riservata ovvero quelle parole che sono utilizzate da R con un significato speciale (e.g, `TRUE`, `FALSE`, etc.; esegui il comando `?reserved` per la lista di tutte le parole riservate in R). +- non deve essere una parola riservata ovvero quelle parole che sono utilizzate da R con un significato speciale (ad es. `TRUE`, `FALSE`, etc.; esegui il comando `?reserved` per la lista di tutte le parole riservate in R). :::{.warning title="CaSe-SeNsItIvE" data-latex="[CaSe-SeNsItIvE]"} -Nota come R sia **Case-Sensitive**, ovvero distingua tra lettere minuscole e maiuscole. Nel seguente esempio i due nomi sono considerate diversi e pertanto non avviene una sovrascrizione ma due differenti oggetti sono creati: +Nota come R sia **Case-Sensitive**, ovvero distingua tra lettere minuscole e maiuscole. Nel seguente esempio i due nomi sono considerati diversi e pertanto non avviene una sovrascrittura ma due differenti oggetti sono creati: ```{r case-sensitive, echo = TRUE} My_name <- "Monty" @@ -91,8 +91,8 @@ my_name Inoltre, il nome ideale di un oggetto dovrebbe essere: -- **auto-descrittivo**: dal solo nome dovrebbe essere possibile intuire il contenuto dell'oggetto. Un nome generico quale `x` o `y` ci sarebbero di poco aiuto poichè potrebbero contenere qualsiasi informazione. Invece un nome come `weight` o `gender` ci suggerirebbe chiaramente il contenuto dell'oggetto (e.g., il peso o il gender dei partecipanti del nostro studio). -- **della giusta lunghezza**: non deve essere ne troppo breve (evitare sigle incomprensibili) ma neppure troppo lunghi. La lunghezza corretta è quella che permette al nome di esssere sufficientemente informativo senza aggiungere inutili dettagli. In genere sono sufficienti 2 o 3 parole. +- **auto-descrittivo**: dal solo nome dovrebbe essere possibile intuire il contenuto dell'oggetto. Un nome generico quale `x` o `y` ci sarebbero di poco aiuto poiché potrebbero contenere qualsiasi informazione. Invece un nome come `weight` o `gender` ci suggerirebbe chiaramente il contenuto dell'oggetto (ad es. il peso o il gender dei partecipanti del nostro studio). +- **della giusta lunghezza**: non deve essere ne troppo breve (evitare sigle incomprensibili) ma neppure troppo lungo. La lunghezza corretta è quella che permette al nome di essere sufficientemente informativo senza aggiungere inutili dettagli. In genere sono sufficienti 2 o 3 parole. :::{.design title="CamelCase vs snake_case" data-latex="[CamelCase vs snake\\_case]"} Spesso più parole sono usate per ottenere un nome sufficientemente chiaro. Dato che però non è possibile includere spazi in un nome, nasce il problema di come unire più parole senza che il nome diventi incomprensibile, ad esempio `mediatestcontrollo`. @@ -100,21 +100,21 @@ Spesso più parole sono usate per ottenere un nome sufficientemente chiaro. Dato Esistono diverse convenzioni tra cui: - **CamelCase**. L'inizio di una nuova parole viene indicata con l'uso della prima lettera maiuscola. Ad esempio `mediaTestControllo`. -- **snake_case**. L'inizio di una nuova parola viene indicata con l'uso carattere `_`. Ad esempio `media_test_controllo`. -- una variante al calssico **snake_case** riguarda l'uso del `.`, ad esempio `media.test.controllo`. Questo approccio in genere è evitato poichè in molti linguaggi di programmazione (ed anche in R in alcune condizioni) il carattere `.` è un carattere speciale. +- **snake_case**. L'inizio di una nuova parola viene indicata con l'uso del carattere `_`. Ad esempio `media_test_controllo`. +- una variante al classico **snake_case** riguarda l'uso del `.`, ad esempio `media.test.controllo`. Questo approccio in genere è evitato poiché in molti linguaggi di programmazione (ed anche in R in alcune condizioni) il carattere `.` è un carattere speciale. In genere viene raccomandato di seguire la convenzione **snake_case**. Tuttavia, la decisione su quale convenzione adottare è libera, ma ricorda ancora che una buona norma nella programmazione riguarda la *consistenza*: una volta presa una decisione è bene mantenerla per facilitare la comprensione del codice. ::: -### Tipologie Dati e Strutture Dati +### Tipologie dati e strutture dati -Per lavorare in modo ottimale in R, è fondamentale conoscere bene e distinuere chiaramente quali sono le tipologie di dati e le strutture degli oggetti usati. +Per lavorare in modo ottimale in R, è fondamentale conoscere bene e distinguere chiaramente quali sono le tipologie di dati e le strutture degli oggetti usati. In R abbiamo 4 principali tipologie di dati, ovvero tipologie di valori che possono essere utilizzati: -- `character` - *Stringhe di caratteri* i cui valori alfannumerici vengono delimitati dalle doppie vigolette `"Hello world!"` o virgolette singole `'Hello world!'`. +- `character` - *Stringhe di caratteri* i cui valori alfanumerici vengono delimitati dalle doppie virgolette `"Hello world!"` o virgolette singole `'Hello world!'`. - `double` - *Valori reali* con o senza cifre decimali ad esempio `27` o `93.46`. - `integer` - *Valori interi* definiti apponendo la lettera `L` al numero desiderato, ad esempio `58L`. - `logical` - *Valori logici* `TRUE` e `FALSE` usati nelle operazioni logiche. @@ -135,7 +135,7 @@ In R abbiamo inoltre differenti tipologie di oggetti, ovvero diverse strutture i Approfondiremo la loro definizione, le loro caratteristiche ed il loro utilizzo nel corso di tutta la [Seconda Sezione](#second-section) di questo libro. -## Funzioni {#functions-def} +## Funzioni {#functions-def} Possiamo pensare alle funzioni in R in modo analogo alle classiche funzioni matematiche. Dati dei valori in input, le funzioni eseguono dei specifici calcoli e restituiscono in output il risultato ottenuto. @@ -144,14 +144,14 @@ Possiamo pensare alle funzioni in R in modo analogo alle classiche funzioni mate

-Abbiamo già incontrato le nostre prime funzioni per eseguire specifiche operazioni matematiche nel Capitolo \@ref(math-operators) come ad esempio `sqrt()` o `abs()` usate per ottenere ripettivamente la radice quadrata o il valore assoluto di un numero. Ovviamente le funzioni in R non sono limitate ai soli calcoli matematici ma possono eseguire qualsiasi genere di compito come ad esempio creare grafici e tabelle o manipolare dei dati o dei file. Tuttavia il concetto rimane lo stesso: ricevuti degli oggetti in input, le funzioni compiono determinate azioni e restituiscono dei nuovi oggetti in output. +Abbiamo già incontrato le nostre prime funzioni per eseguire specifiche operazioni matematiche nel Capitolo \@ref(math-operators) come ad esempio `sqrt()` o `abs()` usate per ottenere rispettivamente la radice quadrata o il valore assoluto di un numero. Ovviamente le funzioni in R non sono limitate ai soli calcoli matematici ma possono eseguire qualsiasi genere di compito come ad esempio creare grafici e tabelle o manipolare dei dati o dei file. Tuttavia il concetto rimane lo stesso: ricevuti degli oggetti in input, le funzioni compiono determinate azioni e restituiscono dei nuovi oggetti in output. -In realtà incontreremo delle funzioni che non richiedono input o non produrre degli output. Ad esempio `getwd()` non richiede input oppure la funzione `rm()` non produce output. Tuttavia questo accade nella minoranza dei casi. +In realtà incontreremo delle funzioni che non richiedono input o non producono output. Ad esempio `getwd()` non richiede input, oppure la funzione `rm()` non produce output. Tuttavia questo accade nella minoranza dei casi. Per eseguire una funzione in R è necessario digitare il nome della funzione ed indicare tra parentesi i valori che vogliamo assegnare agli **argomenti** della funzione, ovvero i nostri input, separati da virgole. Generalmente si utilizza quindi la seguente sintassi:
-`( = , = ,...)` +`( = , = , ...)`
@@ -162,7 +162,7 @@ Ad esempio per creare una sequenza di valori con incrementi di 1 posso usare la seq(from = 0, to = 10) ``` -### Argomenti di una Funzione {#function-arguments} +### Argomenti di una funzione {#function-arguments} Nel definire gli argomenti di una funzione non è necessario specificare il nome degli argomenti. Ad esempio il comando precedente può essere eseguito anche specificando solamente i valori. @@ -171,7 +171,7 @@ Nel definire gli argomenti di una funzione non è necessario specificare il nome seq(0, 10) ``` -Tuttavia, questo rende più difficile la lettura e la comprensione del codice poichè non è chiaro a quali argomenti si riferiscono i valori. L'ordine con cui vengono definiti i valori in questo caso è iportante, poichè R assume rispetti l'ordine prestabilito degli argomenti. Osserva come invertendo invertendo i valori ovviamente otteniamo risultati differenti da quelli precedenti, ma questo non avviene quando il nome dell'argomento è specificato. +Tuttavia, questo rende più difficile la lettura e la comprensione del codice poiché non è chiaro a quali argomenti si riferiscono i valori. L'ordine con cui vengono definiti i valori in questo caso è importante, poiché R assume rispetti l'ordine prestabilito degli argomenti. Osserva come invertendo i valori ovviamente otteniamo risultati differenti da quelli precedenti, ma questo non avviene quando il nome dell'argomento è specificato. ```{r, echo = TRUE} # inverto i valori senza i nomi degli argomenti @@ -183,15 +183,15 @@ seq(to = 10, from = 0) Vediamo inoltre come le funzioni possano avere molteplici argomenti, ma che non sia necessario specificare il valore per ognuno di essi. Molti argomenti, infatti, hanno già dei valori prestabiliti di *default* e non richiedo quindi di essere specificati almeno che ovviamente non si vogliano utilizzare impostazioni diverse da quelle di *default*. Oppure lo specificare un dato argomento rispetto ad un altro può definire il comportamento stesso della funzione. -Ad esempio la funzione `seq()` possiede anche gli argomenti `by` e `length.out` che prima non erano stati specificati. `by` permette di definire l’incremento per ogni elemento successivo della sequenza mentre `length.out` permette di definire il numero di elementi della sequenza. Vediamo come allo specificare dell'uno o dell'altro agromento (o di entrambi) il comportamento della funzione vari. +Ad esempio la funzione `seq()` possiede anche gli argomenti `by` e `length.out` che prima non erano stati specificati. `by` permette di definire l’incremento per ogni elemento successivo della sequenza mentre `length.out` permette di definire il numero di elementi della sequenza. Vediamo come varia allo specificare dell'uno o dell'altro argomento (o di entrambi) il comportamento della funzione. ```{r,echo = TRUE, error=TRUE} -seq(from = 0, to = 10, by = 5) -seq(from = 0, to = 10, length.out = 5) -seq(from = 0, to = 10, length.out = 5, by = 4) +seq(from = 0, to = 10, by = 5) +seq(from = 0, to = 10, length.out = 5) +seq(from = 0, to = 10, length.out = 5, by = 4) ``` -E' pertanto cosigliabile esplicitare sempre gli argomenti di una funzione per rendere chiaro a che cosa si riferiscono i valori indicati. Questo è utlile anche per evitare eventuali comportamenti non voluti delle funzioni ad individuare più facilmente possibili errori. +È pertanto consigliabile esplicitare sempre gli argomenti di una funzione per rendere chiaro a che cosa si riferiscono i valori indicati. Questo è utile anche per evitare eventuali comportamenti non voluti delle funzioni ad individuare più facilmente possibili errori. Gli argomenti di una funzione, inoltre, richiedono specifiche tipologie e strutture di dati e sta a noi assicuraci che i dati siano forniti nel modo corretto. Vediamo ad esempio come la funzione `mean()` che calcola la media di un insieme di valori, richieda come input un vettore di valori numerici. Approfondiremo il concetto di vettori nel Capitolo \@ref(vector), al momento ci basta sapere che possiamo usare la funzione `c()` per combinare più valori in un unico vettore. @@ -202,7 +202,7 @@ mean(c(10, 6, 8, 12)) # c() combina più valori in un unico vettore mean(10, 6, 8, 12) ``` -Notiamo come nel primo caso il risultato sia corretto mentre nel secondo è sbagliato. Questo perchè `mean()` richiede come primo argomento il vettore su cui calcolare la media. Nel primo caso abbiamo correttamente specificato il vettore di valori usando la funzione `c()`. Nel secondo caso invece, il primo argomento risulta essere solo il valore `10` ed R calcola la media di `10` ovvero `10`. Gli altri valori sono passati ad altri argomenti che non alterano il comportameto ma neppure ci segnalano di questo importante errore. +Notiamo come nel primo caso il risultato sia corretto mentre nel secondo è sbagliato. Questo perché `mean()` richiede come primo argomento il vettore su cui calcolare la media. Nel primo caso abbiamo correttamente specificato il vettore di valori usando la funzione `c()`. Nel secondo caso invece, il primo argomento risulta essere solo il valore `10` ed R calcola la media di `10` ovvero `10`. Gli altri valori sono passati ad altri argomenti che non alterano il comportamento ma neppure ci segnalano di questo importante errore. Nel seguente esempio, possiamo vedere come `mean()` richieda che i valori siano numerici. Seppur `"1"` `"2"`, e `"3"` siano dei numeri, l'utilizzo delle doppie virgolette li rende delle stringhe di caratteri e non dei valori numerici e giustamente R non può eseguire una media su dei caratteri. @@ -214,7 +214,7 @@ mean(c("1", "2", "3")) Capiamo quindi che per usare correttamente le funzioni è fondamentale conoscerne gli argomenti e rispettare le tipologie e strutture di dati richieste. -### Help! I need Somebody...Help! {#help} +### Help! I need Somebody... Help! {#help} Conoscere tutte le funzioni e tutti i loro argomenti è impossibile. Per fortuna R ci viene in soccorso fornendoci per ogni funzione la sua documentazione. Qui vengono fornite tutte le informazioni riguardanti la finalità della funzione, la descrizione dei suoi argomenti, i dettagli riguardanti i suoi possibili utilizzi. @@ -234,26 +234,26 @@ knitr::include_graphics("images/help-seq.png") Il formato e le informazioni presenti nella pagina seguono delle norme comuni ma non obbligatorie. Infatti, non necessariamente vengono usati sempre tutti i campi e comunque all'autore delle funzioni è lasciato un certo grado di libertà nel personalizzare la documentazione. Tra i campi principali e più comunemente usati abbiamo: -- **Titile** - Titolo esplicativo della finalità della funzione -- **Description** - Descrizione coincisa della funzione -- **Usage** - Viene mostrata la struttura della funzione con i suoi argomenti e valori di default -- **Arguments** - Elenco con la descrizione dettagliata di tutti gli argomenti. Qui troviamo per ogni argomento sia le opzioni utilizzabili ed il loro effetto, che la tipologia di valori richiesti -- **Details** - Descrizione dettagliata della funzione considerando i casi di utilizzo ed eventuali note tecniche -- **Value** - Descrizione dell'output dalla funzione. Qui troviamo sia la descrizione della struttura dei dati dell'output che la descrizione dei suei elementi utile per interpretare ed utilizzare i rsultati ottenuti -- **See Also** - Eventuali link ad altre funzioni simili o in relazione con la nostra funzione -- **Examples** - Esempi di uso della funzione +- **Title** - Titolo esplicativo della finalità della funzione. +- **Description** - Descrizione coincisa della funzione. +- **Usage** - Viene mostrata la struttura della funzione con i suoi argomenti e valori di default. +- **Arguments** - Elenco con la descrizione dettagliata di tutti gli argomenti. Qui troviamo per ogni argomento sia le opzioni utilizzabili ed il loro effetto, che la tipologia di valori richiesti. +- **Details** - Descrizione dettagliata della funzione considerando i casi di utilizzo ed eventuali note tecniche. +- **Value** - Descrizione dell'output dalla funzione. Qui troviamo sia la descrizione della struttura dei dati dell'output che la descrizione dei suoi elementi utile per interpretare ed utilizzare i risultati ottenuti. +- **See Also** - Eventuali link ad altre funzioni simili o in relazione con la nostra funzione. +- **Examples** - Esempi di uso della funzione. -#### Ricerca per Parola {-} +#### Ricerca per parola {-} Quando non si conosce esattamente il nome di una funzione o si vuole cercare tutte le funzioni e pagine che includono una certa parola, è possibile utilizzare il comando `??` oppure `help.search()`. -R eseguirà una ricerca tra tutta la documentazione disponibile è fornirà un elenco delle pagine che contengono la parola desiderata nel titolo o tra le keywords. +R eseguirà una ricerca tra tutta la documentazione disponibile e fornirà un elenco delle pagine che contengono la parola desiderata nel titolo o tra le keywords. -:::{.trick title="Autocompletamento with 'Tab'" data-latex="[Autocompletamento with 'Tab']"} -La natura dei programmatori è essere pigri e smemorati. Per fortuna ogni *code editor* che si rispetti (i.e., programma per la scrittura di codici) possiede delle utli funzioni di autocompletamento e suggerimento dei comandi che semplificano la scrittura di codici. +:::{.trick title="Autocompletamento con \\texttt{Tab}" data-latex="[Autocompletamento con \\texttt{Tab}]"} +La natura dei programmatori è essere pigri e smemorati. Per fortuna ogni *code editor* che si rispetti (i.e., programma per la scrittura di codici) possiede delle utili funzioni di autocompletamento e suggerimento dei comandi che semplificano la scrittura di codici. -In Rstudio, i suggerimenti compaino automaticamente durante la scrittura di un comando oppure possono essere richiamati premendo il tasto `Tab` in alto a sinistra della tastiera ( ![](images/Tab.png){ width=5% } ). Comparirà una finestra con possibili soluzioni di autocompletamento del nome della funzione. Utilizzando le frecce della tastiera possiamo evidenziare lq funzione voluta e premere `Invio` per autocompletare il comando. Nota come accanto al nome della funzione appare anche un piccolo riquadro giallo con la descrizione della funzione. +In RStudio, i suggerimenti compaiono automaticamente durante la scrittura di un comando oppure possono essere richiamati premendo il tasto `Tab` in alto a sinistra della tastiera ( ![](images/Tab.png){ width=5% } ). Comparirà una finestra con possibili soluzioni di autocompletamento del nome della funzione. Utilizzando le frecce della tastiera possiamo evidenziare la funzione desiderata e premere `Invio` per autocompletare il comando. Nota come accanto al nome della funzione appare anche un piccolo riquadro giallo con la descrizione della funzione.
![](images/autocomplete-function.png){ width=95% } diff --git a/06-working-environment.Rmd b/06-working-environment.Rmd index ca3e797..2cf8bd2 100755 --- a/06-working-environment.Rmd +++ b/06-working-environment.Rmd @@ -1,4 +1,4 @@ -# Ambiente di Lavoro {#working-environment} +# Ambiente di lavoro {#working-environment} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -8,19 +8,19 @@ knitr::opts_chunk$set( ) ``` -In queso capitolo introdurremo alcuni concetti molto importanti che riguardano l'ambiente di lavoro in R o RStudio. In particolare parleremo dell'*environment*, della *working directory* e dell'utilizzo dei pacchetti. +In questo capitolo introdurremo alcuni concetti molto importanti che riguardano l'ambiente di lavoro in R o RStudio. In particolare parleremo dell'*Environment*, della *working directory* e dell'utilizzo dei pacchetti. ## Environment {#environment} Nel Capitolo \@ref(objects-section), abbiamo visto come sia possibile assegnare dei valori a degli oggetti. Questi oggetti vengono creati nel nostro ambiente di lavoro (o meglio *Environment*) e potranno essere utilizzati in seguito. -Il nostro Enviroment raccoglie quindi tutti gli oggetti che vengono creati durante la nostra sessione di lavoro. E' possibile valutare gli oggetti attualmente presenti osservando il pannello *Environment* in alto a destra (vedi Figura \@ref(fig:environment2)) oppure utilizzadno il comando `ls()`, ovvero *list objects*. +Il nostro Environment raccoglie quindi tutti gli oggetti che vengono creati durante la nostra sessione di lavoro. È possibile valutare gli oggetti attualmente presenti osservando il pannello *Environment* in alto a destra (vedi Figura \@ref(fig:environment2)) oppure utilizzando il comando `ls()`, ovvero *list objects*. ```{r environment2, fig.cap="*Environment* - Elenco degli oggetti e variabili presenti nel'ambiente di lavoro", out.width="60%"} knitr::include_graphics("images/environment.png") ``` -All'inizio della sessione di lavoro il nostro Environment sarà vuoto (vedi Figura \@ref(fig:environment-empty)). Il comando `ls()` non restituirà alcun oggeto ma per indicare l'assenza di oggerri userà la risposta `character(0)`, ovvero un vettore di tipo caratteri di lunghezza zero (vedi Capitolo \@ref(vector)). +All'inizio della sessione di lavoro il nostro Environment sarà vuoto (vedi Figura \@ref(fig:environment-empty)). Il comando `ls()` non restituirà alcun oggetto ma per indicare l'assenza di oggetti userà la risposta `character(0)`, ovvero un vettore di tipo caratteri di lunghezza zero (vedi Capitolo \@ref(vector)). ```{r environment-empty, fig.cap="*Environment* vuoto ad inizio sessione di lavoro", out.width="60%"} knitr::include_graphics("images/environment-empty.png") @@ -31,29 +31,29 @@ knitr::include_graphics("images/environment-empty.png") ls() ``` -### Aggiungere Oggetti all'Environment +### Aggiungere oggetti all'Environment -Una volta creati degli oggetti, questi saranno presenti nel nostro Environment e il comando `ls()` restituirà un vettore di caretteri in cui vengono elencati tutti i loro nomi. +Una volta creati degli oggetti, questi saranno presenti nel nostro Environment e il comando `ls()` restituirà un vettore di caratteri in cui vengono elencati tutti i loro nomi. ```{r, echo = TRUE} # Creo oggetti -x <- c(2,4,6,8) -y <- 27 +x <- c(2,4,6,8) +y <- 27 word <- "Hello Word!" # Lista nomi oggetti nell'Environment ls() ``` -Nel pannello in alto a destra (vedi Figura \@ref(fig:environment-object)), possiamo trovare un elenco degli oggetti attualmente presenti nel nostro Environment. Insieme al nome vengono riportate anche alcune utili inforamzioni a seconda del tipo di oggetto. Vediamo come nel nostro esempio, nel caso di variabili con un singolo valore (e.g., `word` e `y`) venganno presentati direttamente gli stessi valori. Mentre, nel caso di vettori (e.g., `x`) vengano fornite anche informazioni riguardanti la tipologia di vettore e la sua dimensione (vedi Capitolo \@ref(vector)), nell'esempio abbiimao un vettore numerico (`num`) di 4 elementi (`[1:4]`). +Nel pannello in alto a destra (vedi Figura \@ref(fig:environment-object)), possiamo trovare un elenco degli oggetti attualmente presenti nel nostro Environment. Insieme al nome vengono riportate anche alcune utili informazioni a seconda del tipo di oggetto. Vediamo come nel nostro esempio, nel caso di variabili con un singolo valore (ad es. `word` e `y`) vengano presentati direttamente gli stessi valori. Mentre, nel caso di vettori (ad es. `x`) vengano fornite anche informazioni riguardanti la tipologia di vettore e la sua dimensione (vedi Capitolo \@ref(vector)), nell'esempio abbiamo un vettore numerico (`num`) di 4 elementi (`[1:4]`). ```{r environment-object, fig.cap="*Environment* contenente gli oggetti creati", out.width="60%"} knitr::include_graphics("images/environment-objects.png") ``` -### Rimuovere Oggetti dall'Environment +### Rimuovere oggetti dall'Environment -Per rimuovere un oggetto dal proprio environment è possibile utilizzare il comando `remove()` oppure la sua abbreviazione `rm()`, indicando tra parentesi il nome dell'oggetto che si intende rimuovere. E' possibile indicare più di un oggetto separando i loro nomi con la virgola. +Per rimuovere un oggetto dal proprio Environment è possibile utilizzare il comando `remove()` oppure la sua abbreviazione `rm()`, indicando tra parentesi il nome dell'oggetto che si intende rimuovere. È possibile indicare più di un oggetto separando i loro nomi con la virgola. ```{r, echo = TRUE} # Rimuovo un oggetto @@ -65,35 +65,37 @@ rm(x,y) ls() ``` -:::{.trick title="rm(list=ls())" data-latex="[rm(list=ls())]"} -Qualora fosse necessario eliminare tutti gli oggetti attualmete presenti nel nosto ambiente di lavoro è possibile ricorrere alla formula `rm(list=ls())`. In questo modo si avrà la certezza di pulire l'ambiente da ogni oggetto e di ripristinarlo alle condizioni iniziali della sessione. +:::{.trick title="\\texttt{rm(list=ls())}" data-latex="[\\texttt{rm(list=ls())}]"} +Qualora fosse necessario eliminare tutti gli oggetti attualmente presenti nel nostro ambiente di lavoro è possibile ricorrere alla formula `rm(list=ls())`. In questo modo si avrà la certezza di pulire l'ambiente da ogni oggetto e di ripristinarlo alle condizioni iniziali della sessione. ::: -:::{.design title="Mantenere Ordinato l'Environment" data-latex="[Mantenere Ordinato l'Environment]"} -Avere cura di mantenre il proprio Environment ordinato ed essere consapevoli degli oggetti attualmente presenti è importante. Questo ci permette di evitare di compiere due errori comuni. +:::{.design title="Mantenere ordinato l'Environment" data-latex="[Mantenere ordinato l'Environment]"} +Avere cura di mantenere il proprio Environment ordinato ed essere consapevoli degli oggetti attualmente presenti è importante. Questo ci permette di evitare di compiere due errori comuni. -- **Utilizzare oggetti non ancora creati**. In questo caso l'errore è facilemente individuabile dat che sarà lo stesso R ad avvisarci che *"object '' not found"*. In questo caso dovremmo semplicemente eseguire il comando per creare l'oggetto richieto. +- **Utilizzare oggetti non ancora creati**. In questo caso l'errore è facilmente individuabile dato che sarà lo stesso R ad avvisarci che `object '' not found`. In questo caso dovremmo semplicemente eseguire il comando per creare l'oggetto richiesto. ```{r, echo = TRUE, error=TRUE} oggetto_non_esistente ``` -- **Utilizzare oggetti con "*vecchi*" valori**. Se non si ha cura di mantenere ordinato il proprio ambiente di lavoro potrebbe accadere che diversi oggetti vengano creati durante successive sessioni di lavoro. A questo punto si corre il rischio di perdere il controllo rispetto al vero contenuto degli oggetti e potremmo quindi utilizzare degli oggetti pensando che contengano un certo valore, quando invece si riferisono a tutt'altro. Questo comporta che qualsiasi nostro risultato perda di significato. Bisogna prestare molta attenzione perchè R non potrà avvisarci di questo errore (per lui sono solo numeri), siamo noi che dobbiamo essere consapevoli del fatto che i comandi eseguiti abbiano senso oppure no. +- **Utilizzare oggetti con "*vecchi*" valori**. Se non si ha cura di mantenere ordinato il proprio ambiente di lavoro potrebbe accadere che diversi oggetti vengano creati durante successive sessioni di lavoro. A questo punto si corre il rischio di perdere il controllo rispetto al vero contenuto degli oggetti e potremmo quindi utilizzare degli oggetti pensando che contengano un certo valore, quando invece si riferiscono a tutt'altro. Questo comporta che qualsiasi nostro risultato perda di significato. Bisogna prestare molta attenzione perché R non potrà avvisarci di questo errore (per lui sono solo numeri), siamo noi che dobbiamo essere consapevoli del fatto che i comandi eseguiti abbiano senso oppure no. -Per mantere un Environmet ordinato vi consigliamo innanzitutto di non salvare automaticamente il vostro *workspace* quando terminate una sessione di lavoro. E' possibile settare tale opzione nelle impostazioni generali di R selezionando *"Never"* alla voce *"save workspace to .RData on exit"* come riportato nella Figura seguente. +Per mantenere un Environment ordinato vi consigliamo innanzitutto di non salvare automaticamente il vostro *workspace* quando terminate una sessione di lavoro. È possibile settare tale opzione nelle impostazioni generali di R selezionando *"Never"* alla voce *"save workspace to .RData on exit"* come riportato nella Figura seguente.
![](images/save-rdata.png){ width=75%}
-Questo vi permetterà di iniziare ogni nuova sessione di lavoro in un Environment vuoto, evitando che vecchi oggetti si accumulino nel corso delle diverse sesssioni di lavoro. Durante le vostre sessioni, inoltre, sarà utile eseguire il comando `rm(list=ls())` quando inizierete un nuovo compito in modo da eliminare tutti i vecchi oggetti. +Questo vi permetterà di iniziare ogni nuova sessione di lavoro in un Environment vuoto, evitando che vecchi oggetti si accumulino nel corso delle diverse sessioni di lavoro. Durante le vostre sessioni, inoltre, sarà utile eseguire il comando `rm(list=ls())` quando inizierete un nuovo compito in modo da eliminare tutti i vecchi oggetti. -#### Environment una Memoria a Breve Termine {-} +#### Environment: una memoria a breve termine {-} -Notiamo quindi come l'Environment sia qualcosa di transitorio. Gli oggetti vengono salvati nella memoria primaria del computer (RAM, possiamo pensarla in modo analogo alla memoria a breve termine dei modelli cognitivi) e verranno cancellati al comando `rm(list=ls())` o al termine di ogni sessione di lavoro. +Notiamo quindi come l'Environment sia qualcosa di transitorio. Gli oggetti vengono salvati nella memoria primaria del computer (RAM, possiamo pensarla in modo analogo alla memoria a breve termine dei modelli cognitivi) e verranno cancellati al comando `rm(list=ls())` o al termine di ogni sessione di lavoro. -Il fatto di partire ogni volta da un Environment vuoto, vi costringerà a raccogliere tutti i passi delle vostre analisi all'interno di uno script in modo ordinato evitando di fare affidamento su vecchi oggetti. Tutti gli oggetti necessari durante le analisi, infattii, dovranno essere ricreati ad ogni sessione, garantendo la riproducibilità e correttezza del lavro (almeno dal punto di vista di programmazione). Idealmente dovrebbe essere posibile, in una sessione di lavoro, partire da un Environment vuoto ed eseguire in ordine tutti i comandi contenuti in uno script fino ad ottenere i risultati desiderati. +Il fatto di partire ogni volta da un Environment vuoto, vi costringerà a raccogliere tutti i passi delle vostre analisi all'interno di uno script in modo ordinato evitando di fare affidamento su vecchi oggetti. Tutti gli oggetti necessari durante le analisi, infatti, dovranno essere ricreati ad ogni sessione, garantendo la riproducibilità e correttezza del lavoro (almeno dal punto di vista di programmazione). Idealmente dovrebbe essere possibile, in una sessione di lavoro, partire da un Environment vuoto ed eseguire in ordine tutti i comandi contenuti in uno script fino ad ottenere i risultati desiderati. -E' facile intuire come in certe situazioni questa non sia la soluzione più efficiente. Alcuni comandi, infatti, potrebbero richiedere molti minuti (o anche giorni) per essere eseguiti. In questi casi sarebbe conveniente, pertanto, salvare i risultati ottenuti per poterli utilizzare anche in sessioni successive, senza la necessità di dover eseguire nuovamente tutti i comadi. Vedremo nel Capitolo TODO come sarà possibile salvare permanentemente gli oggetti creati nella memoria secondaria del computer (hard-disk, nella nostra analogia la memoria a lungo termine) e come caricarli in una successiva sessione di lavoro. +È facile intuire come in certe situazioni questa non sia la soluzione più efficiente. Alcuni comandi, infatti, potrebbero richiedere molti minuti (o anche giorni) per essere eseguiti. In questi casi sarebbe conveniente, pertanto, salvare i risultati ottenuti per poterli utilizzare anche in sessioni successive, senza la necessità di dover eseguire nuovamente tutti i comandi. + +È possibile salvare permanentemente gli oggetti dell'Environment nella memoria secondaria del computer (hard-disk, nella nostra analogia la memoria a lungo termine) e caricarli in una successiva sessione di lavoro. Per salvarli è sufficiente cliccare sull'icona del floppy posta in alto a sinistra nella finestra dell'environment. Per ricaricarli bisogna invece cliccare sull'icona che rappresenta una cartella aperta con una freccia verde. ::: @@ -101,13 +103,13 @@ E' facile intuire come in certe situazioni questa non sia la soluzione più effi Il concetto di *working directory* è molto importante ma spesso poco conosciuto. La *working directory* è la posizione all'interno del computer in cui ci troviamo durante la nostra sessione di lavoro e da cui eseguiamo i nostri comandi. -### Organizzazione Computer +### Organizzazione computer L'idea intuitiva che abbiamo comunemente del funzionamento del computer è fuorviante. Spesso si pensa che il Desktop rispecchi l'organizzazione del nostro intero computer e che tutte le azioni siano gestite attraverso l'interfaccia punta-e-clicca a cui ormai siamo abituati dai moderni sistemi operativi. -Senza entrare nel dettaglio, è più corretto pensare all'organizzazione del cumputer come ad un insieme di cartelle e sottocartelle che contengono tutti i nostri file e al funzionamento del computer come ad un insieme di processi (o comandi) che vengono eseguiti. Gli stessi programmi che installiamo non sono altro che delle cartelle in cui sono contenuti tutti gli script che determinano il loro funzionamento. Anche il Desktop non è altro che una semplice cartella mentre quello che vediamo noi è un programma definito dal sistema operativo che visualizza il contenuto di quella cartella sul nostro schermo e ci permette di interfacciarci con il mouse. +Senza entrare nel dettaglio, è più corretto pensare all'organizzazione del computer come ad un insieme di cartelle e sottocartelle che contengono tutti i nostri file e al funzionamento del computer come ad un insieme di processi (o comandi) che vengono eseguiti. Gli stessi programmi che installiamo non sono altro che delle cartelle in cui sono contenuti tutti gli script che determinano il loro funzionamento. Anche il Desktop non è altro che una semplice cartella mentre quello che vediamo noi è un programma definito dal sistema operativo che visualizza il contenuto di quella cartella sul nostro schermo e ci permette di interfacciarci con il mouse. -Tutto quello che è presente nel nostro computer, compresi i nostri file, i programmi e lo stesso sistema operativo in uso, tutto è organizzato in un articolato sistema di cartelle e sottocartelle. Approsimativamente possiamo pensare all'organizzazione del nostro computer in modo simile alla Figura \@ref(fig:file-system) (da: ). +Tutto quello che è presente nel nostro computer, compresi i nostri file, i programmi e lo stesso sistema operativo in uso, tutto è organizzato in un articolato sistema di cartelle e sottocartelle. Approssimativamente possiamo pensare all'organizzazione del nostro computer in modo simile alla Figura \@ref(fig:file-system) (da: ). ```{r, file-system, fig.cap="Organizzazione Computer (da Wikipedia vedi link nel testo)", out.width="35%"} knitr::include_graphics("images/File-System.png") @@ -115,17 +117,17 @@ knitr::include_graphics("images/File-System.png") Ai livelli più bassi troviamo tutti i file di sistema ai quali gli utenti possono accedere solo con speciali autorizzazioni. Al livello superiore troviamo tutte i file riguardanti i programmi e applicazioni installati che in genere sono utilizzabili da più utenti sullo stesso computer. Infine troviamo tutte le cartelle e file che riguardano lo specifico utente. -### Absolute Path e Relative Path +### Absolute Path e Relative Path -Questo ampio preambolo riguardante l'organizzazione in cartelle e sottocartelle, ci serve perchè è la struttura che il computer utilizza per orientarsi tra tutti file quando esegue dei comandi attraverso un'interfaccia a riga di comando (e.g., R). Se vogliamo ad esempio caricare dei dati da uno specifico file in R devo fornire il *path* (o indirizzo) corretto che mi indichi esattamente la posizione del file all'interno della struttura di cartelle del computer. Ad esempio, immaginiamo di avere dei dati `My-data.Rda` salvato nella cartella `Introduction2R` nel proprio Desktop. +Questo ampio preambolo riguardante l'organizzazione in cartelle e sottocartelle, ci serve perché è la struttura che il computer utilizza per orientarsi tra tutti file quando esegue dei comandi attraverso un'interfaccia a riga di comando (ad es. R). Se vogliamo ad esempio caricare dei dati da uno specifico file in R devo fornire il *path* (o indirizzo) corretto che mi indichi esattamente la posizione del file all'interno della struttura di cartelle del computer. Ad esempio, immaginiamo di avere dei dati `My-data.Rda` salvato nella cartella `Introduction2R` nel proprio Desktop. ``` Desktop/ | - |- Introduction2R/ - | | - | |- Dati/ - | | |- My-data.Rda + |- Introduction2R/ + | | + | |- Dati/ + | | |- My-data.Rda ``` Per indicare la posizione del File potrei utilizzare un: @@ -136,7 +138,7 @@ Per indicare la posizione del File potrei utilizzare un: "/Users//Desktop/Introduction2R/Dati/My-data.Rda" # Windows Vista -"c:\Users\\Desktop\Introduction2R\Dati\My-data.Rda" +"C:\Users\\Desktop\Introduction2R\Dati\My-data.Rda" ``` @@ -150,18 +152,18 @@ Per indicare la posizione del File potrei utilizzare un: ``` -Nota come sia preferibile l'utilizzo dei relative path poichè gli absolute path sono unici per il singolo computer di riferimento e non possono essere quindi utilizzati su altri computer. +Nota come sia preferibile l'utilizzo dei relative path poiché gli absolute path sono unici per il singolo computer di riferimento e non possono essere quindi utilizzati su altri computer. -:::{.warning title='"Error: No such file or directory"' data-latex='["Error: No such file or directory"]'} -Qualora si utilizzasse un relative path per indicare la posizione di un file, è importante che la working directory attualment in uso sia effettivamente quella prevista. Se ci trovassimo in una divesa cartella, ovviamente il "relative path" indicato non sarebbe più valido e R ci mostrerebbe un messaggio di errore. +:::{.warning title='\\texttt{Error: No such file or directory}' data-latex='[\\texttt{Error: No such file or directory}]'} +Qualora si utilizzasse un relative path per indicare la posizione di un file, è importante che la working directory attualmente in uso sia effettivamente quella prevista. Se ci trovassimo in una diversa cartella, ovviamente il "relative path" indicato non sarebbe più valido e R ci mostrerebbe un messaggio di errore. -Riprendendo l'esempio precedente, supponiamo che la nostra attuale working directory sia `Desktop` invece di `Desktop/Introduction2R`. Eseguendo il comadno `load()` per caricare i dati utilizzando il relative path ora non più valido ottengo: +Riprendendo l'esempio precedente, supponiamo che la nostra attuale working directory sia `Desktop` invece di `Desktop/Introduction2R`. Eseguendo il comando `load()` per caricare i dati utilizzando il relative path ora non più valido ottengo: ```{r, echo = TRUE, error = TRUE} load("Dati/My-data.Rda") ``` -Il messaggio di errore mi indica che R non è stato in grado di trovare il file seguendo le mie indicazioni. E' come se chiedessi al computer di aprire il frigo ma attualmente si trovasse in camera, devo prima dargli le indicazioni per raggiungere la cucina altrimenti mi risponderebbe *"frigo non trovato"*. Risulta pertanto fondamentale essere sempre consapevoli di quale sia l'attuale working directory in cui si sta svolgendo la sessione di lavoro. +Il messaggio di errore mi indica che R non è stato in grado di trovare il file seguendo le mie indicazioni. È come se chiedessi al computer di aprire il frigo ma attualmente si trovasse in camera, devo prima dargli le indicazioni per raggiungere la cucina altrimenti mi risponderebbe *"frigo non trovato"*. Risulta pertanto fondamentale essere sempre consapevoli di quale sia l'attuale working directory in cui si sta svolgendo la sessione di lavoro. Ovviamente otterrei lo stesso errore anche usando un absolute path se questo contenesse degli errori. ::: @@ -169,7 +171,7 @@ Ovviamente otterrei lo stesso errore anche usando un absolute path se questo con :::{.design title="The Garden of Forking Paths" data-latex="[The Garden of Forking Paths]"} Come avrai notato dagli esempi precedenti, sia la struttura in cui vengono organizzati i file nel computer sia la sintassi utilizzata per indicare i path è differente in base al sistema operativo utilizzato. -#### Mac OS e Linux{-} +#### Mac OS e Linux {-} - Il carattere utilizzato per separare le cartelle nella definizione del path è `"/"`: ```{r, echo=TRUE, eval=FALSE} @@ -200,7 +202,7 @@ Come avrai notato dagli esempi precedenti, sia la struttura in cui vengono organ Vediamo ora i comandi utilizzati in R per valutare e cambiare la working directory nella propria sessione di lavoro. :::{.tip title='One "/" to Rule Them All' data-latex='[One "/" to Rule Them All]'} -Nota negli esempi successivi, come in R il caratere `"/"` sia sempre utilizzato per separare le cartelle nella definizione del path indipendentemente dal sistema operativo. +Nota negli esempi successivi, come in R il carattere `"/"` sia sempre utilizzato per separare le cartelle nella definizione del path indipendentemente dal sistema operativo. ::: #### Attuale Working Directory {-} @@ -212,15 +214,15 @@ getwd() ## [1] "/Users//Desktop/Introduction2R" ``` -In alternativa, l'attuale working directory è anche riportata in alto a sinistra della Console come mostrato in Figura \@ref(fig:current-wd). +In alternativa, l'attuale working directory è anche riportata in alto a sinistra della *Console* come mostrato in Figura \@ref(fig:current-wd). -```{r, current-wd, fig.cap="Workig directory dell'attuale sessione di lavoro", out.width="95%"} +```{r, current-wd, fig.cap="Working directory dell'attuale sessione di lavoro", out.width="95%"} knitr::include_graphics("images/current-wd.png") ``` -Premendo la freccia al suo fianco il pannello *Files* in basso a destra sarà reindirizzato direttamento alla workig directory dell'attuale sessione di lavoro. In questo modo sarà facile navigare tra i file e cartelle presenti al suo interno (vedi Figura \@ref(fig:current-folder)). +Premendo la freccia al suo fianco il pannello *Files* in basso a destra sarà reindirizzato direttamente alla working directory dell'attuale sessione di lavoro. In questo modo sarà facile navigare tra i file e cartelle presenti al suo interno (vedi Figura \@ref(fig:current-folder)). -```{r, current-folder, fig.cap="Workig directory dell'attuale sessione di lavoro", out.width="65%"} +```{r, current-folder, fig.cap="Working directory dell'attuale sessione di lavoro", out.width="65%"} knitr::include_graphics("images/current-folder.png") ``` @@ -252,7 +254,7 @@ Nota come sia possibile nel digitare il path sfruttare l'autocompletamento. All'

-E' possibile inoltre utilizzare i caratteri speciali `"./"` e `"../"` per indicare rispettivamente l'attuale working directory e la cartella del livello superiore (i.e., *parent folder*) che include l'attuale working directory. `"../"` ci permette quindi di navigare a ritroso dalla nostra attuale posizione tra le cartelle del computer. +È possibile inoltre utilizzare i caratteri speciali `"./"` e `"../"` per indicare rispettivamente l'attuale working directory e la cartella del livello superiore (i.e., *parent folder*) che include l'attuale working directory. `"../"` ci permette quindi di navigare a ritroso dalla nostra attuale posizione tra le cartelle del computer. ```{r, echo=TRUE, eval=FALSE} getwd() @@ -266,21 +268,21 @@ getwd() ::: -## R-packages {#packages} +## R Packages {#packages} -Uno dei grandi punti di forza di R è quella di poter estendere le proprie funzioni di base in modo semplice ed intuitivo utilizzando nuovi pacchetti. Al momento esistono oltre **17'000** pachetti disponibili gratuitamente sul CRAN (la repository ufficiale di R). Questi pacchetti sono stati sviluppati dall'immensa comunity di R per svolgere ogni sorta di compito. Si potrebbe dire quindi che in R ogni cosa sia possibile, basta trovare il giusto pacchetto (oppure crearlo!). +Uno dei grandi punti di forza di R è quella di poter estendere le proprie funzioni di base in modo semplice ed intuitivo utilizzando nuovi pacchetti. Al momento esistono oltre **17'000** pacchetti disponibili gratuitamente sul CRAN (la repository ufficiale di R). Questi pacchetti sono stati sviluppati dall'immensa community di R per svolgere ogni sorta di compito. Si potrebbe dire quindi che in R ogni cosa sia possibile, basta trovare il giusto pacchetto (oppure crearlo!). -Quando abbiamo installato R in automatico sono stati installati una serie di pacchetti che costituiscono la **system library**, ovvero tutti quei pacchetti di base che permettono il fuzionamento di R. Tuttavia, gli altri pacchetti non sono disponibili da subito. Per utilizzare le funzioni di altri pacchetti, è necessario seguire una procedura in due step come rappresentato in Figura \@ref(fig:packages-process): +Quando abbiamo installato R in automatico sono stati installati una serie di pacchetti che costituiscono la **system library**, ovvero tutti quei pacchetti di base che permettono il funzionamento di R. Tuttavia, gli altri pacchetti non sono disponibili da subito. Per utilizzare le funzioni di altri pacchetti, è necessario seguire una procedura in due step come rappresentato in Figura \@ref(fig:packages-process): -1. **Scaricare ed installare i pacchetti sul nostro computer**. I pacchetti sono disponibili gratuitamente online nella reopsitory del CRAN, una sorta di archivio. Vengono quindi scaricati ed installati nella nostra *library*, ovvero la raccolta di tutti i pacchetti di R disponibili sul nostro computer. +1. **Scaricare ed installare i pacchetti sul nostro computer**. I pacchetti sono disponibili gratuitamente online nella repository del CRAN, una sorta di archivio. Vengono quindi scaricati ed installati nella nostra *library*, ovvero la raccolta di tutti i pacchetti di R disponibili sul nostro computer. -2. **Caricare il paccheto nella sessione di lavoro**. Anche se il paccheto è installato nella nostra library non siamo ancora pronti per utilizzare le sue funzioni. Sarà necessario prima caricare il pacchetto nella nostra sessione di lavoro. Solo ora le funzionni del pacchetto saranno effetivamente disponibili per essere usate. +2. **Caricare il pacchetto nella sessione di lavoro**. Anche se il pacchetto è installato nella nostra library non siamo ancora pronti per utilizzare le sue funzioni. Sarà necessario prima caricare il pacchetto nella nostra sessione di lavoro. Solo ora le funzioni del pacchetto saranno effettivamente disponibili per essere usate. -```{r, packages-process, fig.cap="Utilizzare i paccheti in R", out.width="95%"} +```{r, packages-process, fig.cap="Utilizzare i pacchetti in R", out.width="95%"} knitr::include_graphics("images/packages-process.png") ``` -Questo procedimento in due step potrebbe sembrare poco intuitivo. *"Perchè dover caricare qualcosa che è già installato?"* La risposta è molto semplice ci serve per mantenere efficiente e sotto controllo la nostra sessione di lavoro. Infatti non avremo mai bisogno di tutti i pacchetti installati ma a seconda dei compiti da eseguire utilizzeremo di volta in volta solo alcuni pacchetti specifici. Se tutti i pacchetti fossero caricati automaticamente ogni volta sarebbe un inutile spreco di memoria e si creerebbero facilmente dei conflitti. Ovvero, alcune funzioni di diversi pacchetti potrebbero avere lo stesso nome ma scopi diversi. Sarebbe quindi molto facile ottenere errori o comunque risultati non validi. +Questo procedimento in due step potrebbe sembrare poco intuitivo. *"Perché dover caricare qualcosa che è già installato?"* La risposta è molto semplice ci serve per mantenere efficiente e sotto controllo la nostra sessione di lavoro. Infatti non avremo mai bisogno di tutti i pacchetti installati ma a seconda dei compiti da eseguire utilizzeremo di volta in volta solo alcuni pacchetti specifici. Se tutti i pacchetti fossero caricati automaticamente ogni volta sarebbe un inutile spreco di memoria e si creerebbero facilmente dei conflitti. Ovvero, alcune funzioni di diversi pacchetti potrebbero avere lo stesso nome ma scopi diversi. Sarebbe quindi molto facile ottenere errori o comunque risultati non validi. Vediamo ora come eseguire queste operazioni in R. @@ -290,19 +292,19 @@ Per installare dei pacchetti dal CRAN nella nostra library è possibile eseguire ```{r, echo = TRUE, eval=FALSE} # Un ottimo pacchetto per le analisi statistiche di John Fox -# un grandissimo statistico...per gli amici Jonny la volpe ;) +# un grandissimo statistico...per gli amici Johnny la volpe ;) install.packages("car") ``` In alternativa è possibile utilizzare il pulsante *"Install"* nella barra in alto a sinistra del pannello Packages ( vedi Figura \@ref(fig:packages-install)), indicando successivamente il nome del pacchetto desiderato. -```{r, packages-install, fig.cap="Installare paccektti tramite interfacci RStudio", out.width="65%"} +```{r, packages-install, fig.cap="Installare pacchetti tramite interfacci RStudio", out.width="65%"} knitr::include_graphics("images/packages-install.png") ``` -Nota come installare un pacchetto potrebbe comportare l'installazione di più pacchetti. Questo perchè verranno automaticamente installate anche le *dependencies* del pacchetto, ovverro, tutti i pacchetti usati internamente dal pacchetto di interesse che quindi necessari per il suo corretto funzionaemnto (come in un gioco di matrioske). +Nota come installare un pacchetto potrebbe comportare l'installazione di più pacchetti. Questo perché verranno automaticamente installate anche le *dependencies* del pacchetto, ovvero, tutti i pacchetti usati internamente dal pacchetto di interesse che quindi necessari per il suo corretto funzionamento (come in un gioco di matriosche). -Una volta installato il pacchetto, questo comarirà nella library ovvero la lista dei pacchetti disponibili mostrata nel pannello Packages (vedi Figura \@ref(fig:library-car)). +Una volta installato il pacchetto, questo comparirà nella library ovvero la lista dei pacchetti disponibili mostrata nel pannello Packages (vedi Figura \@ref(fig:library-car)). ```{r, library-car, fig.cap="Il pacchetto car è ora disponibile nella library", out.width="65%"} knitr::include_graphics("images/library-car.png") @@ -319,22 +321,22 @@ devtools 1.13.4 2.0.1 FALSE Do you want to install from sources the packages which need compilation? ``` -In breve, la risposta da dare è **NO** (`"n"`). Ma che cosa ci sta effetivamente chiedendo R? Esistono diversi modi in cui un pacchetto è disponibile, tra i principali abbiamo: +In breve, la risposta da dare è **NO** (`"n"`). Ma che cosa ci sta effettivamente chiedendo R? Esistono diversi modi in cui un pacchetto è disponibile, tra i principali abbiamo: - **Versione Binary** - pronta all'uso e semplice da installare - **Versione Source** - richiede una particolare procedura per essere installata detta compilazione -In genere quindi, è sempre preferibile installare la versione *Binary*. Tuttavia, in questo caso R ci avverte che, per alcuni pacchetti, gli aggiornameni più recenti sono disponibili solo nella versione *Source* e ci chiede quindi se installarli attraverso la procedura di compilazione. +In genere quindi, è sempre preferibile installare la versione *Binary*. Tuttavia, in questo caso R ci avverte che, per alcuni pacchetti, gli aggiornamenti più recenti sono disponibili solo nella versione *Source* e ci chiede quindi se installarli attraverso la procedura di compilazione. -E' preferibile rispondere *"no"*, installando così la versione *Binary* pronta all'uso anche se meno aggiornata. Qualora fosse richiesto obbligatoriamente di installare un pacchetto nella version *Source* (perchè ci servono gli ultimi aggiornamenti o perchè non disponibile altrimenti) dovremmo avere prima installato **R tools** (vedi *"Approfondimento: R Tools"* nel Capitolo \@ref(install-r)), che ci fornirà gli strumenti necessari per compilare i pacchetti. +È preferibile rispondere *"no"*, installando così la versione *Binary* pronta all'uso anche se meno aggiornata. Qualora fosse richiesto obbligatoriamente di installare un pacchetto nella version *Source* (perché ci servono gli ultimi aggiornamenti o perché non disponibile altrimenti) dovremmo avere prima installato **RTools** (vedi *"Approfondimento: RTools"* nel Capitolo \@ref(install-r)), che ci fornirà gli strumenti necessari per compilare i pacchetti. -Per una discussione dettagliata vedi e +Per una discussione dettagliata vedi e ::: ### library() -Per utilizzare le funzioni di un pacchetto già presente nella notra library, dobbiamo ora caricarlo nella nostra sessione di lavoro. Per fare ciò, posssiamo utilizzare il comando `library()` indicando tra parentesi il nome del pacchetto richiesto. +Per utilizzare le funzioni di un pacchetto già presente nella nostra library, dobbiamo ora caricarlo nella nostra sessione di lavoro. Per fare ciò, possiamo utilizzare il comando `library()` indicando tra parentesi il nome del pacchetto richiesto. ```{r, echo = TRUE, eval=FALSE} library(car) @@ -346,7 +348,7 @@ In alternativa è possibile spuntare il riquadro alla sinistra del nome del pacc knitr::include_graphics("images/load-package.png") ``` -Ora siamo finalmente pronti per utilizzare le funzioni del pacchetto nella nostra sessione di lavro. +Ora siamo finalmente pronti per utilizzare le funzioni del pacchetto nella nostra sessione di lavoro. :::{.trick title="package::function()" data-latex="[package::function()]"} Esiste un piccolo trucco per utilizzare la funzione di uno specifico pacchetto senza dover caricare il pacchetto nella propria sessione. Per fare questo è possibile usare la sintassi: @@ -358,29 +360,29 @@ Esiste un piccolo trucco per utilizzare la funzione di uno specifico pacchetto s car::Anova() ``` -L'utilizzo dei `::` ci permette di richiamare direttamente la funzione desiderata. La differennza tra l'uso di `library()` e l'uso di `::` riguarda aspetti abbastanza avanzati di R (per un approfondimento vedi ). In estrema sintesi, possiamo dire che in alcuni casi è preferibile non caricare un'intero pacchetto se di questo abbiamo bisogno di un'unica funzione. +L'utilizzo dei `::` ci permette di richiamare direttamente la funzione desiderata. La differenza tra l'uso di `library()` e l'uso di `::` riguarda aspetti abbastanza avanzati di R (per un approfondimento vedi ). In estrema sintesi, possiamo dire che in alcuni casi è preferibile non caricare un'intero pacchetto se di questo abbiamo bisogno di un'unica funzione. ::: -### Aggiornare e Rimuovere Pacchetti +### Aggiornare e rimuovere pacchetti -Anche i pacchettti come ogni altro software vengono aggiornati nel corso del tempo fornendo nuove funzionalità e risolvendo eventuli problemi. Per aggiornare i pacchetti alla versione più recente è possibile eseguire il comando `update.packages()` senza inidare nulla tra le parentesi. +Anche i pacchetti come ogni altro software vengono aggiornati nel corso del tempo fornendo nuove funzionalità e risolvendo eventuali problemi. Per aggiornare i pacchetti alla versione più recente è possibile eseguire il comando `update.packages()` senza indicare nulla tra le parentesi. -In alternativa è possibile premere il pulsante *"Update"* nella barra in alto a sinistra del pannello Packages ( vedi Figura \@ref(fig:library-version)), indicando successivamente i pachetti che si desidera aggiornare. Nota come nella lista dei pacchetti venga riportata l'attuale versione alla voce *"Version"*. +In alternativa è possibile premere il pulsante *"Update"* nella barra in alto a sinistra del pannello Packages ( vedi Figura \@ref(fig:library-version)), indicando successivamente i pacchetti che si desidera aggiornare. Nota come nella lista dei pacchetti venga riportata l'attuale versione alla voce *"Version"*. ```{r, library-version, fig.cap="Aggiornare i pacchetti", out.width="65%"} knitr::include_graphics("images/library-version.png") ``` -Nel caso in cui si vogli invece rimuover uno specifico pacchetto, è possibile eseguire il comando `remove.packages()` indicando tra le parentesi il nome del pacchetto. +Nel caso in cui si voglia invece rimuovere uno specifico pacchetto, è possibile eseguire il comando `remove.packages()` indicando tra le parentesi il nome del pacchetto. -In alternativa è possibile premere il pulsante `x` alla destra del paccehettto nel pannello Packages come mostrao in Figura \@ref(fig:library-remove). +In alternativa è possibile premere il pulsante `x` alla destra del pacchetto nel pannello Packages come mostrato in Figura \@ref(fig:library-remove). ```{r, library-remove, fig.cap="Rimuovere un pacchetto", out.width="65%"} knitr::include_graphics("images/library-remove.png") ``` -### Documentazione Pacchetti +### Documentazione pacchetti Ogni pacchetto include la documentazione delle proprie funzioni e delle *vignette* ovvero dei brevi tutorial che mostrano degli esempi di applicazione e utilizzo del pacchetto. @@ -390,18 +392,18 @@ Ogni pacchetto include la documentazione delle proprie funzioni e delle *vignett - **Documentazione intero pacchetto** - Premendo il nome del pacchetto dal pannello Packages in basso a destra, è possibile accedere alla lista di tutte le informazioni relative al pacchetto come riportato in Figura \@ref(fig:package-documentation). Vengono prima forniti i link per le vignette ed altri file relativi alle caratteristiche del pacchetto. Successivamente sono presentate in ordine alfabetico tutte le funzioni. -```{r, package-documentation, fig.cap="Documetazione del pacchetto car", out.width="65%"} +```{r, package-documentation, fig.cap="Documentazione del pacchetto car", out.width="65%"} knitr::include_graphics("images/package-documentation.png") ``` -Ricordate tuttavia che in ogni caso la più grande risorsa di informazioni è come sempre google. Spesso i pacchetti più importanti hanno addirittura un proprio sito in cui raccolgono molto materiale utile. Ma comunque in ogni caso in internet sono sempre disponibili moltissimi tutorial ed esempi. +Ricordate tuttavia che in ogni caso la più grande risorsa di informazioni è come sempre google. Spesso i pacchetti più importanti hanno addirittura un proprio sito in cui raccolgono molto materiale utile. Ma comunque in ogni caso in internet sono sempre disponibili moltissimi tutorial ed esempi. -:::{.design title="Github" data-latex="[Github]"} -Il CRAN non è l'unica risorsa da cui è possibile installare dei pacchetti di R tuttavia è quella ufficiale e garantisce un certo standard e stabilità dei pacchetti presenti. In internet esistono molte altre repository che raccolgono paccetti di R (e software in generale) tra cui una delle più popolari è certamente GitHub (). +:::{.design title="GitHub" data-latex="[GitHub]"} +Il CRAN non è l'unica risorsa da cui è possibile installare dei pacchetti di R tuttavia è quella ufficiale e garantisce un certo standard e stabilità dei pacchetti presenti. In internet esistono molte altre repository che raccolgono pacchetti di R (e software in generale) tra cui una delle più popolari è certamente GitHub (). -Github viene utilizzato come piattaforma di sviluppo per molti pacchetti di R ed è quindi possibile trovarve le ultime versioni di sviluppo dei pacchetti con gli aggirnamenti più recenti o anche nuovi pacchetti non ancora disponibili sul CRAN. Va sottolineato tuttavia, come quete siano appunto delle versioni di sviluppo e quindi potrebbero presentare maggiori problemi. Inoltre per installare i pacchetti in questo modo, è richiesta l'installzione di **R tools** (vedi *"Approfondimento: R Tools"* nel Capitolo \@ref(install-r)). +Github viene utilizzato come piattaforma di sviluppo per molti pacchetti di R ed è quindi possibile trovare le ultime versioni di sviluppo dei pacchetti con gli aggiramenti più recenti o anche nuovi pacchetti non ancora disponibili sul CRAN. Va sottolineato tuttavia, come queste siano appunto delle versioni di sviluppo e quindi potrebbero presentare maggiori problemi. Inoltre per installare i pacchetti in questo modo, è richiesta l'istallazione di **RTools** (vedi *"Approfondimento: RTools"* nel Capitolo \@ref(install-r)). -Per installare un pacchetto direttamente da Github è posibile utilizzare il comando `install_github()` del pacchetto `devtools`, indicanto tra parentesi la l'url della repository desiderata. +Per installare un pacchetto direttamente da GitHub è possibile utilizzare il comando `install_github()` del pacchetto `devtools`, indicato tra parentesi la l'url della repository desiderata. ```{r, echo = TRUE, eval=FALSE} install.packages("devtools") diff --git a/07-best-practices.Rmd b/07-best-practices.Rmd index 2759cd6..48fab30 100644 --- a/07-best-practices.Rmd +++ b/07-best-practices.Rmd @@ -1,4 +1,4 @@ -# Sessione di Lavoro {#working-session} +# Sessione di lavoro {#working-session} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -17,15 +17,15 @@ if (knitr::is_latex_output()) { In questo capitolo, discuteremo di alcuni aspetti generali delle sessioni di lavoro in R. Descriveremo delle buone abitudini riguardanti l'organizzazione degli scripts per essere ordinati ed efficaci nel proprio lavoro. Inoltre descriveremo come organizzare i propri progetti in cartelle ed in particolare introdurremo l'uso degli *RStudio Projects*. Infine approfondiremo l'uso dei messaggi di R ed in particolare come comportarsi in caso di errori. -## Organizzazione Script +## Organizzazione script Abbiamo visto che idealmente tutti i passaggi delle nostre analisi devono essere raccolti in modo ordinato all'interno di uno script. Eseguendo in ordine linea per linea i comandi, dovrebbe essere possibile svolgere tutte le analisi fino ad ottenere i risultati desiderati. Vediamo ora una serie di buone regole per organizzare in modo ordinato il codice all'interno di uno script e facilitare la sua lettura. -### Creare delle Sezioni +### Creare delle sezioni -Per mantenere chiara l'oreganizzazione degli script e facilitare la sua comprensione, è utile suddividere il codice in sezioni dove vengono eseguiti i diversi step delle analisi. In RStudio è possibile creare una sezione aggiungendo al termine di una linea di commento i caratteri `####` o `----`. Il testo del commento verrà considerao il titolo della sezione e comparirà una piccola freccia a lato del numero di riga. E' possibile utilizzare a piacere i caratteri `#` o `-` per creare lo stile desiderato, l'importante è che la linea si concluda con almeno quattro caratteri identici. +Per mantenere chiara l'organizzazione degli script e facilitare la sua comprensione, è utile suddividere il codice in sezioni dove vengono eseguiti i diversi step delle analisi. In RStudio è possibile creare una sezione aggiungendo al termine di una linea di commento i caratteri `####` o `----`. Il testo del commento verrà considerato il titolo della sezione e comparirà una piccola freccia a lato del numero di riga. È possibile utilizzare a piacere i caratteri `#` o `-` per creare lo stile desiderato, l'importante è che la linea si concluda con almeno quattro caratteri identici. ```{r, echo = TRUE} @@ -45,11 +45,11 @@ A titolo del tutto esemplificativo prendiamo in esempio la divisione in sezioni knitr::include_graphics("images/script-template.png") ``` -- **Titolo** - Un titolo esplicativo del contenuto dello script. E' possibile utilizzare altri caratteri all'interno dei commenti per creare l'effetto desiderato. -- **Intorduzione** - Descrizione e utili informazioni che riguardano sia l'obbiettivo del lavoro che l'esecuzione del codice (e.g., dove sono disponibili i dati, eventuali specifiche tecniche). Potrebbe essere utile anche indicare l'autore e la data del lavoro. -- **Setting** - Sezione fondamentale in cui si predispone l'abiente di lavoro. Le operazioni da svolgere sono: +- **Titolo** - Un titolo esplicativo del contenuto dello script. È possibile utilizzare altri caratteri all'interno dei commenti per creare l'effetto desiderato. +- **Introduzione** - Descrizione e utili informazioni che riguardano sia l'obbiettivo del lavoro che l'esecuzione del codice (ad es. dove sono disponibili i dati, eventuali specifiche tecniche). Potrebbe essere utile anche indicare l'autore e la data del lavoro. +- **Setting** - Sezione fondamentale in cui si predispone l'ambiente di lavoro. Le operazioni da svolgere sono: 1. `rm(list = ls())` per pulire l'Environment da eventuali oggetti in modo da eseguire lo script partendo da un ambiente vuoto (vedi Capitolo \@ref(environment)). - 2. `setwd()` per settare la working directory per assicuraci che i comandi siano eseguiti dalla correttta posizione nel nostro computer (vedi Capitolo \@ref(working-directory)). + 2. `setwd()` per settare la working directory per assicuraci che i comandi siano eseguiti dalla corretta posizione nel nostro computer (vedi Capitolo \@ref(working-directory)). 3. `library()` per caricare i pacchetti utilizzati nel corso delle analisi (vedi Capitolo \@ref(packages)). - **Caricare e Pulire i Dati** - Generica sezione in cui eseguire l'importazione e pulizia dei dati. - **Codifica e Scoring dei Dati** - Generica sezione in cui eseguire la codifica ed eventuale scoring dei dati. @@ -74,31 +74,31 @@ Infine, un altro vantaggio è quello di poter compattare o espandere le sezioni knitr::include_graphics("images/section-closed.png") ``` -### Sintassi {#sintax} +### Sintassi {#syntax} Elenchiamo qui altre buone norme nella scrittura del codice che ne facilitano la comprensione. #### Commenti {-} -L'uso dei commenti è molto importante, ci permette di documentare le varie parti del codice e chiarire eventuli comandi difficili da capire. Tuttavia, non è necessario commentare ogni singola riga di codice ed anzi è meglio evitare di commentare laddove i comandi sono facilemtne interpetabili semplicemnte leggendo il codice. +L'uso dei commenti è molto importante, ci permette di documentare le varie parti del codice e chiarire eventuali comandi difficili da capire. Tuttavia, non è necessario commentare ogni singola riga di codice ed anzi è meglio evitare di commentare laddove i comandi sono facilmente interpretabili semplicemente leggendo il codice. -La capacità di scrivere commenti utili ed eviare quelli rindondanti si impara con l'esperienza. In generale un commento non dovrebbe indicare *"che cosa"* ma piuttosto il *"perchè"* di quella parte di codice. Infatti il cosa è facilmente interpretabile dal codice stesso mentre il perchè potrebbe essere meno ovvio e soprattutto più utile per la comprensione dell'intero script. Ad esempio: +La capacità di scrivere commenti utili ed evitare quelli ridondanti si impara con l'esperienza. In generale un commento non dovrebbe indicare *"che cosa"* ma piuttosto il *"perché"* di quella parte di codice. Infatti il cosa è facilmente interpretabile dal codice stesso mentre il perché potrebbe essere meno ovvio e soprattutto più utile per la comprensione dell'intero script. Ad esempio: ```{r, echo = TRUE, eval=FALSE} x <- 10 # assegno a x il valore 10 x <- 10 # definisco massimo numero risposte ``` -Il primo commento è inutile poichè è facilmente comprensibile dal codice stesso, mentre il secondo commento è motlo utile perchè chiarisce il significato della variabile e mi faciliterà nella comprensione del codice. +Il primo commento è inutile poiché è facilmente comprensibile dal codice stesso, mentre il secondo commento è molto utile perché chiarisce il significato della variabile e mi faciliterà nella comprensione del codice. #### Nomi Oggetti {-} -Abbiamo visto nel Capitolo \@ref(objects-names) le regole che discriminano nomi validi da nomi non validi e le convenzioni da seguire nella definizione di un nome. Ricordiamo qui le caratterisiche che un nome deve avere per facilitare la comprensione del codice. Il nome di un oggetto deve essere: +Abbiamo visto nel Capitolo \@ref(objects-names) le regole che discriminano nomi validi da nomi non validi e le convenzioni da seguire nella definizione di un nome. Ricordiamo qui le caratteristiche che un nome deve avere per facilitare la comprensione del codice. Il nome di un oggetto deve essere: -- **auto-descrittivo** - Dal solo nome dovrebbe essere possibile intuire il contenuto dell'oggetto. E' meglio quindi evitare nomi generici (quali `x` o `y`) ed utilizzare invece nomi che chiaramente descrivano il contenuto dell'oggetto. +- **auto-descrittivo** - Dal solo nome dovrebbe essere possibile intuire il contenuto dell'oggetto. È meglio quindi evitare nomi generici (quali `x` o `y`) ed utilizzare invece nomi che chiaramente descrivano il contenuto dell'oggetto. - **della giusta lunghezza** - Non deve essere ne troppo breve (evitare sigle incomprensibili) ma neppure troppo lunghi. In genere sono sufficienti 2 o 3 parole per descrivere chiaramente un oggetto. -E' inoltre importante essere **consistenti** nella scelta dello stile con cui si nominano le variabili. In genere è preferibile usare lo **snake_case** rispetto al **CamelCase**, ma la scelta è comunque libera. Tuttavia, una volta presa una decisione, è bene mantenerla per facilitare la comprensione del codice. +È inoltre importante essere **consistenti** nella scelta dello stile con cui si nominano le variabili. In genere è preferibile usare lo **snake_case** rispetto al **CamelCase**, ma la scelta è comunque libera. Tuttavia, una volta presa una decisione, è bene mantenerla per facilitare la comprensione del codice. -#### Esplicitare Argomenti {-} +#### Esplicitare argomenti {-} Abbiamo visto nel Capitolo \@ref(function-arguments) l'importanza di esplicitare il nome degli argomenti quando vengono utilizzati nelle funzioni. Specificando a che cosa si riferiscono i vari valori facilitiamo la lettura e la comprensione del codice. Ad esempio: @@ -106,14 +106,14 @@ Abbiamo visto nel Capitolo \@ref(function-arguments) l'importanza di esplicitare seq(0, 10, 2) ``` -Potrebbe non essere chiaro se intendiamo una sequennza tra 0 e 10 di lunghezza 2 o a intervalli di 2. Specificando gli argomenti evitiamo incomprensioni e possibili errori. +Potrebbe non essere chiaro se intendiamo una sequenza tra 0 e 10 di lunghezza 2 o a intervalli di 2. Specificando gli argomenti evitiamo incomprensioni e possibili errori. ```{r, echo = TRUE, eval = FALSE} seq(from = 0, to = 10, by = 2) seq(from = 0, to = 10, length.out = 2) ``` -#### Spazi, Indentazione ed allineamento {-} +#### Spazi, indentazione e allineamento {-} Al contrario di molti altri software, R non impone regole severe nell'utilizzo di spazi, indentazioni ed allineamenti ed in genere è molto permissivo per quanto riguarda la sintassi del codice. Tuttavia è importante ricordare che: @@ -126,7 +126,7 @@ Prendiamo ad esempio le seguenti linee di codice, che includono delle funzioni a k=10;if(k<5){x<-5:15}else{x<-seq(0,16,4)};y=7*2-12;mean(x/y) # Stile 2 -k <- 10 +k <- 10 if (k < 5){ x <- 5:15 @@ -154,7 +154,7 @@ x <- 0:10 x<-0 : 10 ``` -- Nelle funzioni aggiungi degli **spazi** intorno al simbolo `=` che separa il nome degli argomenti e il loro valore. Aggiungi uno spazio dopo ogni virogola ma non separare il nome della funzione dalla parentesi sinistra. +- Nelle funzioni aggiungi degli **spazi** intorno al simbolo `=` che separa il nome degli argomenti e il loro valore. Aggiungi uno spazio dopo ogni virgola ma non separare il nome della funzione dalla parentesi sinistra. ```{r, echo=TRUE, eval = FALSE} # Good seq(from = 0, to = 10, by = 2) @@ -163,14 +163,14 @@ seq(from = 0, to = 10, by = 2) seq (from=0,to=10,by=2) ``` -- Usa la corretta **indentazione** per i blocchi di codice posti all'interno delle parentesi graffe. Il livello di indentazione deve rispecchiare la struttura di annidamento del codice. +- Usa la corretta **indentazione** per i blocchi di codice posti all'interno delle parentesi graffe. Il livello di indentazione deve rispecchiare la struttura di annidamento del codice. ```{r, echo=TRUE, eval = FALSE} # Good for (...) { # loop più esterno ... for (...) { # loop interno ... - if (...) { # isruzione condizionale + if (...) { # istruzione condizionale ... } } @@ -181,7 +181,7 @@ for (...) { # loop più esterno ... for (...) { # loop interno ... -if (...) { # isruzione condizionale +if (...) { # istruzione condizionale ... } } @@ -202,33 +202,34 @@ age = ..., sex = ...) :::{.design title="Tutta una Questione di Stile" data-latex="[Tutta una Questione di Stile]"} -Potete trovare ulteriori regole e consigli riguardanti lo stile nella scrittura di codici al seguente link . +Potete trovare ulteriori regole e consigli riguardanti lo stile nella scrittura di codici al seguente link . ::: -## Organizzazione Progetti +## Organizzazione progetti -All'aumentare della complessità di un'analisi vi troverete presto a dover gestire molti file di deversa tipologia (e.g., dati, report, grafici) e a dover suddividere le varie parti del lavoro in differenti script. A questo punto sarà opportuno organizzare in modo ordinato tutto il materiale necessario per l'analisi e i relativi risultati in un'unica cartella. +All'aumentare della complessità di un'analisi vi troverete presto a dover gestire molti file di diversa tipologia (ad es. dati, report, grafici) e a dover suddividere le varie parti del lavoro in differenti script. A questo punto sarà opportuno organizzare in modo ordinato tutto il materiale necessario per l'analisi e i relativi risultati in un'unica cartella. Idealmente, infatti, ogni analisi verrà salvata in una differente cartella e possiamo ad esempio organizzare i file utilizzando la seguente struttura di sottocartelle: ``` My_analysis/ - |- Data/ - |- Documents/ - |- Outputs/ - |- R/ + | + |- Data/ + |- Documents/ + |- Outputs/ + |- R/ ``` -- `Data/` - tutti i file relativi ai dati usati nell'analisi. Sarà importante mantenere sia una copia dei dati *raw*, ovvero i dati grezzi senza alcuan manipolazione, sia i dati effetivamente usati nelle analisi che in genere sono stati già puliti e codificati. -- `Documents/` - tutti i file di testo (e.g., Word o simili) e report utilizzati per descrivere le analisi (vedi in particolare [R-markdown](https://rmarkdown.rstudio.com/)). +- `Data/` - tutti i file relativi ai dati usati nell'analisi. Sarà importante mantenere sia una copia dei dati *raw*, ovvero i dati grezzi senza alcuna manipolazione, sia i dati effettivamente usati nelle analisi che in genere sono stati già puliti e codificati. +- `Documents/` - tutti i file di testo (ad es. Word o simili) e report utilizzati per descrivere le analisi (vedi in particolare [R-markdown](https://rmarkdown.rstudio.com/)). - `Outputs/` - eventuali outputs creati durante le analisi come ad esempio grafici e tabelle. -- `R/` - tutti gli script utilizzati per le analisi. E' possibile numerare gli script per suggerire il corretto ordine in cui debbano essere eseguiti, ad esempio `01-import-data.R`, `02-munge-data.R`, `03-descriptive-analysis.R` etc. +- `R/` - tutti gli script utilizzati per le analisi. È possibile numerare gli script per suggerire il corretto ordine in cui debbano essere eseguiti, ad esempio `01-import-data.R`, `02-munge-data.R`, `03-descriptive-analysis.R` etc. Questa struttura è puramente esemplificativa ma può essere un utile base di partenza che è possibile adattare a seconda delle particolari esigenze di ogni lavoro. ### RStudio Projects -RStudio permette inoltre di creare degli **R Projects**, ovvero degli spazi di lavoro che permettono di gestire indipendentemente diversi progetti. Ogni progetto avrà la propria working directory, workspace, history e settaggi personalizzati. Questo consente di passare velocemente da un progetto ad un altro riprendento immediatamente il lavoro da dove si era arrivati senza altre preoccupazioni. +RStudio permette inoltre di creare degli **R Projects**, ovvero degli spazi di lavoro che permettono di gestire indipendentemente diversi progetti. Ogni progetto avrà la propria working directory, workspace, history e settaggi personalizzati. Questo consente di passare velocemente da un progetto ad un altro riprendendo immediatamente il lavoro da dove si era arrivati senza altre preoccupazioni. Vediamo quindi come creare un **R Projects**. @@ -257,12 +258,12 @@ Vediamo quindi come creare un **R Projects**. ![](images/r-project-5.png){ width=15% }
-6. Per chiudere un progetto è sufficiente selezionare *File* > *Close Project* o in alterantiva utilizzare il menù in alto a destra +6. Per chiudere un progetto è sufficiente selezionare *File* > *Close Project* o in alterativa utilizzare il menù in alto a destra
![](images/r-project-6.png){ width=75% }

-6. Per aprire un progetto precedente, è sufficiente selezionare *File* > *Open Project* o in alterantiva fare doppio click sul file `.Rproj` presente nella cartella del progetto +6. Per aprire un progetto precedente, è sufficiente selezionare *File* > *Open Project* o in alterativa fare doppio click sul file `.Rproj` presente nella cartella del progetto
![](images/r-project-7.png){ width=75% }
@@ -270,27 +271,27 @@ Vediamo quindi come creare un **R Projects**. Elenchiamo ora alcuni dei principali vantaggi dell'utilizzare gli R Project: -- La **working directory** viene autoamticamente settata nella cartella del progetto. Questo ci permette di non doverci più preoccupare della sua definizione e possiamo definire ogni *path* in relazione alla cartella del progetto. -- Quando apriamo un progetto in una successiva **sessione di lavoro** gli script e i documenti di lavoro verranno automaticamente aperti come li avevamo lasciati nella sessione precedente. E' come avere una scrivania per ogni progetto dove lasciare tutti i documenti utili e riprendere il lavoro immediatamete. -- Utilizzando i progetti è possibile **personnalizzare e automatizzare** molte funzioni come ad esempio caricare i paccheti o eseguire determinati codici. Tuttavia richiedono una buona conoscenza di R. +- La **working directory** viene automaticamente settata nella cartella del progetto. Questo ci permette di non doverci più preoccupare della sua definizione e possiamo definire ogni *path* in relazione alla cartella del progetto. +- Quando apriamo un progetto in una successiva **sessione di lavoro** gli script e i documenti di lavoro verranno automaticamente aperti come li avevamo lasciati nella sessione precedente. È come avere una scrivania per ogni progetto dove lasciare tutti i documenti utili e riprendere il lavoro immediatamente. +- Utilizzando i progetti è possibile **personalizzare e automatizzare** molte funzioni come ad esempio caricare i pacchetti o eseguire determinati codici. Tuttavia richiedono una buona conoscenza di R. - Esistono molti **template** per i progetti che implementano utili funzionalità, in particolare la struttura degli R Projects usata per lo sviluppo dei pacchetti è molto utile anche nel caso di analisi statistiche. Tuttavia richiedono una buona conoscenza di R. -## Messages, Warnings e Errors +## Message, Warning ed Error R utilizza la console per comunicare con noi durante le nostre sessioni di lavoro. Oltre a fornirci i risultati dei nostri comandi, R ci segnala anche altre utili informazioni attraverso diverse tipologie di messaggi. In particolare abbiamo: -- **Messages**: dei semplici messaggi che ci possono aggiornare ad esempio sullo stato di avanzamento di un dato compito oppure fornire suggerimenti sull'uso di una determinata funzione o pacchetto (spesso vengono mostrati quando viene caricato un pacchetto). -- **Warnings**: questi messaggi sono utlizzati da R per dirci che c'è stato qualche cosa di strano che ha messo in allerta R. R ci avvisa che, sebbene il comando sia stato eseguito ed abbiamo ottenuto un risultato, ci sono stati dei comportamenti inusuali o magari eventuali correzioni apportate in automatico. Nel caso di warnings non ci dobbiamo allramre, è importante controllare che i comandi siano corretti e che abbiamo effetivamente ottenuto il risultato desiderato. Una volta sicuri dei risultati possiamo procedere tranquillamente. -- **Errors**: R ci avvisa di eventuali errori e problemi che non permettono di eseguire il comando. in questo caso non otterremo nnessun risultato ma sarà necessario capire e risolvere il problema per poi rieseguire nuovamente il comando e procedere. +- **Message**: dei semplici messaggi che ci possono aggiornare ad esempio sullo stato di avanzamento di un dato compito oppure fornire suggerimenti sull'uso di una determinata funzione o pacchetto (spesso vengono mostrati quando viene caricato un pacchetto). +- **Warning**: questi messaggi sono utilizzati da R per dirci che c'è stato qualche cosa di strano che ha messo in allerta R. R ci avvisa che, sebbene il comando sia stato eseguito ed abbiamo ottenuto un risultato, ci sono stati dei comportamenti inusuali o magari eventuali correzioni apportate in automatico. Nel caso di warnings non ci dobbiamo allarmare, è importante controllare che i comandi siano corretti e che abbiamo effettivamente ottenuto il risultato desiderato. Una volta sicuri dei risultati possiamo procedere tranquillamente. +- **Error**: R ci avvisa di eventuali errori e problemi che non permettono di eseguire il comando. in questo caso non otterremo nessun risultato ma sarà necessario capire e risolvere il problema per poi rieseguire nuovamente il comando e procedere. -Notiamo quindi come non tutti i messaggi che R ci manda sono dei messaggi di errore. E' quindi importante non spaventarsi ma leggere con attenzione i messaggi, molte volte si tratta semplicemente di avvertimenti o suggerimenti. +Notiamo quindi come non tutti i messaggi che R ci manda sono dei messaggi di errore. È quindi importante non spaventarsi ma leggere con attenzione i messaggi, molte volte si tratta semplicemente di avvertimenti o suggerimenti. -Tuttavia gli errori rappresentano sempre il maggiore dei problemi perchè non è possibile procedere nel lavoro senza averli prima risolti. E' importante ricordare che i messaggi di errore non sono delle critiche che R ci rivolge perchè sbagliamo. Al contrario, sono delle richieste di aiuto fatte da R perchè non sa come comportarsi. Per quanto super potente, R è un seplice programma che non può interpretare le nostre richieste ma si basa sull'uso dei comandi che seguono una rigida sintassi. A volte è sufficiente una virgola mancante o un charattere al posto di un numero per mandare in confusione R e richiedere il nostro intervento risolutore. +Tuttavia gli errori rappresentano sempre il maggiore dei problemi perché non è possibile procedere nel lavoro senza averli prima risolti. È importante ricordare che i messaggi di errore non sono delle critiche che R ci rivolge perché sbagliamo. Al contrario, sono delle richieste di aiuto fatte da R perché non sa come comportarsi. Per quanto super potente, R è un semplice programma che non può interpretare le nostre richieste ma si basa sull'uso dei comandi che seguono una rigida sintassi. A volte è sufficiente una virgola mancante o un carattere al posto di un numero per mandare in confusione R e richiedere il nostro intervento risolutore. -### Risolvere gli Errori +### Risolvere gli errori -Quando si approccia la scrittura di codice, anche molto semplice, la cosa che sicuramente capiterà più spesso sarà riscontrare messaggi di **errore** e quindi trovare il modo per risolverli. +Quando si approccia la scrittura di codice, anche molto semplice, la cosa che sicuramente capiterà più spesso sarà riscontrare messaggi di **errore** e quindi trovare il modo per risolverli. > Qualche programmatore esperto direbbe che l'essenza stessa di programmare è in realtà risolvere gli errori che il codice produce. @@ -302,11 +303,11 @@ Abbiamo tutti le immagini in testa di programmatori da film che scrivono codice * Sapere **come e dove cercare una soluzione** (ancora meno banale) * In caso non si trovi una soluzione direttamente, chiedere aiuto in modo efficace -#### Comprendere gli errori{-} +#### Comprendere gli errori {-} Leggere con attenzione i messaggi di errore è molto importante. R è solitamente abbastanza esplicito nel farci capire il problema. Ad esempio usare una funzione di un pacchetto che non è stato caricato di solito fornisce un messaggio del tipo `Error in funzione : could not find function "funzione"`. -Tuttavia, in altre situazioni i messaggi potrebbero non essere altrettanto chiari. Seppur esplicito R è anche molto sintetico e quindi l'utilzzo di un linguaggio molto specifico (e almeno inizialmente poco familiare), potrebbe rendere difficile capire il loro significato o addirittura renderli del tutto incomprensibili. Man mano che diventerete più esperti in R, diventerà sempre più semplice ed immmediato capire quale sia il problema e anche come risolverlo. Ma nel caso non si conosca la soluzione è necessario cercarla in altro modo. +Tuttavia, in altre situazioni i messaggi potrebbero non essere altrettanto chiari. Seppur esplicito R è anche molto sintetico e quindi l'utilizzo di un linguaggio molto specifico (e almeno inizialmente poco familiare), potrebbe rendere difficile capire il loro significato o addirittura renderli del tutto incomprensibili. Man mano che diventerete più esperti in R, diventerà sempre più semplice ed immediato capire quale sia il problema e anche come risolverlo. Ma nel caso non si conosca la soluzione è necessario cercarla in altro modo. #### Problema + Google = Soluzione {-} @@ -327,10 +328,10 @@ Cercando in questo modo vedrete che molti dei risultati saranno esattamente rife #### Chiedere una soluzione {-} -Se invece il vostro probelma non è un messaggio di errore ma un utilizzo specifico di R allora il consiglio è di usare una ricerca del tipo: `argomento + breve descrizione problema + R`. Nelle sezioni successive vedrete nel dettaglio altri aspetti della programmazione ma se volete ad esempio calcolare la **media** in R potrete scrivere `compute mean in R`. -Mi raccomando, fate tutte le ricerche in **inglese** perchè le possibilità di trovare una soluzione sono molto più alte. +Se invece il vostro problema non è un messaggio di errore ma un utilizzo specifico di R allora il consiglio è di usare una ricerca del tipo: `argomento + breve descrizione problema + R`. Nelle sezioni successive vedrete nel dettaglio altri aspetti della programmazione ma se volete ad esempio calcolare la **media** in R potrete scrivere `compute mean in R`. +Mi raccomando, fate tutte le ricerche in **inglese** perché le possibilità di trovare una soluzione sono molto più alte. -Dopo qualche ricerca, vi renderete conto che il sito che vedrete più spesso si chiama [**Stack Overflow**](https://stackoverflow.com/). Questo è una manna dal cielo per tutti i programmatori, a qualsiasi livello di expertise. E' una community dove tramite domande e risposte, si impara a risolvere i vari problemi ed anche a trovare nuovi modi di fare la stessa cosa. E' veramente utile oltre che un ottimo modo per imparare. +Dopo qualche ricerca, vi renderete conto che il sito che vedrete più spesso si chiama [**Stack Overflow**](https://stackoverflow.com/). Questo è una manna dal cielo per tutti i programmatori, a qualsiasi livello di expertise. È una community dove tramite domande e risposte, si impara a risolvere i vari problemi ed anche a trovare nuovi modi di fare la stessa cosa. È veramente utile oltre che un ottimo modo per imparare. L'ultimo punto di questa piccola guida alla ricerca di soluzioni, riguarda il fatto di dover non solo cercare ma anche chiedere. Dopo aver cercato vari post di persone che richiedevano aiuto per un problema noterete che le domande e le risposte hanno sempre una struttura simile. Questo non è solo un fatto stilistico ma anzi è molto utile per uniformare e rendere chiara la domanda ma sopratutto la risposta, in uno spirito di condivisione. C'è anche una [guida dedicata](https://stackoverflow.com/help/how-to-ask) per scrivere la domanda perfetta. @@ -341,7 +342,7 @@ In generale[^stack]: - Descrizione del problema/richiesta: in modo chiaro e semplice ma non troppo generico - Codice ed eventuali dati per capire il problema -L'ultimo punto di questa lista è forse il più importante e si chiama in gergo tecnico [**REPREX**](https://community.rstudio.com/t/faq-whats-a-reproducible-example-reprex-and-how-do-i-create-one/5219) (**Rep**roducible **Ex**ample). E' un tema leggermente più avanzato ma l'idea di fondo è quella di fornire tutte le informazioni possibili per poter riprodurre (e quindi eventualmente trovare una soluzione) il codice di qualcuno nel proprio computer. +L'ultimo punto di questa lista è forse il più importante e si chiama in gergo tecnico [**REPREX**](https://community.rstudio.com/t/faq-whats-a-reproducible-example-reprex-and-how-do-i-create-one/5219) (**Rep**roducible **Ex**ample). È un tema leggermente più avanzato ma l'idea di fondo è quella di fornire tutte le informazioni possibili per poter riprodurre (e quindi eventualmente trovare una soluzione) il codice di qualcuno nel proprio computer. Se vi dico "R non mi fa creare un nuovo oggetto, quale è l'errore?" è diverso da dire "il comando `oggetto -> 10` mi da questo errore `Error in 10 <- oggetto : invalid (do_set) left-hand side to assignment`, come posso risolvere?" diff --git a/08-introduction-data-structure.Rmd b/08-introduction-data-structure.Rmd index 127702a..a84a621 100755 --- a/08-introduction-data-structure.Rmd +++ b/08-introduction-data-structure.Rmd @@ -1,15 +1,15 @@ -# (PART\*) Struttura Dati {-} +# (PART\*) Strutture Dati {-} # Introduzione {#second-section -} -In questa sezione verranno introdotte le principali tipologie di oggetti usati in R . Ovvero le principali strutture in cui possono essere organizzati i dati: Vettori, Matrici, Dataframe e Liste. +In questa sezione verranno introdotte le principali tipologie di oggetti usati in R . Ovvero le principali strutture in cui possono essere organizzati i dati: vettori, matrici, dataframe e liste. -Per ognuna di esse descriveremo le loro caretteristiche e vedremo come crearle, modificarle e manipolarle a seconda delle necessità +Per ognuna di esse descriveremo le loro caratteristiche e vedremo come crearle, modificarle e manipolarle a seconda delle necessità I capitoli sono così organizzati: -- **Capitolo \@ref(vector) - Vettori**. Impareremo le caratterisiche e l'uso dei vettori soffermandoci anche sulle diverse tipologie di dati. -- **Capitolo \@ref(factor) - Fattori**. Impareremo le caratterisiche e l'uso dei fattori, ovvero un particolare tipo di vettori usati per le variabili categoriali ed ordinali. -- **Capitolo \@ref(matrix) - Matrici**. Impareremo le caratterisiche e l'uso delle matrici introducendo anche gli array. -- **Capitolo \@ref(dataframe) - Dataframe**. Impareremo le caratterisiche e l'uso dei datafraeme, l'oggetto maggiormmente utilizzato nell'analisi di dati. -- **Capitolo \@ref(list) - Liste**. Impareremo le caratterisiche e l'uso delle liste. +- **Capitolo \@ref(vector) - Vettori**. Impareremo le caratteristiche e l'uso dei vettori soffermandoci anche sulle diverse tipologie di dati. +- **Capitolo \@ref(factor) - Fattori**. Impareremo le caratteristiche e l'uso dei fattori, ovvero un particolare tipo di vettori usati per le variabili categoriali ed ordinali. +- **Capitolo \@ref(matrix) - Matrici**. Impareremo le caratteristiche e l'uso delle matrici introducendo anche gli array. +- **Capitolo \@ref(dataframe) - Dataframe**. Impareremo le caratteristiche e l'uso dei dataframe, l'oggetto maggiormente utilizzato nell'analisi di dati. +- **Capitolo \@ref(list) - Liste**. Impareremo le caratteristiche e l'uso delle liste. diff --git a/09-vectors.Rmd b/09-vectors.Rmd index 737af69..3959c41 100755 --- a/09-vectors.Rmd +++ b/09-vectors.Rmd @@ -20,10 +20,10 @@ knitr::include_graphics("images/vector.png") Due caratteristiche importanti di un vettore sono: - la **lunghezza** - il numero di elementi da cui è formato il vettore -- la **tipologia** - la tipologia di dati da cui è formato il vettore. Un vettore infatti deve esssere formato da **elementi tutti dello stesso tipo** e pertanto esistono diversi vettori a seconda della tipologia di dati da cui è formato (valori numerici, valori interi, valori logici, valori carattere). +- la **tipologia** - la tipologia di dati da cui è formato il vettore. Un vettore infatti deve essere formato da **elementi tutti dello stesso tipo** e pertanto esistono diversi vettori a seconda della tipologia di dati da cui è formato (valori numerici, valori interi, valori logici, valori carattere). -E' fondamentale inoltre sottolineare come ogni **elemento** di un vettore sia caratterizzato da: +È fondamentale inoltre sottolineare come ogni **elemento** di un vettore sia caratterizzato da: - un **valore** - ovvero il valore dell'elemento che può essere di qualsiasi tipo ad esempio un numero o una serie di caratteri. - un **indice di posizione** - ovvero un numero intero positivo che identifica la sua posizione all'interno del vettore. @@ -32,14 +32,14 @@ Notiamo quindi come i vettori $x$ e $y$ così definiti: $$ x = [1, 3, 5];\ \ \ y = [3, 1, 5], $$ -sebbene includano gli stessi elementi, non sono identici poichè differiscono per la loro disposizione. Tutto questo ci serve solo per ribadire come l'ordine degli elementi sia fondamentale per la valutazione di un vettore. +sebbene includano gli stessi elementi, non sono identici poiché differiscono per la loro disposizione. Tutto questo ci serve solo per ribadire come l'ordine degli elementi sia fondamentale per la valutazione di un vettore. -Vedimao ora come creare dei vettori in R e come compiere le comuni operazini di selezione e manipolazione di vettori. Successivamente approfondiremo le caratteristiche dei vettori valutandone le diverse tipologie. +Vediamo ora come creare dei vettori in R e come compiere le comuni operazioni di selezione e manipolazione di vettori. Successivamente approfondiremo le caratteristiche dei vettori valutandone le diverse tipologie. ## Creazione -In realtà abbiamo già incontrato dei vettori nei precedenti capitoli poichè anche le variabili con un singolo valore altro non sono che un vettore di lunghezza 1. Tuttavia, per creare dei vettori di più elementi dobbiamo utilizzare il comando `c()`, ovvero *"combine"*, indicando tra le parentesi i valori degli elementi nella sucessione desiderata e separati da una virgola. Avremo quindi la seguente sintassi: +In realtà abbiamo già incontrato dei vettori nei precedenti capitoli poiché anche le variabili con un singolo valore altro non sono che un vettore di lunghezza 1. Tuttavia, per creare dei vettori di più elementi dobbiamo utilizzare il comando `c()`, ovvero *"combine"*, indicando tra le parentesi i valori degli elementi nella successione desiderata e separati da una virgola. Avremo quindi la seguente sintassi: ```{r echo = TRUE, eval = FALSE} nome_vettore <- c(x_1, x_2, x_3, ..., x_n) @@ -47,8 +47,8 @@ nome_vettore <- c(x_1, x_2, x_3, ..., x_n) Nota come gli elementi di un vettore debbano essere tutti della stessa tipologia ad esempio valori numerici o valori carattere. -:::{.design title="Sequenze - ':', seq() e rep() " data-latex="[Sequenze - ':', seq() e rep() ]"} -In altrentativa è possibile utilizzare qualsiasi funzione che restituisca come output una sequenza di valori sotto forma di vettore. Tra le funzioni più usate per creare delle sequenze abbiammo: +:::{.design title="Sequenze - \\texttt{:}, \\texttt{seq()} e \\texttt{rep()}" data-latex="[Sequenze - \\texttt{:}, \\texttt{seq()} e \\texttt{rep()}]"} +In alternativa è possibile utilizzare qualsiasi funzione che restituisca come output una sequenza di valori sotto forma di vettore. Tra le funzioni più usate per creare delle sequenze abbiamo: - `:` - Genera una sequenza di valori numerici crescenti (o decrescenti) dal primo valore indicato (``) al secondo valore indicato (``) a step di 1 (o -1 ). ```{r echo = TRUE} @@ -62,7 +62,7 @@ In altrentativa è possibile utilizzare qualsiasi funzione che restituisca come 5.3:10 ``` -- `seq(from = , to = , by = , length.out = )` - Genera una sequenza regolare di valori numerici compresi tra `from` e `to` con incrementi indicati da `by`, oppure di lunghezza conplessiva indicata da `length.out` (vedi `?seq()` per maggiori dettagli). +- `seq(from = , to = , by = , length.out = )` - Genera una sequenza regolare di valori numerici compresi tra `from` e `to` con incrementi indicati da `by`, oppure di lunghezza complessiva indicata da `length.out` (vedi `?seq()` per maggiori dettagli). ```{r echo = TRUE} # sequenza a incrementi di 2 seq(from = 0, to = 10, by = 2) @@ -71,7 +71,7 @@ seq(from = 0, to = 10, by = 2) seq(from = 0, to = 1, length.out = 5) ``` -- `rep(x, times = , each = )` - Genera una sequenza di valori ripetendo i valori contenuti in `x`. I valori di `x` posssono essere ripetuti nello stesso ordine più volte specificando `times` oppure ripetuti ciascuno più volte specificando `each` (vedi `?rep()` per maggiori dettagli). +- `rep(x, times = , each = )` - Genera una sequenza di valori ripetendo i valori contenuti in `x`. I valori di `x` possono essere ripetuti nello stesso ordine più volte specificando `times` oppure ripetuti ciascuno più volte specificando `each` (vedi `?rep()` per maggiori dettagli). ```{r echo = TRUE} # sequenza a incrementi di 2 rep(c("foo", "bar"), times = 3) @@ -83,7 +83,7 @@ rep(1:3, each = 2) ### Esercizi {-} -Famigliarizza con la creazione di vettori ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-07-vectors.R)): +familiarizza con la creazione di vettori ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-07-vectors.R)): 1. Crea il vettore `x` contenente i numeri 4, 6, 12, 34, 8 2. Crea il vettore `y` contenente tutti i numeri pari compresi tra 1 e 25 (`?seq()`) @@ -97,7 +97,7 @@ rep(rep(c("foo", "bar"), each = 2),times = 2) ``` -## Selezione Elementi {#vector-selection} +## Selezione elementi {#vector-selection} Una volta creato un vettore potrebbe essere necessario selezionare uno o più dei suoi elementi. In R per selezionare gli elementi di un vettore si utilizzano le **parentesi quadre** `[]` dopo il nome del vettore, indicando al loro interno **l'indice di posizione** degli elementi desiderati: @@ -119,7 +119,7 @@ my_numbers[2] my_numbers[4] ``` -Per selezionare più elementi è necessario indicare tra le parentesi quadre tutti gli indici di posizione degli elementi desiderati. Nota come non sia possibile fornire semplicemente i singoli indici numerici ma questi devono essere raccolti in un vettore, ad esempio usando la funzione `c()`. Praticamente usiamo un vetore di indici per selezionare gli elemeni desiderati dal nostro vettore iniziale. +Per selezionare più elementi è necessario indicare tra le parentesi quadre tutti gli indici di posizione degli elementi desiderati. Nota come non sia possibile fornire semplicemente i singoli indici numerici ma questi devono essere raccolti in un vettore, ad esempio usando la funzione `c()`. Praticamente usiamo un vettore di indici per selezionare gli elementi desiderati dal nostro vettore iniziale. ```{r echo = TRUE, error = TRUE} # ERRATA selezione più valori @@ -130,7 +130,7 @@ my_numbers[c(1,2,3)] my_numbers[1:3] ``` -:::{.tip title="Selezionare non è Modificare" data-latex="[Selezionare non è Modificare]"} +:::{.tip title="Selezionare non è modificare" data-latex="[Selezionare non è modificare]"} Nota come l'operazione di selezione non modifichi l'oggetto iniziale. Pertanto è necessario salvare il risultato della selezione se si desidera mantenere le modifiche. ```{r, echo = TRUE} @@ -149,8 +149,8 @@ my_words ::: -:::{.warning title="Casi Estremi nella Selezione" data-latex="[Casi Estremi nella Selezione]"} -Cosa accade se utiliziamo un indice di posizione maggiore del numero di elementi del nostro vettore? +:::{.warning title="Casi estremi nella selezione" data-latex="[Casi estremi nella selezione]"} +Cosa accade se utilizziamo un indice di posizione maggiore del numero di elementi del nostro vettore? ```{r echo = TRUE} # Il mio vettore my_numbers <- c(2,4,6,8) @@ -180,7 +180,7 @@ my_numbers[0] ``` ::: -### Utilizzi Avanzati Selezione {#vector-selection-advanced} +### Utilizzi avanzati selezione {#vector-selection-advanced} Vediamo ora alcuni utilizzi avanzati della selezione di elementi di un vettore. In particolare impareremo a: @@ -190,17 +190,17 @@ Vediamo ora alcuni utilizzi avanzati della selezione di elementi di un vettore. - sostituire degli elementi - eliminare degli elementi -#### Operatori Relazionali e Logici {-} +#### Operatori relazionali e logici {-} -Un'utile funzione è quella di selezionare tra gli elementi di un vetore quelli che rispetano una certa condizione. Per fare questo dobbiamo specificare all'interno delle parentesi quadre la proposizione di interesse utilizzando gli operatori relazionali e logici (vedi Capitolo \@ref(operators-rel-log)). +Un'utile funzione è quella di selezionare tra gli elementi di un vettore quelli che rispettano una certa condizione. Per fare questo dobbiamo specificare all'interno delle parentesi quadre la proposizione di interesse utilizzando gli operatori relazionali e logici (vedi Capitolo \@ref(operators-rel-log)). Possiamo ad esempio selezionare da un vettore numerico tutti gli elementi maggiori di un certo valore, oppure selezionare da un vettore di caratteri tutti gli elementi uguali ad una data stringa. ```{r, echo = TRUE} -# Vettore numerico - seleziono elemeni maggiori di 0 +# Vettore numerico - seleziono elementi maggiori di 0 my_numbers <- -5:5 my_numbers[my_numbers >= 0] -# Vettore caratteri - seleziono elemeni uguali a "bar" +# Vettore caratteri - seleziono elementi uguali a "bar" my_words <- rep(c("foo", "bar"), times = 4) my_words[my_words == "bar"] ``` @@ -220,7 +220,7 @@ condition my_words[condition] ``` -#### Ordinare gli Elementi {-} +#### Ordinare gli elementi {-} Gli indici di posizione possono essere utilizzati per ordinare gli elementi di un vettore a seconda delle necessità. @@ -234,7 +234,7 @@ messy_vector[c(4,2,3,1)] messy_vector[c(2,4,1,3)] ``` -:::{.trick title="sort() vs order()" data-latex="[sort() vs order()]"} +:::{.trick title="\\texttt{sort()} vs \\texttt{order()}" data-latex="[\\texttt{sort()} vs \\texttt{order()}]"} Per ordinare gli elementi di un vettore in ordine crescente o decrescente (sia alfabetico che numerico), è possibile utilizzare la funzione `sort()` specificando l'argomento `decreasing`. Vedi l'help page della funzione per ulteriori informazioni (`?sort()`). ```{r, echo = TRUE} @@ -246,7 +246,7 @@ sort(my_letters) sort(messy_vector, decreasing = TRUE) ``` -Nota come esista anche la funzione `order()` ma questa sia un false-friend perchè non ci fornisce direttamente un vettore con gli elementi ordinati ma bensì gli indici di posizione per riordinare gli elementi (`?order()`). Vediamo nel seguente esempio come utilizzare questa funzione: +Nota come esista anche la funzione `order()` ma questa sia un false-friend perché non ci fornisce direttamente un vettore con gli elementi ordinati ma bensì gli indici di posizione per riordinare gli elementi (`?order()`). Vediamo nel seguente esempio come utilizzare questa funzione: ```{r, echo = TRUE} # Indici di posizione per riordinare gli elementi order(messy_vector) @@ -255,28 +255,28 @@ messy_vector[order(messy_vector)] ``` ::: -#### Combinazioni di Elementi {-} +#### Combinazioni di elementi {-} Gli stessi indici di posizione possono essere richiamati più volte per ripetere gli elementi nelle combinazioni desiderate formando un nuovo vettore. ```{r, echo = TRUE} my_numbers <- c(5,6,7,8) -# Ottengo un nuovo vettore con la combinazioen desiderata +# Ottengo un nuovo vettore con la combinazione desiderata my_numbers[c(1,2,2,3,3,3,4)] ``` -#### Modificare gli Elementi {-} +#### Modificare gli elementi {-} Un importante utilizzo degli indici riguarda la modifica di un elemento di un vettore. Per sostituire un vecchio valore con un nuovo valore, posso utilizzare la funzione *assign* (`<-` o `=`) come nell'esempio: ```{r, echo = TRUE} my_names <- c("Andrea", "Bianca", "Carlo") -# Modifico il nome "Bianca" in "Beatrice" +# Modifico il nome "Bianca" in "Beatrice" my_names[2] <- "Beatrice" my_names ``` -Per sostituire il valore viene indicato alla sinistra dell'operatore *assign* il valore che si vuole modificare e alla destra il nuovo valore. Nota come questa operazione possa essere usata per aggiungere anche nuovi elementi al vettore. +Per sostituire il valore viene indicato alla sinistra dell'operatore *assign* il valore che si vuole modificare e alla destra il nuovo valore. Nota come questa operazione possa essere usata per aggiungere anche nuovi elementi al vettore. ```{r, echo = TRUE} my_names[4] @@ -287,7 +287,7 @@ my_names ``` -#### Eliminare gli Elementi {-} +#### Eliminare gli elementi {-} Per **eliminare degli elementi** da un vettore, si indicano all'interno delle parentesi quadre gli indici di posizione degli elementi da eliminare preceduti dall'operatore `-` (*meno*). Nel caso di più elementi è anche possibile indicare il meno solo prima del comando `c()`, ad esempio il comando `x[c(-2,-4)]` diviene `x[-c(2,4)]`. @@ -325,7 +325,7 @@ x > 5 which(x > 5) ``` -Come vedete, la funzione `which()` essenzialmente restituisce la **posizione** (e non il valore) dove la condizione testata è `TRUE`. E' importante notare che queste due scritture sono equivalenti: +Come vedete, la funzione `which()` essenzialmente restituisce la **posizione** (e non il valore) dove la condizione testata è `TRUE`. È importante notare che queste due scritture sono equivalenti: ```{r} x[x > 5] @@ -343,13 +343,13 @@ Esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introductio 3. Dato il vettore `my_vector = c(2,4,6,8)` commenta il risultato del comando `my_vector[my_vector]` 4. Del vettore `y` seleziona tutti i valori minori di 13 o maggiori di 19 5. Del vettore `z` seleziona tutti i valori compresi tra 24 e 50 -6. Del vettore `s` seleziona tutti gli elementi uguali ad `"A"` -7. Del vettore `t` seleziona tutti gli elementi diversi da `"B"` +6. Del vettore `s` seleziona tutti gli elementi uguali ad `"A"` +7. Del vettore `t` seleziona tutti gli elementi diversi da `"B"` 8. Crea un nuovo vettore `u` identico a `s` ma dove le `"A"` sono sostituite con la lettera `"U"` 9. Elimina dal vettore `z` i valori 28 e 42 -## Funzioni ed Operazioni {#vector-functions} +## Funzioni e operazioni {#vector-functions} Vediamo ora alcune utili funzioni e comuni operazioni che è possibile svolgere con i vettori (vedi Tabella \@ref(tab:table-vector-operators)). @@ -374,16 +374,16 @@ if (knitr::is_latex_output()) { } kableExtra::kable(vector_operators, col.names = c("Funzione", "Descrizione"), - escape = escape, caption = "Funzioni e operazioni con vettori") %>% + escape = escape, caption = "Funzioni e operazioni con vettori") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = F, latex_options = c("hold_position")) ``` -Nota che l'esecuzione di operazioni matematiche (e.g., `+`, `-`, `*`, `/` etc.) è possibile sia rispetto ad un singolo valore sia rispetto ad un altro vettore: +Nota che l'esecuzione di operazioni matematiche (ad es. `+`, `-`, `*`, `/` etc.) è possibile sia rispetto ad un singolo valore sia rispetto ad un altro vettore: - **Singolo valore** - l'operazione sarà svolta per ogni elemento del vettore rispetto al singolo valore fornito. -- **Altro vettore** - l'operazione sarà svolta per ogni coppia di elementi dei due vettori. E' quindi necessario che i due vettori abbiano la **stessa lunghezza**, ovvero lo stesso numero di elementi. +- **Altro vettore** - l'operazione sarà svolta per ogni coppia di elementi dei due vettori. È quindi necessario che i due vettori abbiano la **stessa lunghezza**, ovvero lo stesso numero di elementi. ```{r, echo = TRUE} x <- 1:5 @@ -396,17 +396,17 @@ x + 10 x + y ``` -:::{.warning title="Vettori di Diversa Lunghezza" data-latex="[Vettori di Diversa Lunghezza]"} +:::{.warning title="Vettori di diversa lunghezza" data-latex="[Vettori di diversa lunghezza]"} Qualora i vettori differiscano per la loro lunghezza, R ci presenterà un warning avvisandoci del problema ma eseguirà comunque l'operazione utilizzando più volte il vettore più corto. ```{r, echo = TRUE, error = TRUE} x + c(1, 2) ``` -Tuttavia, compiere operazioni tra vettori di diversa lunghezza (anche se multipli) dovrebbe essere evitato poichè è facile causa di errori ed incomprensioni. +Tuttavia, compiere operazioni tra vettori di diversa lunghezza (anche se multipli) dovrebbe essere evitato poiché è facile causa di errori ed incomprensioni. ::: :::{.design title="Vectorized Operations" data-latex="[Vectorized Operations]"} -In R la maggior parte degli operatori sono *vettorizzati*, ovvero calcolano direttamente il risultato per ogni elemento di un vettore. Questo è un grandissimo vantaggio poichè ci permette di essere molto efficienti e coincisi nel codice. +In R la maggior parte degli operatori sono *vettorizzati*, ovvero calcolano direttamente il risultato per ogni elemento di un vettore. Questo è un grandissimo vantaggio poiché ci permette di essere molto efficienti e coincisi nel codice. Senza vettorizzazione, ogni operazione tra due vettori richiederebbe di specificare l'operazione per ogni elemento del vettore. Nel precedente esempio della somma tra `x` e `y` avremmo dovuto usare il seguente codice: ```{r, echo = TRUE} @@ -439,16 +439,16 @@ Esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introductio ## Data Type {#data-type} -Abbiamo visto come sia necessario che in un vettore tutti gli elementi siano della stessa tipologia. Avremo quindi diversi tipi di vettori a seconda della tiopologia di dati che contengono. +Abbiamo visto come sia necessario che in un vettore tutti gli elementi siano della stessa tipologia. Avremo quindi diversi tipi di vettori a seconda della tipologia di dati che contengono. In R abbiamo 4 principali tipologie di dati, ovvero tipologie di valori che possono essere utilizzati: -- `character` - *Stringhe di caratteri* i cui valori alfannumerici vengono delimitati dalle doppie vigolette `"Hello world!"` o virgolette singole `'Hello world!'`. +- `character` - *Stringhe di caratteri* i cui valori alfanumerici vengono delimitati dalle doppie virgolette `"Hello world!"` o virgolette singole `'Hello world!'`. - `double` - *Valori reali* con o senza cifre decimali ad esempio `27` o `93.46`. - `integer` - *Valori interi* definiti apponendo la lettera `L` al numero desiderato, ad esempio `58L`. - `logical` - *Valori logici* `TRUE` e `FALSE` usati nelle operazioni logiche. -Possiamo verificare la tipologia di un valore utlizzando la funzione `typeof()`. +Possiamo verificare la tipologia di un valore utilizzando la funzione `typeof()`. ```{r, echo = TRUE} typeof("foo") @@ -459,24 +459,24 @@ typeof(2021L) # nota la lettera L typeof(TRUE) ``` -Esistono molte altre tipologie di dati tra cui `complex` (per rappresentare i numeri complessi del tipo $x + yi$) e `Raw` (usati per rappresenttare i valori come bytes) che però riguardano usi poco comuni o comunque molto avanzati di R e pertanto non verranno trattati. +Esistono molte altre tipologie di dati tra cui `complex` (per rappresentare i numeri complessi del tipo $x + yi$) e `Raw` (usati per rappresentare i valori come bytes) che però riguardano usi poco comuni o comunque molto avanzati di R e pertanto non verranno trattati. -:::{.design title="Tutta una Questione di Bit" data-latex="[Tutta una Questione di Bit]"} +:::{.design title="Tutta una questione di bit" data-latex="[Tutta una questione di bit]"} Questa distinzione tra le varie tipologie di dati deriva dalla modalità con cui il computer rappresenta internamente i diversi valori. Sappiamo infatti che il computer non possiede caratteri ma solamente bits, ovvero successioni di 0 e 1 ad esempio 01000011. -Senza scendere nel dettaglio, per ottimizzare l'uso della memoria i diversi valori vengono *"mappati"* utilizzando i bits in modo differente a seconda delle tipologie di dati. Pertanto in R il valore `24` sarà rappresentato diversamente a seconda che sia definitio come una stringa di caratteri (`"24"`), un numero intero (`24L`) o un numero double (`24`). +Senza scendere nel dettaglio, per ottimizzare l'uso della memoria i diversi valori vengono *"mappati"* utilizzando i bits in modo differente a seconda delle tipologie di dati. Pertanto in R il valore `24` sarà rappresentato diversamente a seconda che sia definito come una stringa di caratteri (`"24"`), un numero intero (`24L`) o un numero double (`24`). -#### Integer vs Double {-} +#### Integer vs double {-} -In particolare un aspetto poco intuitivo riguarda la differenza tra valori `double` e `integer`. Mentre i valori interi possono essere rappresentati con precisione dal computer, non tutti i valori reali posssono essere rappresentati esattamente utilizzando il numero massimo di 64 bit. In questi casi i loro valori vengonno quindi approsimati e, sebbene questo venga fatto con molta precisione, a volte potrebbe portare a dei risultati inaspettati. Nota infatti come nell'esempio seguente non otteniamo zero, ma osserviamo un piccolo errore dovuto all'approsimazione dei valori `double`. +In particolare un aspetto poco intuitivo riguarda la differenza tra valori `double` e `integer`. Mentre i valori interi possono essere rappresentati con precisione dal computer, non tutti i valori reali possono essere rappresentati esattamente utilizzando il numero massimo di 64 bit. In questi casi i loro valori vengono quindi approssimati e, sebbene questo venga fatto con molta precisione, a volte potrebbe portare a dei risultati inaspettati. Nota infatti come nell'esempio seguente non otteniamo zero, ma osserviamo un piccolo errore dovuto all'approssimazione dei valori `double`. ```{r, echo = TRUE} my_value <- sqrt(2)^2 # dovrei ottenere 2 -my_value - 2 # dovrei ottenre 0 +my_value - 2 # dovrei ottenere 0 ``` -E' importante tenere a mente questo problema nei test di ugualianza dove l'utilizzo dell'operatore `==` potrebbe generare delle risposte inaspettate. In genere viene quindi preferita la funzione `all.equal()` che prevede un certo margine di tolleranza (vedi `?all.equal()` per ulteriori dettagli). +È importante tenere a mente questo problema nei test di uguaglianza dove l'utilizzo dell'operatore `==` potrebbe generare delle risposte inaspettate. In genere viene quindi preferita la funzione `all.equal()` che prevede un certo margine di tolleranza (vedi `?all.equal()` per ulteriori dettagli). ```{r, echo = TRUE} -my_value == 2 # Problema di approsimazione +my_value == 2 # Problema di approssimazione all.equal(my_value, 2) # Test con tolleranza ``` @@ -487,7 +487,7 @@ Vediamo ora i diversi tipi di vettori a seconda della tipologia di dati utilizza ### Character -I vettori formati da stringhe di caratteri sono definiti vettori di caratteri. Per valutare la tipologia di un oggetto possiamo utilizzare la funzione `class()`, mentre ricordiamo che la funzionne `typeof()` valuta la tipologia di dati. In questo caso otteniamo per entrambi il valore `character`. +I vettori formati da stringhe di caratteri sono definiti vettori di caratteri. Per valutare la tipologia di un oggetto possiamo utilizzare la funzione `class()`, mentre ricordiamo che la funzione `typeof()` valuta la tipologia di dati. In questo caso otteniamo per entrambi il valore `character`. ```{r, echo = TRUE} my_words<-c("Foo","Bar","foo","bar") @@ -497,7 +497,7 @@ class(my_words) # tipologia oggetto typeof(my_words) # tipologia dati ``` -Non è possibile eseguire operazioni aritmetiche con vettori di caratteri ma solo valutare relazioni di uguaglianza o disuguaglianza ripetto ad un'altra stringa. +Non è possibile eseguire operazioni aritmetiche con vettori di caratteri ma solo valutare relazioni di uguaglianza o disuguaglianza rispetto ad un'altra stringa. ```{r, echo = TRUE, error = TRUE} my_words + "foo" @@ -535,7 +535,7 @@ class(my_integers) # tipologia oggetto typeof(my_integers) # tipologia dati ``` -Come per i vettori numerici, i vettori di valori interi possono esssere utilizzati per compiere qualsiasi tipo di operazioni matematiche o logico-relazionali. Nota tuttavia che operazioni tra integer e doubles restituiranno dei doubles ed anche nel caso di operazioni tra integers il risultato potrebbe non essere un integer. +Come per i vettori numerici, i vettori di valori interi possono essere utilizzati per compiere qualsiasi tipo di operazioni matematiche o logico-relazionali. Nota tuttavia che operazioni tra integer e doubles restituiranno dei doubles ed anche nel caso di operazioni tra integers il risultato potrebbe non essere un integer. ```{r, echo = TRUE} is.integer(5L * 5) # integer e double @@ -556,7 +556,7 @@ class(my_logical) # tipologia oggetto typeof(my_logical) # tipologia dati ``` -I vettori di valori logici possono esssere utilizzati con gli operatori logici. +I vettori di valori logici possono essere utilizzati con gli operatori logici. ```{r, echo = TRUE} my_logical & c(FALSE, TRUE, TRUE) @@ -564,7 +564,7 @@ my_logical & c(FALSE, TRUE, TRUE) my_logical & c(0, 1, 3) ``` -Tuttavia ricordiamo che ai valori `TRUE` e `FALSE` sono associati rispettivamente i valori numerici 1 e 0 (o più precisamente i valori interi `1L` e `0L`). Pertanto è possibile eseguire anche operazioni matematiche dove verrano automaticamente considerati i rispettivi valori numerici. Ovviamente il risultato ottenuto sarà un valore numerico e non logico. +Tuttavia ricordiamo che ai valori `TRUE` e `FALSE` sono associati rispettivamente i valori numerici 1 e 0 (o più precisamente i valori interi `1L` e `0L`). Pertanto è possibile eseguire anche operazioni matematiche dove verranno automaticamente considerati i rispettivi valori numerici. Ovviamente il risultato ottenuto sarà un valore numerico e non logico. ```{r, echo = TRUE} TRUE * 10 @@ -573,7 +573,7 @@ FALSE * 10 ``` -:::{.trick title="sum() e mean()" data-latex="[sum() e mean()]"} +:::{.trick title="\\texttt{sum()} e \\texttt{mean()}" data-latex="[\\texttt{sum()} e \\texttt{mean()}]"} Utilizzando le funzioni `sum()` e `mean()` con un vettore logico, possiamo valutare rispettivamente il numero totale e la percentuale di elementi che hanno soddisfatto una certa condizione logica. ```{r, echo = TRUE} @@ -587,11 +587,11 @@ mean(my_values > 0) # percentuale numeri positivi :::{.design title="is.* adn as.* Function Families" data-latex="[is.* adn as.* Function Families]"} -Esistono due famiglie di funzioni che permettono rispettivamene di testare e di modificare la tipologia dei dati. +Esistono due famiglie di funzioni che permettono rispettivamente di testare e di modificare la tipologia dei dati. #### is.* Family {-} -Per testare se un certo valore (o un vettore di valori) appartiene ad una specifica tipologia di dati, possimao utilizzare una tra le seguenti funzioni: +Per testare se un certo valore (o un vettore di valori) appartiene ad una specifica tipologia di dati, possiamo utilizzare una tra le seguenti funzioni: - `is.vector()` - valuta se un oggetto è un generico vettore di qualsiasi tipo ```{r, echo = TRUE, eval=FALSE} @@ -639,7 +639,7 @@ is.logical(TRUE) # TRUE #### as.* Family {-} -Per modificare la tipologia di un certo valore (o un vettore di valori), possimao utilizzare una tra le seguenti funzioni: +Per modificare la tipologia di un certo valore (o un vettore di valori), possiamo utilizzare una tra le seguenti funzioni: - `as.character()` - trasforma l'oggetto in una stringa ```{r, echo = TRUE} @@ -650,19 +650,19 @@ as.character(TRUE) - `as.numeric()` - trasforma l'oggetto in un `double` ```{r, echo = TRUE} as.numeric("foo") # Non valido con stringhe di caratteri -as.numeric("2021") # Valido per stinghe di cifre +as.numeric("2021") # Valido per stringhe di cifre as.numeric(2021L) as.numeric(TRUE) ``` - `as.double()` - trasforma l'oggetto in un `double` ```{r, echo = TRUE} -as.double("2021") # Valido per stinghe di cifre +as.double("2021") # Valido per stringhe di cifre as.double(2021L) as.double(TRUE) ``` - `as.integer()` - trasforma l'oggetto in un `integer` ```{r, echo = TRUE} -as.integer("2021") # Valido per stinghe di cifre +as.integer("2021") # Valido per stringhe di cifre as.integer(2021.6) # Tronca la parte decimale as.integer(TRUE) ``` @@ -677,25 +677,25 @@ as.logical(2021L) ### Valori speciali -Vediamo infine alcuni valori speciali utilizzatti in R con dei particolari significati e che richiedono specifici accorgimenti quando vengono manipolati: +Vediamo infine alcuni valori speciali utilizzati in R con dei particolari significati e che richiedono specifici accorgimenti quando vengono manipolati: -- `NULL`- rappresenta l'oggetto nullo, ovvero l'assenza di un oggetto. Spesso viene restituito dalle funzioni quano il loro output è indefinito. -- `NA` - rappresenta un dato mancate (*Not Available*). E' un valore costante di lunghezza 1 che può essere utlizzato per qualsiasi tipologia di dati. -- `NaN` - indica un risulato matematico che non può essere rappresentato come un valore numerico (*Not A Number*). E' un valore costante di lunghezza 1 che può essere utlizzato come valore numerico (non intero). +- `NULL`- rappresenta l'oggetto nullo, ovvero l'assenza di un oggetto. Spesso viene restituito dalle funzioni quando il loro output è indefinito. +- `NA` - rappresenta un dato mancate (*Not Available*). È un valore costante di lunghezza 1 che può essere utilizzato per qualsiasi tipologia di dati. +- `NaN` - indica un risultato matematico che non può essere rappresentato come un valore numerico (*Not A Number*). È un valore costante di lunghezza 1 che può essere utilizzato come valore numerico (non intero). ```{r, echo = TRUE} 0/0 sqrt(-1) ``` -- `Inf` (o `-Inf`) - indica un risultato matematico inifinito (o infinito negativo). E' anche utilizzato per rappresentare numeri estremamente grandi. +- `Inf` (o `-Inf`) - indica un risultato matematico infinito (o infinito negativo). È anche utilizzato per rappresentare numeri estremamente grandi. ```{r, echo = TRUE} pi^650 -pi/0 ``` -E' importante essere consapevoli delle caratteristiche di questi valori poichè presentano dei comportamenti peculiari che, se non corretamente gestiti, possono generare conseguenti errori nei codici. Descriviamo ora alcune delle carateristiche più importanti. +È importante essere consapevoli delle caratteristiche di questi valori poiché presentano dei comportamenti peculiari che, se non correttamente gestiti, possono generare conseguenti errori nei codici. Descriviamo ora alcune delle caratteristiche più importanti. -#### Lunghezza Elementi {-} +#### Lunghezza elementi {-} Notiamo innanzitutto come mentre `NULL` sia effettivamente un oggetto nullo, ovvero privo di dimensione, `NA` sia uno speciale valore che rappresenta la presenza di un dato mancate. Pertanto `NA`, a differenza di `NULL`, è effettivamente un valore di lunghezza 1. @@ -717,9 +717,9 @@ length(c(1:5, NaN)) length(c(1:5, Inf)) ``` -#### Propagazione Valori {-} +#### Propagazione valori {-} -Altra importante caratteristica è quella che viene definita *propagazione* dei valori ovvero le operazioni che includono questi speciali valori resituiscono a loro volta lo stesso speciale. Ciò significa che questi valori si propagheranno di risultato in risultato all'interno del nostro codice se non opportunamente gestiti. +Altra importante caratteristica è quella che viene definita *propagazione* dei valori ovvero le operazioni che includono questi speciali valori restituiscono a loro volta lo stesso speciale. Ciò significa che questi valori si propagheranno di risultato in risultato all'interno del nostro codice se non opportunamente gestiti. - `NULL`- osserviamo come se il valore `NULL` viene utilizzato in una qualsiasi operazione matematica il risultato sarà un vettore numerico vuoto di dimensione 0, il quale può essere interpretato in modo simile (seppur non identico) al valore `NULL` ```{r, echo = TRUE} @@ -727,15 +727,15 @@ res_NULL <- NULL * 3 length(res_NULL) res_NULL ``` -- `NA` - quando `NA` viene utilizzato in una qualsiasi operazione matematica il risultato sarà nuovamene un `NA`. +- `NA` - quando `NA` viene utilizzato in una qualsiasi operazione matematica il risultato sarà nuovamente un `NA`. ```{r, echo = TRUE} NA * 3 ``` -- `NaN` - quando `NaN` viene utilizzato in una qualsiasi operazione matematica il risultato sarà nuovamene un `NaN`. +- `NaN` - quando `NaN` viene utilizzato in una qualsiasi operazione matematica il risultato sarà nuovamente un `NaN`. ```{r, echo = TRUE} NaN * 3 ``` -- `Inf` (o `-Inf`) - qualora `Inf` (o `-Inf`) siano utilizzati in un'operazione matematica il risultato seguirà le comuni regole delle operazioni tra infiti. +- `Inf` (o `-Inf`) - qualora `Inf` (o `-Inf`) siano utilizzati in un'operazione matematica il risultato seguirà le comuni regole delle operazioni tra infiniti. ```{r, echo = TRUE, eval = FALSE} Inf - 3 # Inf @@ -750,37 +750,37 @@ Inf * -Inf # -Inf Inf / Inf # NaN ``` -#### Testare Valori {-} +#### Testare valori {-} -E' importante ricordare come per testare l apresenza di uno di questi valori speciali siano presenti delle funzioni specifiche della famiglia `is.*`. Non deve mai essere utlizzato il comune operatore di uguaglianza `==` poichè non fornisce i risultai corretti. +È importante ricordare come per testare la presenza di uno di questi valori speciali siano presenti delle funzioni specifiche della famiglia `is.*`. Non deve mai essere utilizzato il comune operatore di uguaglianza `==` poiché non fornisce i risultai corretti. - `is.null` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} NULL == NULL # logical(0) is.null(NULL) # TRUE ``` - `is.na` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} NA == NA # NA is.na(NA) # TRUE ``` - `is.nan` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} NaN == NaN # NA is.nan(NaN) # TRUE ``` - `Inf` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} Inf == Inf # TRUE considero anche il segno is.infinite(Inf) # TRUE sia per Inf che -Inf ``` -#### Operatori Logici {-} +#### Operatori logici {-} Un particolare comportamento riguarda i risultati ottenute con gli operatori logici dove la *propagazione* del valore non segue sempre le attese. Osserviamo i diversi casi: -- `NULL`- ottenimo come da attese un vettore logico vuoto di dimensione 0 -```{r, echo = TRUE, eval = FALSE} +- `NULL`- otteniamo come da attese un vettore logico vuoto di dimensione 0 +```{r, echo = TRUE, eval = FALSE} TRUE & NULL # logical(0) TRUE | NULL # logical(0) @@ -788,7 +788,7 @@ FALSE & NULL # logical(0) FALSE | NULL # logical(0) ``` - `NA` - non otteniamo come da attese sempre il valore `NA` ma in alcune condizioni la proposizione sara `TRUE` o `FALSE` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} TRUE & NA # NA TRUE | NA # TRUE @@ -796,15 +796,15 @@ FALSE & NA # FALSE FALSE | NA # NA ``` - `NaN` - otteniamo gli stessi risultati del caso precedente utilizzando il valore `NA` -```{r, echo = TRUE, eval = FALSE} +```{r, echo = TRUE, eval = FALSE} TRUE & NaN # NA TRUE | NaN # TRUE FALSE & NaN # FALSE FALSE | NaN # NA ``` -- `Inf` - essendo un valore numerico diverso da zero otteniamo i rissultati secondo le attese -```{r, echo = TRUE, eval = FALSE} +- `Inf` - essendo un valore numerico diverso da zero otteniamo i risultati secondo le attese +```{r, echo = TRUE, eval = FALSE} TRUE & Inf # TRUE TRUE | Inf # TRUE @@ -818,30 +818,28 @@ Un comportamento tanto strano per quanto riguarda l'utilizzo del valore `NA` con is.logical(NA) ``` -Pertanto le proposizioni vengono correttamente seguendo le comuni regole. Nel caso di `TRUE | NA` la proposizione è giudicata `TRUE` perchè con l'operatore di disgiunzione è sufficiente che una delle due parti sia vera avvinchè la proposizione sia vera. Nel caso di `FALSE & NA`, invece, la proposizione è giudicata `FALSE` perchè con l'operatore di congiunzione è sufficiente che una delle due parti sia falsa avvinchè la proposizione sia falsa. LA non risposta indicata da `NA` i questi casi è ininfluente, mentre determina il risultato nei restanti casi quando la seconda parte della proposizione deve essere necessariamente valutata. A questo punto gli operatori restituiscono `NA` poichè incapaci di determinare la risposta. +Pertanto le proposizioni vengono correttamente seguendo le comuni regole. Nel caso di `TRUE | NA` la proposizione è giudicata `TRUE` perché con l'operatore di disgiunzione è sufficiente che una delle due parti sia vera affinché la proposizione sia vera. Nel caso di `FALSE & NA`, invece, la proposizione è giudicata `FALSE` perché con l'operatore di congiunzione è sufficiente che una delle due parti sia falsa affinché la proposizione sia falsa. LA non risposta indicata da `NA` i questi casi è ininfluente, mentre determina il risultato nei restanti casi quando la seconda parte della proposizione deve essere necessariamente valutata. A questo punto gli operatori restituiscono `NA` poiché incapaci di determinare la risposta. -Per quanto riguarda il caso del valore `NaN` è sufficinete ricordare che tale valore sia comunque un valore numerico di cui però non è possibile identificare il valore. +Per quanto riguarda il caso del valore `NaN` è sufficiente ricordare che tale valore sia comunque un valore numerico di cui però non è possibile identificare il valore. ```{r, echo = TRUE} is.numeric(NaN) ``` -Tutti i valori numerici sono considerati validi nelle operazioni logiche, dove qualsiais numero diveros da zero è valutato `TRUE`. Pertanto viene seguito lo stesso ragionamento precedente, quando non è necessario valutare entrambe le parti della proposizione viene fornita una risposta, mentre si ottiene `NA` negli altri casi quando R è obbligato a valutare entrambe la parti ma è incapace di fornire una risspossta poichè non può determinare il valore di `NaN`. +Tutti i valori numerici sono considerati validi nelle operazioni logiche, dove qualsiasi numero diverso da zero è valutato `TRUE`. Pertanto viene seguito lo stesso ragionamento precedente, quando non è necessario valutare entrambe le parti della proposizione viene fornita una risposta, mentre si ottiene `NA` negli altri casi quando R è obbligato a valutare entrambe la parti ma è incapace di fornire una risposta poiché non può determinare il valore di `NaN`. ::: -:::{.design title="L'importanza dei Dati Mancanti" data-latex="[L'importanza dei Dati Mancanti]"} -Lavorare in presenza di dati mancanti accadrà nella maggior parte dei casi. Molte delle funzioni presenti in R hanno già delle opzioni per rimuovere automaticamete eventuali dati mancanti così da poter ottenre correttamete i risultati. +:::{.design title="L'importanza dei dati mancanti" data-latex="[L'importanza dei dati mancanti]"} +Lavorare in presenza di dati mancanti accadrà nella maggior parte dei casi. Molte delle funzioni presenti in R hanno già delle opzioni per rimuovere automaticamente eventuali dati mancanti così da poter ottenere correttamente i risultati. ```{r, echo = TRUE} my_sample <- c(2,4,6,8, NA) mean(my_sample) mean(my_sample, na.rm = TRUE) ``` -Tuttavia, è importante non avvalersi in modo automatico di tali opzioni ma avere cura di valutare attentamente la presenza di dati mancanti. Questo ci permetterà di indagare possibili pattern riguardanti i dati mancanti e valutare la loro possibile influenza sui nostri risultati e la validità elle conclusioni. +Tuttavia, è importante non avvalersi in modo automatico di tali opzioni ma avere cura di valutare attentamente la presenza di dati mancanti. Questo ci permetterà di indagare possibili pattern riguardanti i dati mancanti e valutare la loro possibile influenza sui nostri risultati e la validità elle conclusioni. -Inoltre sarà fondamentale controllare sempre l'effittiva dimensione del campione utilizzato nelle vari analisi. Ad esempio se non valutato attentamente potremmo non ottenere il numero effettivo di valori su cui è stata calcolata precedentemente la media. +Inoltre sarà fondamentale controllare sempre l'effettiva dimensione del campione utilizzato nelle vari analisi. Ad esempio se non valutato attentamente potremmo non ottenere il numero effettivo di valori su cui è stata calcolata precedentemente la media. ```{r echo = TRUE} length(my_sample) # NA incluso length(my_sample[!is.na(my_sample)]) # NA escluso ``` ::: - - diff --git a/10-factors.Rmd b/10-factors.Rmd index c964441..cff2f23 100644 --- a/10-factors.Rmd +++ b/10-factors.Rmd @@ -14,17 +14,17 @@ library(kableExtra) In questo capitolo vedremo i *fattori*, una speciale tipologia di vettori utilizzata per salvare informazioni riguardanti una variabile categoriale (nominale o ordinale). Tuttavia, prima di introdurre i fattori, descriveremo che cosa sono gli attributi di un oggetto. Questi ci permetteranno successivamente di capire meglio il funzionamento dei fattori. -## Attributi di un Oggetto {#attributes} +## Attributi di un oggetto {#attributes} In R, gli oggetti possiedono quelli che sono definiti *attributi*, ovvero delle utili informazioni riguardanti l'oggetto stesso, una sorta di *metadata*. Queste informazioni non interferiscono con i valori contenuti negli oggetti nè vengono normalmente mostrati nell'output di un oggetto. Tuttavia, si rivelano particolarmente utili in alcune circostanze e permettono di fornire speciali informazioni associate ad un determinato oggetto. Gli oggetti possiedono diversi attributi a seconda della loro tipologia. Tuttavia, tra quelli principalmente usati troviamo: - **Classe** (`class`) - la classe (o tipologia) di un oggetto. Ci permette di verificare la tipologia di struttura dati di un particolare oggetto. -- **Nomi** (`names`) - nomi degli elementi di un oggetto. Permette ad esempio di assegnare dei nomi agli elementi un vettore o alle righe e colonne di una matrice o dataframe. +- **Nomi** (`names`) - nomi degli elementi di un oggetto. Permette ad esempio di assegnare dei nomi agli elementi un vettore o alle righe e colonne di una matrice o dataframe. - **Dimensione** (`dim`) - la dimensione dell'oggetto. Questo attributo non è disponibile per i vettori ma sarà particolarmente importante nel caso delle matrici e dataframe. -Per valutare ee eventualmente modifiacare gli attributi di un oggetto esistono delle specifiche funzioni dedicate. Ad esempio abbiamo: +Per valutare ed eventualmente modificare gli attributi di un oggetto esistono delle specifiche funzioni dedicate. Ad esempio abbiamo: - `attributes()` - elenca tutti gli attributi di un oggetto - `class()` - accede all'attributo `class` di un oggetto @@ -34,7 +34,7 @@ Per valutare ee eventualmente modifiacare gli attributi di un oggetto esistono d Vediamo ora alcuni utilizzi degli attributi con i vettori. Gli attributi nel caso delle altre tipologie di oggetti, invece, saranno trattati nei rispettivi capitoli. -### Attributi di un Vettore +### Attributi di un vettore Vediamo come inizialmente un generico vettore non possiede alcun attributo vettore. @@ -63,7 +63,7 @@ dim(my_vector) length(my_vector) ``` -#### Nomi Elementi{-} +#### Nomi elementi {-} Inizialmente gli elementi di un vettore non possiedono nomi. @@ -78,14 +78,14 @@ names(my_vector) <- paste0("Item_", 1:10) my_vector ``` -Questa procedura ci pemette di ottenere quello che viene definito un *named vector*. Possiamo vedere come i nomi degli elementi compaiano ora tra gli attributi dell'oggetto. +Questa procedura ci permette di ottenere quello che viene definito un *named vector*. Possiamo vedere come i nomi degli elementi compaiano ora tra gli attributi dell'oggetto. ```{r} attributes(my_vector) ``` :::{.trick title="Selezione Named Vectors" data-latex="[Selezione Named Vectors]"} -Una particolare utlizzo dei named vectors riguarda la selezione dei valori tramite i nomi degli elementi. Nota che per un corretto funzionameto è necessario che tutti gli elementi possiedano nomi differenti. +Una particolare utilizzo dei named vectors riguarda la selezione dei valori tramite i nomi degli elementi. Nota che per un corretto funzionamento è necessario che tutti gli elementi possiedano nomi differenti. ```{r, echo = TRUE} my_vector[c("Item_3", "Item_5")] @@ -119,7 +119,7 @@ my_factor Nota come non sia necessario specificare l'argomento `levels`. I livelli della variabile, infatti, vengono determinati automaticamente a partire dai dati presenti e ordinati in ordine alfabetico. Tuttavia, specificare i livelli nella creazione di un fattore ci permette di definire a piacere l'ordine dei livelli ed anche includere eventuali livelli non presenti nei dati. -### Funzionamento Fatori +### Funzionamento fattori Cerchiamo ora di capire meglio la struttura dei fattori e l'utilizzo degli attributi. @@ -127,26 +127,26 @@ Cerchiamo ora di capire meglio la struttura dei fattori e l'utilizzo degli attri attributes(my_factor) ``` -Vediamo come la classe dell'oggetto sia `factor` e abbiamo aunceh un ulteriore attributo `levels` dove sono salvati i posibili livelli della nostra variabile. Ma attenzione adesso a cosa otteniamo quando valutiamo la tipologia di dati contenuti nel fattore e la sua sruttura. +Vediamo come la classe dell'oggetto sia `factor` e abbiamo anche un ulteriore attributo `levels` dove sono salvati i possibili livelli della nostra variabile. Ma attenzione adesso a cosa otteniamo quando valutiamo la tipologia di dati contenuti nel fattore e la sua struttura. ```{r, echo = TRUE} # Tipologia dati typeof(my_factor) -# Sstrutura +# Struttura str(my_factor) ``` -Ci saremmo aspettati di ottenere `character` pensando che all'interno del fattore fossero salvati vari valori della nostra variabile come stringhe. Invece il fattore è formato da `integer` e possimao osservare come effetivamente l'output del comando `str()` riporta dei valori numerici (oltre ai livelli della variabile). Come spiegarsi tutto questo? +Ci saremmo aspettati di ottenere `character` pensando che all'interno del fattore fossero salvati vari valori della nostra variabile come stringhe. Invece il fattore è formato da `integer` e possiamo osservare come effettivamente l'output del comando `str()` riporta dei valori numerici (oltre ai livelli della variabile). Come spiegarsi tutto questo? -La soluzione è molto semplice. Nel creare un fattore, R valuta i livelli presennti creando l'attributo `levels` e poi sostituisce ad ogni elemento un valore numerico che indica il livello della variabile. Pertanto nel nostro esempio avremmo che il valore `1` è associato al livello `"azzurro"`, il valore `2` a `"marrone"` e il valore `3` a `"verde"`. Questo approccio permette di ottimizzare l'uso della memoria tuttavia inizialmete potrebbe risultare poco intuitivo e causa di errori. +La soluzione è molto semplice. Nel creare un fattore, R valuta i livelli presenti creando l'attributo `levels` e poi sostituisce ad ogni elemento un valore numerico che indica il livello della variabile. Pertanto nel nostro esempio avremmo che il valore `1` è associato al livello `"azzurro"`, il valore `2` a `"marrone"` e il valore `3` a `"verde"`. Questo approccio permette di ottimizzare l'uso della memoria tuttavia inizialmente potrebbe risultare poco intuitivo e causa di errori. -:::{.warning title="Attenti alla Conversione" data-latex="[Attenti alla Conversione]"} -Uno dei principali errori riguarda la conversione da un fattore ad un normale vettore. Nel caso volessimo ottenere un vettore di caratteri possimo usare la funzione `as.character()` ottenendo il risultato voluto. +:::{.warning title="Attenti alla conversione" data-latex="[Attenti alla conversione]"} +Uno dei principali errori riguarda la conversione da un fattore ad un normale vettore. Nel caso volessimo ottenere un vettore di caratteri possiamo usare la funzione `as.character()` ottenendo il risultato voluto. ```{r, echo = TRUE} as.character(my_factor) ``` -Tuttavia, se volessimo ottenere un vettore numerico, dobbiamo prestare particolare attenzione. Considera il seguente esempio dove abbiamo gli anni di istruzione di alcuni partecipanti ad uno studio. Potremmo eseguire alcune analissi considerando questa variable come categoriale per poi ritrasformarla in una variebile numerica per compiere altre analisi. Osserva cosa succede +Tuttavia, se volessimo ottenere un vettore numerico, dobbiamo prestare particolare attenzione. Considera il seguente esempio dove abbiamo gli anni di istruzione di alcuni partecipanti ad uno studio. Potremmo eseguire alcune analisi considerando questa variable come categoriale per poi ritrasformarla in una variabile numerica per compiere altre analisi. Osserva cosa succede ```{r, echo = TRUE} # Creo la mia variabile come fattore school_years<-factor(c(11, 8, 4, 8, 11, 4, 11, 8)) @@ -155,27 +155,27 @@ school_years # Trasformo in un vettore numerico as.numeric(school_years) ``` -In modo forse inaspettato non otteniamo i valori originali (i.e., 4, 8, 11) ma dei valori differenti. Questi in realtà sono i valori numerici che R ha usato per associare ogni elemento al corripondente livello. Per ottenre i valori corretti dobbiamo eseguire il seguente comando: +In modo forse inaspettato non otteniamo i valori originali (i.e., 4, 8, 11) ma dei valori differenti. Questi in realtà sono i valori numerici che R ha usato per associare ogni elemento al corrispondente livello. Per ottenere i valori corretti dobbiamo eseguire il seguente comando: ```{r, echo = TRUE} as.numeric(as.character(school_years)) ``` Questo ci permette di sostituire prime i valori con le giuste *etichette*, ovvero i livelli della variabile, e successivamente convertire il tutto in un vettore numerico. -E' importante prestare molta attenzione in questi casi poichè un eventuale errore potrebbe non risultare subito evidente. +È importante prestare molta attenzione in questi casi poiché un eventuale errore potrebbe non risultare subito evidente. ::: -### Operazioni Fattori +### Operazioni fattori Ora che abbiamo capito il funzionamento dei fattori vediamo alcune comuni operazioni. -#### Rinominare i Livelli {-} +#### Rinominare i livelli {-} -E possibile rinominare i livelli di un fattore utilizzando la funzione `levels()` quesa ci permette di accedere agli attuali livelli ed eventualmente ssostituirli. +E possibile rinominare i livelli di un fattore utilizzando la funzione `levels()` questa ci permette di accedere agli attuali livelli ed eventualmente sostituirli. ```{r, echo = TRUE} my_factor -# Attuli livelli +# Attuali livelli levels(my_factor) # Rinomino i livelli @@ -183,9 +183,9 @@ levels(my_factor) <- c("brown", "blue", "green") my_factor ``` -#### Ordinare i Livelli {-} +#### Ordinare i livelli {-} -E' importante non confondere l'ordinare i livelli con il rinominarli. Infatti, mentre nel primo caso viene solo modificato l'ordine dei livelli, nel secondo caso verrebbero modificati anche tutti gli effettivi valori degli elementi. In genere è preferibile quindi ridefinire il fattore specificando l'argomento `levels`. +È importante non confondere l'ordinare i livelli con il rinominarli. Infatti, mentre nel primo caso viene solo modificato l'ordine dei livelli, nel secondo caso verrebbero modificati anche tutti gli effettivi valori degli elementi. In genere è preferibile quindi ridefinire il fattore specificando l'argomento `levels`. Vediamo un esempio dove raccogliamo i dati riguardanti i dosaggi di un farmaco: @@ -194,7 +194,7 @@ dosage <- factor(rep(c("medium", "low", "high"), times = 2)) dosage ``` -Non avendo specificato l'attributo `levels` i livelli siano stati definiti automaticamente in ordine alfabetico. Osserviamo cosa succede se per erroe rinominiamo i livelli invece di riordinarli correttamente. +Non avendo specificato l'attributo `levels` i livelli siano stati definiti automaticamente in ordine alfabetico. Osserviamo cosa succede se per errore rinominiamo i livelli invece di riordinarli correttamente. ```{r, echo = TRUE} # Creo una copia @@ -205,9 +205,9 @@ levels(dosage_wrong) <- c("low", "medium", "high") dosage_wrong ``` -Nota come questo sia un grave errore poichè rinominado i livelli abbiamo modificato anche gli effettivi valori degli elementi. Adesso i valori sono tutti diversi e insensati. +Nota come questo sia un grave errore poiché rinominando i livelli abbiamo modificato anche gli effettivi valori degli elementi. Adesso i valori sono tutti diversi e insensati. -Per riordinare corretamente i livelli riutilizziamo la funzione `factor()` specificando i livelli nell'ordine desiderato. +Per riordinare correttamente i livelli riutilizziamo la funzione `factor()` specificando i livelli nell'ordine desiderato. ```{r, echo = TRUE} dosage <- factor(dosage, levels = c("low", "medium", "high")) dosage @@ -271,11 +271,11 @@ levels(my_factor) <- c(levels(my_factor), "nuovolivello") levels(my_factor)[4] <- "nuovolivello" -# il fattore my_factor ha 3 livelli e quindi alla quarta posizione (vuota) aggiungo il nuov livello +# il fattore my_factor ha 3 livelli e quindi alla quarta posizione (vuota) aggiungo il nuovo livello ``` -E' possibile inoltre combinare due fattori in modo da ottenerne uno unico unendo quindi i livelli e i rispettivi valori numerici. Semplicemente usando il comando `c(fac1, fac2)`: +È possibile inoltre combinare due fattori in modo da ottenerne uno unico unendo quindi i livelli e i rispettivi valori numerici. Semplicemente usando il comando `c(fac1, fac2)`: ```{r} fac1 <- factor(rep(c("a", "b", "c"), each = 5)) @@ -283,11 +283,11 @@ fac2 <- factor(rep(c("d"), each = 5)) c(fac1, fac2) ``` - + -### Fattori Ordinali +### Fattori ordinali -Vediamo infine un esempio di variabile categoriale ordinale. Riprendendo l'esempio precedente rigurdo i dosaggio del farmaco, è chiaro che esiste una relazionee ordinale tra i veri livelli della variabile. Per creare una variabile ordinale possiamo specificare l'argomento `ordered = TRUE`: +Vediamo infine un esempio di variabile categoriale ordinale. Riprendendo l'esempio precedente riguardo i dosaggio del farmaco, è chiaro che esiste una relazione ordinale tra i veri livelli della variabile. Per creare una variabile ordinale possiamo specificare l'argomento `ordered = TRUE`: ```{r, echo = TRUE} dosage_ord <- factor(dosage, levels = c("low", "medium", "high"), ordered = TRUE) @@ -304,10 +304,10 @@ class(dosage) class(dosage_ord) ``` -:::{.tip title="Codifica Tipologia Variabli" data-latex="[Codifica Tipologia Variabli]"} -In R è importante codificare correttamente le differenii varibili specificando la loro tipologia. Distinnguendo appropriatamente le variabili categoriali (nominali e ordinali) rispetto alle varibili numeriche e alle semplici variabili di caratteri abbiamo numerosi vantaggi. In R, infatti, molti pacchetti e funzioni adottano particolari accorgimenti a seconda della tipologia di variabile fornendoci output e risultati coerenti alla natura della variabile. +:::{.tip title="Codifica tipologia variabili" data-latex="[Codifica tipologia variabili]"} +In R è importante codificare correttamente le differenti variabili specificando la loro tipologia. Distinguendo appropriatamente le variabili categoriali (nominali e ordinali) rispetto alle variabili numeriche e alle semplici variabili di caratteri abbiamo numerosi vantaggi. In R, infatti, molti pacchetti e funzioni adottano particolari accorgimenti a seconda della tipologia di variabile fornendoci output e risultati coerenti alla natura della variabile. -Nota ad esempio comee l'output della funzione `summary()` cambi a seconda della tipologia di varibile. +Nota ad esempio come l'output della funzione `summary()` cambi a seconda della tipologia di variabile. ```{r, echo = TRUE} # Variabile numerica summary(1:15) @@ -337,14 +337,3 @@ factor(c(rep(c("CBT","Psicanalisi"),3),"Controllo","Controllo","CBT")) ```{r} c("Farmaci","Controllo","Farmaci") ``` - - - - - - - - - - - diff --git a/11-matrices.Rmd b/11-matrices.Rmd index 310108b..f408f8e 100644 --- a/11-matrices.Rmd +++ b/11-matrices.Rmd @@ -20,12 +20,12 @@ knitr::include_graphics("images/matrix.png") Due caratteristiche importanti di una matrice sono: - la **dimensione** - il numero di **righe** e di **colonne** da cui è formata la matrice -- la **tipologia** - la tipologia di dati che sono contenuti nella matrice. Infatti, in modo analogo a quanto visto con i vettori, una matrice deve esssere formata da **elementi tutti dello stesso tipo**. Pertanto esistono diverse tipologie di matrici a seconda del tipo di dati da cui è formata, in particolare abbiamo matrici numeriche, di valori logici e di caratteri (vedi Capitolo \@ref(matrix-types)). +- la **tipologia** - la tipologia di dati che sono contenuti nella matrice. Infatti, in modo analogo a quanto visto con i vettori, una matrice deve essere formata da **elementi tutti dello stesso tipo**. Pertanto esistono diverse tipologie di matrici a seconda del tipo di dati da cui è formata, in particolare abbiamo matrici numeriche, di valori logici e di caratteri (vedi Capitolo \@ref(matrix-types)). -E' fondamentale inoltre sottolineare come ogni **elemento** di una matrice sia caratterizzato da: +È fondamentale inoltre sottolineare come ogni **elemento** di una matrice sia caratterizzato da: - un **valore** - ovvero il valore dell'elemento che può essere di qualsiasi tipo ad esempio un numero o una serie di caratteri. -- un **indice di posizione** - ovvero una **coppia di valori (*i*, *j*)** interi positivi che indicando rispettivamente **l'indice di riga** e **l'indice di colonna** e che permettono di identificare univocamente l'elemento all'interno della matrice. +- un **indice di posizione** - ovvero una **coppia di valori (*i*, *j*)** interi positivi che indicando rispettivamente **l'indice di riga** e **l'indice di colonna** e che permettono di identificare univocamente l'elemento all'interno della matrice. Ad esempio, data una matrice $X$ di dimensione $3\times4$ (i.e., 3 righe e 4 colonne) così definita: $$ @@ -38,7 +38,7 @@ $$ $$ abbiamo che $x_{2, 3} = 9$ mentre $x_{3, 2} = 1$. Questo ci serve solo per ribadire il corretto uso degli indici, dove per un generico elemento $x_{i, j}$, il valore *i* è l'indice di riga mentre il valore *j* è l'indice di colonna. **Prima si indicano le righe poi le colonne**. -Vediamo ora come creare delle matrici in R e come compiere le comuni operazini di selezione. Successivamente vedremo diverse manipolazioni e operazioni con le matrici. Infine estenderemo brevemente il concetto di matrici a dimensioni maggiori di due atttraverso l'uso degli **array**. +Vediamo ora come creare delle matrici in R e come compiere le comuni operazioni di selezione. Successivamente vedremo diverse manipolazioni e operazioni con le matrici. Infine estenderemo brevemente il concetto di matrici a dimensioni maggiori di due attraverso l'uso degli **array**. ## Creazione @@ -48,8 +48,8 @@ Il comando usato per creare una matrice in R è `matrix()` e contiene diversi ar nome_matrice <- matrix(data, nrow = , ncol = , byrow = FALSE) ``` -* `data` - un **vettore di valori** utilizzati per popolare la matrice -* `nrow` e `ncol` - sono rispettivamente il numero di righe e il numero di colonne della matrice +* `data` - un **vettore di valori** utilizzati per popolare la matrice +* `nrow` e `ncol` - sono rispettivamente il numero di righe e il numero di colonne della matrice * `byrow` - indica se la matrice deve essere popolata per riga oppure per colonna. Il valore di default è `FALSE` quindi i valori della matrice vengono aggiunti colonna dopo colonna. Indicare `TRUE` per aggiungere gli elementi riga dopo riga Creiamo come esempio una matrice di 3 righe e 4 colonne con i valori che vanno da 1 a 12. @@ -63,7 +63,7 @@ mat_bycol <- matrix(my_values, nrow = 3, ncol = 4) mat_bycol ``` -La funzione `matrix()` ha di default l'argomento `byrow = FALSE`, quindi di base R popola le matrici colonna dopo colonna. Per popolare le matrici riga dopo riga invece, è necessario richiederlo esplicitamente specificando `byrow = TRUE`. +La funzione `matrix()` ha di default l'argomento `byrow = FALSE`, quindi di base R popola le matrici colonna dopo colonna. Per popolare le matrici riga dopo riga invece, è necessario richiederlo esplicitamente specificando `byrow = TRUE`. ```{r, echo = T} # Matrice popolata per righe @@ -71,34 +71,34 @@ mat_byrow <- matrix(my_values, nrow = 3, ncol = 4, byrow = TRUE) mat_byrow ``` -E' importante notare come mentre sia possibile specificare qualsiasi combinazione di righe e colonne, il numero di valori forniti per popolare la matrice deve essere compatibile con la dimensione della matrice. In altre parole, **non posso fornire più o meno dati di quelli che la matrice può contenere**. +È importante notare come mentre sia possibile specificare qualsiasi combinazione di righe e colonne, il numero di valori forniti per popolare la matrice deve essere compatibile con la dimensione della matrice. In altre parole, **non posso fornire più o meno dati di quelli che la matrice può contenere**. -Pertanto, la launghezza del vettore passato all'argomento `data` deve essere compatibile con gli argomenti `nrow` e `ncol`. E' possibile tuttavia, fornire un unico valore se si desidera ottenre una matrice in cui tutti i valori siano identici. Creiamo ad esempio una matrice vuota con soli valori `NA` con 3 righe e 3 colonne. +Pertanto, la lunghezza del vettore passato all'argomento `data` deve essere compatibile con gli argomenti `nrow` e `ncol`. È possibile tuttavia, fornire un unico valore se si desidera ottenere una matrice in cui tutti i valori siano identici. Creiamo ad esempio una matrice vuota con soli valori `NA` con 3 righe e 3 colonne. ```{r, echo = TRUE} mat_NA <- matrix(NA, nrow = 3, ncol = 3) mat_NA ``` -:::{.tip title="Ciclare Valori" data-latex="[Ciclare Valori]"} +:::{.tip title="Ciclare valori" data-latex="[Ciclare valori]"} In realtà è possibile fornire più o meno dati di quelli che la matrice può contenere. Nel caso vengano forniti più valori, R semplicemente utilizza i primi valori disponibili ignorando quelli successivi. ```{r, echo = TRUE} matrix(1:20, nrow = 2, ncol = 2) ``` -Nel caso vengano forniti meno valori, invece, R riutilizza gli stessi valori nello stesso ordinere per completare la matrice avvertendoci del problema. +Nel caso vengano forniti meno valori, invece, R riutilizza gli stessi valori nello stesso ordinare per completare la matrice avvertendoci del problema. ```{r, echo = TRUE} matrix(1:4, nrow = 3, ncol = 4) ``` -Tuttavia, è meglio evitare questa pratica di *ciclare* i valori poichè i risultati potrebbero essere poco chiari ed è facile commettere errori. +Tuttavia, è meglio evitare questa pratica di *ciclare* i valori poiché i risultati potrebbero essere poco chiari ed è facile commettere errori. ::: -### Tipologie di Matrici {#matrix-types} +### Tipologie di matrici {#matrix-types} Abbiamo viso che, in modo analogo ai vettori, anche per le matrici è necessario che tutti i dati siano della stessa tipologia. Avremo pertanto matrici che includono solo valori `character`, `double`, `integer` oppure `logical` e le operazioni che si potranno eseguire (uso di operatori matematiche o operatori logici-relazionali) dipenderanno dalla tipologia di dati. Tuttavia, a differenza dei vettori, la tipologia di oggetto rimarrà sempre `matrix` indipendentemente dai dati contenuti. Le matrici sono sempre matrici, è la tipologia di dati che varia. #### Character {-} -E' possibile definire una matrice di soli caratteri, tuttavia sono usate raramente visto che chiaramente tutte le operazioni matematiche non sono possibili. +È possibile definire una matrice di soli caratteri, tuttavia sono usate raramente visto che chiaramente tutte le operazioni matematiche non sono possibili. ```{r, echo = TRUE} mat_char <- matrix(letters[1:12], nrow = 3, ncol = 4, byrow = TRUE) mat_char @@ -117,7 +117,7 @@ LETTERS[6:10] #### Numeric {-} -Le matrici di valori numerici, sia `double` che `integer`, sono senza dubbio le più comuni ed utilizzate. Vengono spesso sfruttate per eseguire calcoli algebrici computazionalemnte molto efficienti. +Le matrici di valori numerici, sia `double` che `integer`, sono senza dubbio le più comuni ed utilizzate. Vengono spesso sfruttate per eseguire calcoli algebrici computazionalmente molto efficienti. ```{r, echo = TRUE} # doubles mat_num <- matrix(5, nrow = 3, ncol = 4) @@ -141,7 +141,7 @@ class(mat_logic) typeof(mat_logic) ``` -Ricordiamo che è comunque possibile eseguire operazioni matematiche con i valori logici poichè verranno automaticamente rasformatti nei rispettivi valori numerici 1 e 0. +Ricordiamo che è comunque possibile eseguire operazioni matematiche con i valori logici poiché verranno automaticamente trasformati nei rispettivi valori numerici 1 e 0. ### Esercizi {-} @@ -152,21 +152,21 @@ $$ \begin{matrix} 2 & 34 & 12 & 7\\ 46 & 93 & 27 & 99\\ -23 & 38 & 7 & 04 +23 & 38 & 7 & 04 \end{matrix} $$ 2. Crea la matrice `B` contenente tutti i primi 12 numeri dispari disposti su 4 righe e 3 colonne. 3. Crea la matrice `C` contenente i primi 12 multipli di 9 disposti su 3 righe e 4 colonne. -4. Crea la matrice `D` formata da 3 colonne in cui le lettere `"A"`,`"B"` e `"C"` vengano ripetute 4 volte ciascuna rispettivamente nella prima, seconda e terza colonna. -5. Crea la matrice `E` formata da 3 righe in cui le lettere `"A"`,`"B"` e `"C"` vengano ripetute 4 volte ciascuna rispettivamente nella prima, seconda e terza riga. +4. Crea la matrice `D` formata da 3 colonne in cui le lettere `"A"`,`"B"` e `"C"` vengano ripetute 4 volte ciascuna rispettivamente nella prima, seconda e terza colonna. +5. Crea la matrice `E` formata da 3 righe in cui le lettere `"A"`,`"B"` e `"C"` vengano ripetute 4 volte ciascuna rispettivamente nella prima, seconda e terza riga. -## Selezione Elementi {#sel-matrix} +## Selezione elementi {#sel-matrix} L'aspetto sicuramente più importante (e divertente) riguardo le matrici è accedere ai vari elementi. Ricordiamo che una matrice non è altro che una griglia di righe e colonne dove vengono disposti i vari valori. Indipendentemente da cosa la matrice contenga, è possibile utilizzare gli indici di riga e di colonna per identificare univocamente un dato elemento nella matrice. Pertanto ad ogni elemento è associata una coppia di valori (*i*, *j*) dove *i* è l'indice di riga e *j* è l'indice di colonna. -Per visualizzare questo concetto, riportiamo nel seguente esempio gli indici per ogni elemnto di una matrice $3\times4$: +Per visualizzare questo concetto, riportiamo nel seguente esempio gli indici per ogni elemento di una matrice $3\times4$: ```{r} mat <- matrix(NA, 3, 4) @@ -180,7 +180,7 @@ for(i in 1:nrow(mat)){ mat ``` -In R è possibile selezionare un elemento di una matrice utilizzando il suo indice di riga e di colonna. In modo analogo ai vettori è necessario quindi indicare all'inerno delle **parentesi quadre** `[]` poste dopo il nome del vettore, **l'indice di riga** e **l'indice di colonna** **separati da virgola**. +In R è possibile selezionare un elemento di una matrice utilizzando il suo indice di riga e di colonna. In modo analogo ai vettori è necessario quindi indicare all'interno delle **parentesi quadre** `[]` poste dopo il nome del vettore, **l'indice di riga** e **l'indice di colonna** **separati da virgola**. ```{r, echo = TRUE, eval = FALSE} nome_matrice[, ] @@ -208,14 +208,14 @@ my_matrix[20,30] Oltre alla selezione di un singolo elemento è possibile eseguire altri tipi di selezione: -#### Selezionare Riga o Colonna {-} +#### Selezionare riga o colonna {-} -E' possibile selezionare **tutti** gli elementi di una riga o di una colonna utilizzando la seguente sintassi: +È possibile selezionare **tutti** gli elementi di una riga o di una colonna utilizzando la seguente sintassi: ```{r, echo = TRUE, eval = FALSE} -# Selzione intera riga +# Selezione intera riga nome_matrice[, ] -# Selzione intera colonna +# Selezione intera colonna nome_matrice[ , ] ``` Nota come sia comunque necessario l'utilizzo della **virgola** lasciando vuoto il posto prima o dopo la virgola per indicare ad R di selezionare rispettivamente tutte le righe o tutte le colonne. @@ -223,10 +223,10 @@ Nota come sia comunque necessario l'utilizzo della **virgola** lasciando vuoto i # Selezioniamo la 2 riga e tutte le colonne my_matrix[2, ] -# Selezioniamo tutte le righe e la 3 colonna +# Selezioniamo tutte le righe e la 3 colonna my_matrix[ ,3] ``` -Qualora fosse necessario selezionare più righe o più colonne è sufficiente indicare tutti gli indici di interesse. Ricorda che questi devono essere specificati in un unico vettore. All'interno delle parentesi quadre, R si aspetta una sola virgola che separa gli indici di riga da quelli di colonna. E' quindi necessario combinare gli indici che vogliamo selezionare in un unico vettore sia nel caso delle righe che delle colonne. Per selezionare righe o colonne in successione, ad esempio le prime 3 colonne, posso utilizzare la scrittura compatta `1:3` che è equivalente a `c(1,2,3)`. +Qualora fosse necessario selezionare più righe o più colonne è sufficiente indicare tutti gli indici di interesse. Ricorda che questi devono essere specificati in un unico vettore. All'interno delle parentesi quadre, R si aspetta una sola virgola che separa gli indici di riga da quelli di colonna. È quindi necessario combinare gli indici che vogliamo selezionare in un unico vettore sia nel caso delle righe che delle colonne. Per selezionare righe o colonne in successione, ad esempio le prime 3 colonne, posso utilizzare la scrittura compatta `1:3` che è equivalente a `c(1,2,3)`. ```{r, echo = TRUE} # Selezioniamo la 1 e 3 riga @@ -236,7 +236,7 @@ my_matrix[c(1,3), ] my_matrix[ , 2:4] ``` -#### Selezionare Regione Matrice {-} +#### Selezionare regione matrice {-} Combinando indici di righe e di colonne è anche possibile selezionare specifiche regioni di una matrice o selezionare alcuni suoi valori per creare una nuova matrice. @@ -248,15 +248,15 @@ my_matrix[1:2, 3:4] my_matrix[c(1,3), c(2,4)] ``` -:::{.tip title="Selezionare non è Modificare" data-latex="[Selezionare non è Modificare]"} +:::{.tip title="Selezionare non è modificare" data-latex="[Selezionare non è modificare]"} Ricordiamo che, come per i vettori, l'operazione di selezione non modifichi l'oggetto iniziale. Pertanto è necessario salvare il risultato della selezione se si desidera mantenere le modifiche. ::: -:::{.design title="Matrici e Vettori" data-latex="[Matrici e Vettori]"} +:::{.design title="Matrici e vettori" data-latex="[Matrici e vettori]"} I più attenti avranno notato che che i comandi di selezione non restituiscono sempre lo stesso oggetto, a volte otteniamo come risultato un vettore e delle altre una matrice. -E' importante chiarire che una **un vettore non è un matrice** e tanto più vale l'opposto. In R questi sono due tipologie di oggetti diversi e sarà importante tenere a mente questa distinzione. +È importante chiarire che una **un vettore non è un matrice** e tanto più vale l'opposto. In R questi sono due tipologie di oggetti diversi e sarà importante tenere a mente questa distinzione. ```{r, echo=TRUE, eval = FALSE} # Un vettore non è una matrice @@ -284,13 +284,13 @@ is.matrix(my_matrix[, c(1,2)]) # TRUE Questa distinzione influirà sul successivo utilizzo dell'oggetto ottenuto dalla selezione. -#### Vettore Riga e Vettore Colonna {-} +#### Vettore riga e vettore colonna {-} -Una particolare fonte di incomprensioni e successivi errori riguarda proprio l'utilizzo di un vettore ottenuto dalla selezione di una singola riga (o una singola colonna) di una matrice come fosse un *vettore riga* (o un *vettore colonna*). +Una particolare fonte di incomprensioni e successivi errori riguarda proprio l'utilizzo di un vettore ottenuto dalla selezione di una singola riga (o una singola colonna) di una matrice come fosse un *vettore riga* (o un *vettore colonna*). In algebra lineare, i *vettori riga* ed i *vettori colonna* non sono altro che delle matrici rispettivamente di dimensione $1\times n$ e $m \times 1$. La dimensione ($righe \times colonne$) di una matrice, e quindi anche di un vettore, rivestono un ruolo importante nelle operazioni con le matrici ed in particolare nel prodotto matriciale. -In R i vettori hanno una sola dimensione ovvero la *lunghezza* e quindi nel loro utilizzo con operazioni tra matrici vengono convertiti automaticamente in vettori riga o vettori colonna a seconda delle necessità. Tuttavia, questa trasformazione potrebbe non sempre rispettare le attuali intenzioni ed è quindi meglio utlizzare sempre le matrici e non i vettori. +In R i vettori hanno una sola dimensione ovvero la *lunghezza* e quindi nel loro utilizzo con operazioni tra matrici vengono convertiti automaticamente in vettori riga o vettori colonna a seconda delle necessità. Tuttavia, questa trasformazione potrebbe non sempre rispettare le attuali intenzioni ed è quindi meglio utilizzare sempre le matrici e non i vettori. ```{r, echo = TRUE} # Vettore @@ -309,7 +309,7 @@ dim(my_col_vector) my_col_vector ``` -#### Srotolare una Matrice {-} +#### Srotolare una matrice {-} Abbiamo visto che possiamo facilmente popolare una matrice con un vettore. Allo stesso modo possiamo vettorizzare una matrice (in altri termini "srotolare" la matrice) per ritornare al vettore originale. Con il comando `c(matrice)` oppure forzando la tipologia di oggetto a vettore con `vector(matrice)` o `as.vector(matrice)`. @@ -322,27 +322,27 @@ as.vector(my_matrix) ::: -### Utilizzi Avanzati Selezione {#matrix-selection-advanced} +### Utilizzi avanzati selezione {#matrix-selection-advanced} Vediamo ora alcuni utilizzi avanzati della selezione di elementi di una matrice. In particolare impareremo a: -- utilizzare gli operatori relazionali e logici per selezionare gli elementi di una martrice +- utilizzare gli operatori relazionali e logici per selezionare gli elementi di una matrice - modificare l'ordine di righe e colonne - sostituire degli elementi - eliminare delle righe o colonne Nota che queste operazioni siano analoghe a quelle viste per i vettori e quindi seguiranno le stesse regole e principi. -#### Operatori Relazionali e Logici {-} +#### Operatori relazionali e logici {-} -Un'utile funzione è quella di selezionare tra gli elementi di una matrice quelli che rispetano una certa condizione. Possiamo ad esempio valutare *"quali elementi della matrice sono maggiori di x?"*. Per fare questo dobbiamo specificare all'interno delle parentesi quadre la proposizione di interesse utilizzando gli operatori relazionali e logici (vedi Capitolo \@ref(operators-rel-log)). +Un'utile funzione è quella di selezionare tra gli elementi di una matrice quelli che rispettano una certa condizione. Possiamo ad esempio valutare *"quali elementi della matrice sono maggiori di x?"*. Per fare questo dobbiamo specificare all'interno delle parentesi quadre la proposizione di interesse utilizzando gli operatori relazionali e logici (vedi Capitolo \@ref(operators-rel-log)). Quando una matrice è valutata all'interno di una proposizione, R valuta la veridicità di tale proposizione rispetto ad ogni suo elemento. Come risultato otteniamo una matrice di valori logici con le rispettive risposte per ogni elemento (`TRUE` o `FALSE`). ```{r, echo = TRUE} my_matrix <- matrix(1:23, nrow = 3, ncol = 4) my_matrix -# Elemeni maggiori di 4 e minori di 10 +# Elementi maggiori di 4 e minori di 10 test <- my_matrix >= 4 & my_matrix <=10 test ``` @@ -356,7 +356,7 @@ my_matrix[test] Nota come in questo caso non sia necessaria alcuna virgola all'interno delle parentesi quadre e come il risultato ottenuto sia un vettore. -#### Modificare Ordine Righe e Colonne {-} +#### Modificare ordine righe e colonne {-} Gli indici di riga e di colonna possono essere utilizzati per riordinare le righe e le colonne di una matrice a seconda delle necessità. @@ -364,15 +364,15 @@ Gli indici di riga e di colonna possono essere utilizzati per riordinare le righ my_matrix <- matrix(1:6, nrow = 3, ncol = 4) my_matrix -# Altero l'ordinen delle righe +# Altero l'ordine delle righe my_matrix[c(3,2,1), ] -# Altero l'ordine delle colonnne +# Altero l'ordine delle colonne my_matrix[ ,c(1,3,2, 4)] ``` -#### Modificare gli Elementi {-} +#### Modificare gli elementi {-} Un importante utilizzo degli indici riguarda la modifica di un elemento di una matrice. Per sostituire un vecchio valore con un nuovo valore, seleziono il vecchio valore della matrice e utilizzo la funzione `<-` (o `=`) per assegnare il nuovo valore. @@ -385,7 +385,7 @@ my_matrix[2,2] <- 555 my_matrix ``` -E' possibile anche sostituire tutti i valori di un'intera riga o colonnna opportunamente selezionata. In questo caso sarà necessario fornire un corretto numero di nuovi valori da utilizzare. +È possibile anche sostituire tutti i valori di un'intera riga o colonna opportunamente selezionata. In questo caso sarà necessario fornire un corretto numero di nuovi valori da utilizzare. ```{r, echo = TRUE} # Modifico la 2 colonna my_matrix[ ,2] <- c(444, 555, 666) @@ -396,14 +396,14 @@ my_matrix[3, ] <- c(111, 666, 999, 122) my_matrix ``` -Nota come a differenza dei vettori non sia possibile aggiungere una nuova riga o colonna attraverso questa operazione ma sarà necesssario utilizzare una diversa procedura (vedi Capitolo \@ref(matrix-bind)). +Nota come a differenza dei vettori non sia possibile aggiungere una nuova riga o colonna attraverso questa operazione ma sarà necessario utilizzare una diversa procedura (vedi Capitolo \@ref(matrix-bind)). -```{r, echo = TRUE, error = TRUE} +```{r, echo = TRUE, error = TRUE} # Aggiungo una nuova colona [errore selezione indici] my_matrix[, 5] <- c(27, 27, 27) ``` -#### Eliminare Righe o Colonne {-} +#### Eliminare righe o colonne {-} Per **eliminare** delle righe (o delle colonne) da una matrice, è necessario indicare all'interno delle parentesi quadre gli indici di riga (o di colonna) che si intende eliminare, preceduti dall'operatore `-` (*meno*). Nel caso di più righe (o colone) è possibile indicare il meno solo prima del comando `c()` analogamente con quanto fatto con i vettori. @@ -413,7 +413,7 @@ my_matrix <- matrix(1:12, nrow = 3, ncol = 4) # Elimino la 2° riga my_matrix[-2, ] -# Elimino la 2° riga e la 2° e 3° colonna +# Elimino la 2° riga e la 2° e 3° colonna my_matrix[-2, -c(2,3)] ``` @@ -424,14 +424,14 @@ Nota come l'operazione di eliminazione sia comunque un'operazione di selezione. Utilizzando le matrici create nei precedenti esercizi esegui le seguenti consegne ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-09-matrices.R)): -1. Utilizzando gli indici di riga e di colonna selziona il numero 27 della matrice `A` -2. Selziona gli elementi compresi tra la seconda e quarta riga, seconda e terza colonna della matrice `B` +1. Utilizzando gli indici di riga e di colonna seleziona il numero 27 della matrice `A` +2. Seleziona gli elementi compresi tra la seconda e quarta riga, seconda e terza colonna della matrice `B` 3. Seleziona solo gli elementi pari della matrice `A` (Nota: utilizza l'operazione resto `%%`) 4. Elimina dalla matrice `C` la terza riga e la terza colonna 5. Seleziona tutti gli elementi della seconda e terza riga della matrice `B` -6. Seleziona tutti gli elementi diversi da “B” appartenenti alla matrice `D` +6. Seleziona tutti gli elementi diversi da “B” appartenenti alla matrice `D` -## Funzioni ed Operazioni +## Funzioni e operazioni Vediamo ora alcune funzioni frequentemente usate e le comuni operazioni eseguite con le matrici (vedi Tabella \@ref(tab:table-matrix-operators)). @@ -484,7 +484,7 @@ kableExtra::kable(matrix_operators, col.names = c("Funzione", "Descrizione"), Descriviamo ora nel dettaglio alcuni particolari utilizzi. -### Attributi di una Matrice {#mat-prop} +### Attributi di una matrice {#mat-prop} Abbiamo visto nel Capitolo \@ref(attributes) che gli oggetti in R possiedono quelli che sono definiti *attributi* ovvero delle utili informazioni riguardanti l'oggetto stesso, una sorta di *metadata*. Vediamo ora alcuni attributi particolarmente rilevanti nel caso delle matrici ovvero la dimensione (`dim`) e i nomi delle righe e colonne (`names`). @@ -508,7 +508,7 @@ In alternativa per conoscere le dimensioni di una matrice è possibile utilizzar dim(my_matrix) ``` -#### Nomi Righe e Colonne {-} +#### Nomi righe e colonne {-} Come avrete notato, di base le dimensioni di una matrice (ovvero le righe e le colonne) vengono identificate attraverso i loro indici numerici. In R tuttavia, è anche possibile assegnare dei nomi alle righe e alle colonne di una matrice. @@ -524,10 +524,10 @@ rownames(mat) colnames(mat) ``` -Non essendo impostati, ottieniamo inizialmente come output il valore `NULL`. Per impostare i nomi di righe e/o colonne, sarà quindi necessario assegnare a `rownames(nome_matrice)` e `colnames(nome_matrice)` un vettore di caratteri della stessa lunghezza della dimensione che stiamo rinominando. Se impostiamo un unico carattere, tutte le righe/colonne avranno lo stesso valore. Questo ci fa capire che, se vogliamo impostare dei nomi, R richiede che questo venga fatto per tutte le righe/colonne. +Non essendo impostati, otteniamo inizialmente come output il valore `NULL`. Per impostare i nomi di righe e/o colonne, sarà quindi necessario assegnare a `rownames(nome_matrice)` e `colnames(nome_matrice)` un vettore di caratteri della stessa lunghezza della dimensione che stiamo rinominando. Se impostiamo un unico carattere, tutte le righe/colonne avranno lo stesso valore. Questo ci fa capire che, se vogliamo impostare dei nomi, R richiede che questo venga fatto per tutte le righe/colonne. ```{r, echo=TRUE} -# Assegnamo i nomi alle righe +# Assegniamo i nomi alle righe rownames(my_matrix) <- LETTERS[1:3] my_matrix @@ -536,13 +536,13 @@ colnames(my_matrix) <- LETTERS[4:7] my_matrix ``` -In alternativa posso utilizzare il `dimnames()` per accedere contemporaneamente sia ai nomi di riga che a quelli di colonna. Come output ottengo una lista (vedi Capitolo \@ref(list)) dove vengono prima indicati i nomi di riga e poi quelli di colonna +In alternativa posso utilizzare il `dimnames()` per accedere contemporaneamente sia ai nomi di riga che a quelli di colonna. Come output ottengo una lista (vedi Capitolo \@ref(list)) dove vengono prima indicati i nomi di riga e poi quelli di colonna ```{r, echo = TRUE} dimnames(my_matrix) ``` -:::{.design title="Selezione per Nomi" data-latex="[Selezione per Nomi]"} +:::{.design title="Selezione per nomi" data-latex="[Selezione per nomi]"} Quando nel Capitolo \@ref(sel-matrix) abbiamo visto i diversi modi di selezionare gli elementi di una matrice, abbiamo sempre usato gli indici numerici di riga e di colonna. Tuttavia, quando i nomi delle delle dimensioni sono disponibili, è possibile indicizzare una matrice in base ai nomi delle righe e/o colone. Possiamo quindi selezionare la prima colonna sia con il suo indice numerico `nome_matrice[ , 1]` ma anche con il nome assegnato `nome_matrice[ ,"nome_colonna"]`. Queste sono operazioni poco utili con le matrici ma che saranno fondamentali nel caso dei **dataframe** (vedi Capitolo \@ref(dataframe)). @@ -556,15 +556,15 @@ my_matrix[c("A", "C"), ] ``` ::: -### Unire Matrici {#matrix-bind} +### Unire matrici {#matrix-bind} -Abbiamo visto nel Capitolo \@ref(vector-functions) come si possono unire diversi vettori tramite la funnzione `c()`. Anche per le matrici è possibile combinare matrici diverse, rispettando però alcune regole: +Abbiamo visto nel Capitolo \@ref(vector-functions) come si possono unire diversi vettori tramite la funzione `c()`. Anche per le matrici è possibile combinare matrici diverse, rispettando però alcune regole: -* `rbind()` - Posso unire matrici **per riga** ovvero aggiungo una o più righe ad una matrice, in questo caso le matrici devono avere lo stesso numero di colonne +* `rbind()` - Posso unire matrici **per riga** ovvero aggiungo una o più righe ad una matrice, in questo caso le matrici devono avere lo stesso numero di colonne * `cbind()` - Posso unire matrici **per colonna** ovvero aggiungo una o più colonne ad una matrice, in questo caso le matrici devono avere lo stesso numero di righe * Le matrici che unisco devono essere della **stessa tipologia** (numeri o caratteri) -Quindi, data una matrice `my_matrix` di dimensione $m \times n$ se volgiamo aggiungere le righe di una seconda matrice `row_matrix` possiamo utlizzare il comando `rbind(my_matrix, row_matrix)` a patto che abbiano lo stesso numero di colonnne ($n$). Se vogliamo invece aggiungere le colonne di una nuova matrice `col_matrix` possiamo utlizzare il comando `cbind(my_matrix, col_matrix)` a patto che abbiano lo stesso numero di righe ($m$). E' utile pensare all'unione come ad un collage tra matrici. In Figura\@ref(fig:mat-comb) è presente uno schema utile per capire visivamente questo concetto, dove le matrici colorate in verde possono essere correttamente unite mentre le matrici in rosso non presentano la corretta dimensionalità. +Quindi, data una matrice `my_matrix` di dimensione $m \times n$ se volgiamo aggiungere le righe di una seconda matrice `row_matrix` possiamo utilizzare il comando `rbind(my_matrix, row_matrix)` a patto che abbiano lo stesso numero di colonne ($n$). Se vogliamo invece aggiungere le colonne di una nuova matrice `col_matrix` possiamo utilizzare il comando `cbind(my_matrix, col_matrix)` a patto che abbiano lo stesso numero di righe ($m$). È utile pensare all'unione come ad un collage tra matrici. In Figura\@ref(fig:mat-comb) è presente uno schema utile per capire visivamente questo concetto, dove le matrici colorate in verde possono essere correttamente unite mentre le matrici in rosso non presentano la corretta dimensionalità. ```{r mat-comb, fig.cap="Schema per la combinazione di matrici", out.width="50%"} knitr::include_graphics("images/matrix_comb.png") @@ -595,7 +595,7 @@ cbind(my_matrix, col_matrix) Un ultimo aspetto utile è l'estensione dei comandi `cbind()` ed `rbind()`. Fino ad ora li abbiamo utilizzati con due soli elementi: matrice di partenza e matrice da aggiungere. Tuttavia, è possibile indicare più matrici che si vogliono unire, separandole con una virgola. Se vogliamo combinare $n$ matrici possiamo usare il comando `cbind(mat1, mat2, mat3, ...)` o `rbind(mat1, mat2, mat3, ...)`. In questo caso il risultato finale sarà l'unione delle matrici nell'ordine utilizzato nel definire gli argomenti quindi prima la `mat1`, poi la `mat2` e così via. -:::{.warning title='"Matrices Must Match"' data-latex='["Matrices Must Match"]'} +:::{.warning title='Matrices Must Match' data-latex='[Matrices Must Match]'} Abbiamo visto che possiamo unire matrici per riga/colonna solo se il numero di colonne/righe delle due matrici sono equivalenti. Otteniamo un errore, invece, quando cerchiamo di combinare matrici di dimensioni diverse *"number of columns/rows of matrices must match "*. ```{r, echo = TRUE, error = TRUE} @@ -607,13 +607,13 @@ rbind(my_matrix, wrong_matrix) ``` ::: -### Operatori Matematici +### Operatori matematici -Gli operatori matematici (e.g., `+`, `-`, `*`, `/`, etc.) svolgono le operazioni tra una matrice ed un singolo valore, tra una matrice ed un vettore oppure tra due matrici. +Gli operatori matematici (ad es. `+`, `-`, `*`, `/`, etc.) svolgono le operazioni tra una matrice ed un singolo valore, tra una matrice ed un vettore oppure tra due matrici. -#### Operazione tra Matrice e Valore Singolo {-} +#### Operazione tra matrice e valore singolo {-} -Nel caso di un singolo valore, la stessa operazione viene semplicemente eseguita su tutti gli elementi della matrice. Possiamo ad esempio aggiungere a tutti gli elementi di una matrice il volore 100. +Nel caso di un singolo valore, la stessa operazione viene semplicemente eseguita su tutti gli elementi della matrice. Possiamo ad esempio aggiungere a tutti gli elementi di una matrice il valore 100. ```{r, echo = TRUE} my_matrix <- matrix(1:12, nrow = 3, ncol = 4) @@ -623,18 +623,18 @@ my_matrix my_matrix + 100 ``` -#### Operazione tra Matrice e Vettore {-} +#### Operazione tra matrice e vettore {-} -Nel caso di un vettore, l'operazione viene eseguita **elemento per elemento** ciclando i valori del vettore qualora la sua lunghezza non sia suficiente. Possiamo ad esempio aggiungere a tutti gli elementi di una matrice il vettore di valori `c(100, 200, 300, 400)`. +Nel caso di un vettore, l'operazione viene eseguita **elemento per elemento** ciclando i valori del vettore qualora la sua lunghezza non sia sufficiente. Possiamo ad esempio aggiungere a tutti gli elementi di una matrice il vettore di valori `c(100, 200, 300, 400)`. ```{r, echo = TRUE} # Aggiungo un vettore di valori my_matrix + c(100, 200, 300, 400) ``` -Com'è facilmente intuibile, questa operazione è poco connsigliata poichè è facile causa di errori ed incomprensioni. +Com'è facilmente intuibile, questa operazione è poco consigliata poiché è facile causa di errori ed incomprensioni. -#### Operazione tra Matrici {-} +#### Operazione tra matrici {-} Nel caso di operazioni tra matrici, l'operazione viene eseguita **elemento per elemento** ed è quindi importante che le matrici abbiano la **stessa dimensione**. Possiamo ad esempio aggiungere a tutti gli elementi di una matrice nelle cui righe abbiamo i valori 100, 200, 300 e 400. @@ -647,14 +647,14 @@ my_matrix + sum_matrix ``` :::{.tip title="Matrix Multiplication" data-latex="[Matrix Multiplication]"} -Nota come in R l'operatore `*` indichi il semmplice prodotto elemento per elemento mentre per ottenere il prodotto matriciale è necessario utilizzare l'operatore `%*%`. +Nota come in R l'operatore `*` indichi il semplice prodotto elemento per elemento mentre per ottenere il prodotto matriciale è necessario utilizzare l'operatore `%*%`. Il prodotto matriciale segue delle specifiche regole e specifiche proprietà. In particolare, il numero di colonne della prima matrice deve essere uguale al numero di righe della seconda matrice. Per un approfondimento vedi . ```{r} ``` -#### Algebra Lineare {-} +#### Algebra lineare {-} Anche altri aspetti che riguardano le operazioni con le matrici non vengono qui discusse ma si rimanda il lettore interessato alle seguenti pagine: @@ -698,11 +698,11 @@ diag(4) ### Esercizi {-} -Utilizzando le matrici create nei precedenti esercizi, esegui le seguentti consegne ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-09-matrices.R)): +Utilizzando le matrici create nei precedenti esercizi, esegui le seguenti consegne ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-09-matrices.R)): 1. Crea la matrice `G` unendo alla matrice `A` le prime due colonne della matrice `C` 2. Crea la matrice `H` unendo alla matrice `C` le prime due righe della matrice trasposta di `B` -3. Ridefinisci la matrice `A` eliminando la seconda colonna. Ridefinisci la matrice `B` eliminando la prima riga. Verifica che le matrici così ottenute abbiano la stessa dimensione. +3. Ridefinisci la matrice `A` eliminando la seconda colonna. Ridefinisci la matrice `B` eliminando la prima riga. Verifica che le matrici così ottenute abbiano la stessa dimensione. 4. Commenta i differenti risultati che otteniamo nelle operazioni `A*B`, `B*A`, `A%*%B` e `B%*%A`. 5. Assegna i seguenti nomi alle colonne e alle righe della matrice `C`: `"col_1", "col_2", "col_3", "col_4", "row_1", "row_2", "row_3"`. @@ -722,13 +722,13 @@ my_cube <- array(1:27, dim = c(3,3,3)) my_cube ``` -Tutte le principali funzioni ed operazioni di selezione che abbiamo visto per le matrici ed i vettori posono essere eseguite in modo analogo anche con gli array. Il funzinonamento generale della selezione di elementi tramite parentesi quadre risulterà ora certamente pù chiaro. Per ogni dimensione vengono indicarti gli indici di posizioni desiderati. L'ordine all'interno delle parentesi quadre determina la specifica deimensione a cui ci si riferisce e le virgole sono utilizzate per separare gli indici delle diverse dimensioni. +Tutte le principali funzioni e operazioni di selezione che abbiamo visto per le matrici ed i vettori possono essere eseguite in modo analogo anche con gli array. Il funzionamento generale della selezione di elementi tramite parentesi quadre risulterà ora certamente pù chiaro. Per ogni dimensione vengono indicarti gli indici di posizioni desiderati. L'ordine all'interno delle parentesi quadre determina la specifica dimensione a cui ci si riferisce e le virgole sono utilizzate per separare gli indici delle diverse dimensioni. ```{r, echo = TRUE, eval = FALSE} my_hypercube[, , , ..., ] ``` -Vediamo ora alcuni semplici eempi di selezione. +Vediamo ora alcuni semplici esempi di selezione. ```{r} # Seleziono un singolo elemento @@ -745,8 +745,8 @@ my_cube[ 1:2, 1:2, 1:2] ``` -:::{.tip title="Array Mother of All Matrix" data-latex="[Array Mother of All Matrix]"} -E' facilmente intuibile come le matrici non siano altro che un caso speciale di array con 2 dimensioni. Infatti i più attenti avranno notato che il valore `"array"` compariva insieme a `"matrix"` nel valutare la tipologia di oggetto. +:::{.tip title="Array Mother of All Matrices" data-latex="[Array Mother of All Matrices]"} +È facilmente intuibile come le matrici non siano altro che un caso speciale di array con 2 dimensioni. Infatti i più attenti avranno notato che il valore `"array"` compariva insieme a `"matrix"` nel valutare la tipologia di oggetto. ```{r, echo = TRUE} my_matrix <- matrix(1:12, nrow = 2, ncol = 2) @@ -755,7 +755,7 @@ class(my_matrix) ``` Tuttavia nota come un semplice vettore non sia un array. Ricordiamo infatti che un vettore non possiede una dimensione (`dim`) ma semplicemente una lunghezza (`length`). -```{r, echo = TRUE} +```{r, echo = TRUE} my_vector <- 1:12 is.array(my_vector) dim(my_vector) diff --git a/12-dataframe.Rmd b/12-dataframe.Rmd index e1da70e..7f48b85 100644 --- a/12-dataframe.Rmd +++ b/12-dataframe.Rmd @@ -11,16 +11,16 @@ knitr::opts_chunk$set( library(kableExtra) ``` -I `dataframe` sono uno degli oggetti più utilizzati in R per rappresentare i propri dati. In modo analogo alle matrici, i `dataframe` sono una struttura **bidimensionale** dove i dati sono disposti secondo righe e colonne. Può essere utile pensare al dataframe esattamente come ad una normale tabella che si può creare in un foglio di calcolo (e.g., Excel) dove possiamo inserire i nostri dati. Dati in questo caso è volutamente generico poichè i dataframe, a differenza delle matrici, possono contenere nello stesso oggetto tipi diversi di dati (e.g., *nomi*, *date* e *numeri*). +I `dataframe` sono uno degli oggetti più utilizzati in R per rappresentare i propri dati. In modo analogo alle matrici, i `dataframe` sono una struttura **bidimensionale** dove i dati sono disposti secondo righe e colonne. Può essere utile pensare al dataframe esattamente come ad una normale tabella che si può creare in un foglio di calcolo (ad es. Excel) dove possiamo inserire i nostri dati. Dati in questo caso è volutamente generico poiché i dataframe, a differenza delle matrici, possono contenere nello stesso oggetto tipi diversi di dati (ad es. *nomi*, *date* e *numeri*). -La struttura di base di un dataframe è quindi la stessa di una matrice ma ci permette di includere diversi tipi di dati nello stesso oggetto come caratteri e valori numerici. Questo ci consente di raccogliere in un unico oggetto tutte le caratteristiche delle unità statistiche (variabili numeriche, categoriali, nominali etc.) che intendiamo successivamente analizzare. Un aspetto cruciale quindi è proprio quello che il dataframe è stato pensato per gestire dati complessi ed eterogenei come quelli che si trovano in un’analisi di dati reale. Se vi capiterà di utilizzare altri linguaggi di programmazione sopratutto mirati all'analisi dati (e.g., Matlab) noterete come vi mancherà un oggetto potente e intuitivo come il dataframe. +La struttura di base di un dataframe è quindi la stessa di una matrice ma ci permette di includere diversi tipi di dati nello stesso oggetto come caratteri e valori numerici. Questo ci consente di raccogliere in un unico oggetto tutte le caratteristiche delle unità statistiche (variabili numeriche, categoriali, nominali etc.) che intendiamo successivamente analizzare. Un aspetto cruciale quindi è proprio quello che il dataframe è stato pensato per gestire dati complessi ed eterogenei come quelli che si trovano in un’analisi di dati reale. Se vi capiterà di utilizzare altri linguaggi di programmazione sopratutto mirati all'analisi dati (ad es. Matlab) noterete come vi mancherà un oggetto potente e intuitivo come il dataframe. -In genere in un dataframe le righe rappresentano le unità statitiche (ad esempio persone o osservazioni) e le colonne rappresentano variabili ovvero delle proprietà misurate su quelle unità statistiche. Esistono tuttavia due formati principali di dataframe a seconda del modo in cui vengono organizzati i dati. Abbiamo i dataframe in forma **wide** (oppure larga) oppure i dataframe in forma **long** (oppure lunga). Valutiamo la differenza tra i due formati ipotizzando dei dati dove per ogni soggetto abbiamo misuriamo l'età, il genere, e la risposta a tre item di un questionario. +In genere in un dataframe le righe rappresentano le unità statistiche (ad esempio persone o osservazioni) e le colonne rappresentano variabili ovvero delle proprietà misurate su quelle unità statistiche. Esistono tuttavia due formati principali di dataframe a seconda del modo in cui vengono organizzati i dati. Abbiamo i dataframe in forma **wide** (oppure larga) oppure i dataframe in forma **long** (oppure lunga). Valutiamo la differenza tra i due formati ipotizzando dei dati dove per ogni soggetto abbiamo misuriamo l'età, il genere, e la risposta a tre item di un questionario. #### Wide Dataframe {-} -Nel formato **wide**, ogni singola riga del dataframe rappresenta un soggetto e ogni sua risposta o variabile misurata sarà riportata in una diversa colonna. In Tabelle \@ref(tab:table-wide-db) vengono presentati i darti dell'esempio in un formato wide. +Nel formato **wide**, ogni singola riga del dataframe rappresenta un soggetto e ogni sua risposta o variabile misurata sarà riportata in una diversa colonna. In Tabelle \@ref(tab:table-wide-db) vengono presentati i darti dell'esempio in un formato wide. ```{r table-wide-db} data_wide<-data.frame( @@ -34,7 +34,7 @@ data_wide<-data.frame( data_wide %>% kable(align = "c", - caption = "Dataframe nel formato wong") %>% + caption = "Dataframe nel formato wide") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F) ``` @@ -42,7 +42,7 @@ Osserviamo come ogni soggetto si identificato da un codice riportato nella varia #### Long Dataframe {-} -Nel formato **long**, ogni singola riga rappresenta una singola osservazione. Quindi i dati di ogni soggetto saranno riportati su più righe e le variabili che non cambiano tra le osservazioni saranno ripetute. In Tabelle \@ref(tab:table-long-db) vengono presentati i darti dell'esempio in un formato lide. +Nel formato **long**, ogni singola riga rappresenta una singola osservazione. Quindi i dati di ogni soggetto saranno riportati su più righe e le variabili che non cambiano tra le osservazioni saranno ripetute. In Tabelle \@ref(tab:table-long-db) vengono presentati i darti dell'esempio in un formato wide. ```{r table-long-db} data_long<-data.frame(Id=rep(c("subj_1","subj_2","subj_3"),each=3), @@ -56,20 +56,20 @@ data_long %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F) ``` -Osserviamo come le risposte di ogni soggetto siano distribuite su più righe. Le caratterische che non variano vengono ripetute ad ogni riga (*Id*, *age* e *gender*) mentre le risposte agli item vengono registrate utilizzando due colonne *item*, ovvero il numero dell'item, e *response* l'effettiva risposta di quel partecipante a quello specifico item. +Osserviamo come le risposte di ogni soggetto siano distribuite su più righe. Le caratteristiche che non variano vengono ripetute ad ogni riga (*Id*, *age* e *gender*) mentre le risposte agli item vengono registrate utilizzando due colonne *item*, ovvero il numero dell'item, e *response* l'effettiva risposta di quel partecipante a quello specifico item. -:::{.tip title="Long o Wide?" data-latex="[Long o Wide?]"} +:::{.tip title="Long o wide?" data-latex="[Long o wide?]"} I dati in forma long e wide hanno delle proprietà diverse sopratutto in riferimento all'utilizzo. La tipologia di dato e il risultato finale è esattamente lo stesso tuttavia alcuni software o alcuni pacchetti di R funzionano solo con dataset organizzati in un certo modo. Non c'è quindi un formato corretto o sbagliato ma dipende dal tipo di analisi e dal software o pacchetto che si utilizza. Alcune operazioni o analisi richiedono il dataset in forma **long** altre in forma **wide**. -Il consiglio però è di abituarsi il più possibile a ragionare in forma **long** perchè la maggior parte dei moderni pacchetti per l'analisi dati e per la creazione di grafici richiedono i dati in questo formato. Ci sono comunque delle funzioni (più avanzate) per passare velocemente da un formato all'altro. +Il consiglio però è di abituarsi il più possibile a ragionare in forma **long** perché la maggior parte dei moderni pacchetti per l'analisi dati e per la creazione di grafici richiedono i dati in questo formato. Ci sono comunque delle funzioni (più avanzate) per passare velocemente da un formato all'altro. ::: Nota come nei precedenti esempi abbiamo utilizzato sia colonne che contengono valori numerici numeri sia colonne con caratteri. Questo non era chiaramente possibile con le matrici. Ricorda tuttavia che, come per le matrici, anche i dataframe richiedono che tutte le colonne (variabili) abbiano lo stesso numero di elementi. -Vedremo ora come creare dei dataframe in R e come compiere le comuni operazini di selezione. Infine descriveremo alcune semplici manipolazioni e operazioni con i dataframe. Come vedremo ci sono molte somiglianze nell'utilizzo dei dataframe e delle matrici. Quando necessario, si farà riferimento al capitolo precedente per far notare aspetti in comune e differenze tra queste due strutture di dati. +Vedremo ora come creare dei dataframe in R e come compiere le comuni operazioni di selezione. Infine descriveremo alcune semplici manipolazioni e operazioni con i dataframe. Come vedremo ci sono molte somiglianze nell'utilizzo dei dataframe e delle matrici. Quando necessario, si farà riferimento al capitolo precedente per far notare aspetti in comune e differenze tra queste due strutture di dati. ## Creazione di un dataframe @@ -82,7 +82,7 @@ nome_df <- data.frame( ...) ``` -La creazione è leggermente diversa rispetto al caso delle matrici. Intuitivamente è facile immaginarla come l'unione di diverse colonne (dove una può contenere dei nomi, un'altra delle date e così via) piuttosto che un insieme di valori inseriti per riga o per colonna come per le matrici. Infatti per creare un `dataframe` è proprio necessario specificare le colonne una alla volta, indicando `nome_colonna = valori` all'interno del comando `data.frame()`. Vediamo un esempio in R, +La creazione è leggermente diversa rispetto al caso delle matrici. Intuitivamente è facile immaginarla come l'unione di diverse colonne (dove una può contenere dei nomi, un'altra delle date e così via) piuttosto che un insieme di valori inseriti per riga o per colonna come per le matrici. Infatti per creare un `dataframe` è proprio necessario specificare le colonne una alla volta, indicando `nome_colonna = valori` all'interno del comando `data.frame()`. Vediamo un esempio in R, ```{r, echo = TRUE} my_data <- data.frame( @@ -99,11 +99,11 @@ my_data In questo caso abbiamo creato un ipotetico dataframe dove in ogni riga abbiamo un soggetto e ogni colonna rappresenta una data caratteristica del soggetto come il genere, l'età e così via. :::{.tip title="ID" data-latex="[ID]"} -E' sempre consigliato definire una colonna (e.g., `Id`) in cui assegnnare un idenificativo univoco ad ogni soggetto. Questo ci permetto di poterlo indentificare senza correre il rischio di compiere errori. Ad esempio l'utlizzo del nome (o anche nome e cognome) potrebbe non essere indicato poichè più persone potrebbero avere lo stesso nome e non saremo quindi in grado di discriminare i due soggetti. +È sempre consigliato definire una colonna (ad es. `Id`) in cui assegnare un identificativo univoco ad ogni soggetto. Questo ci permetto di poterlo identificare senza correre il rischio di compiere errori. Ad esempio l'utilizzo del nome (o anche nome e cognome) potrebbe non essere indicato poiché più persone potrebbero avere lo stesso nome e non saremo quindi in grado di discriminare i due soggetti. ::: :::{.warning title="stringsAsFactors" data-latex="[stringsAsFactors]"} -Una variabile di caratteri all'interno di un DataFrame è considerata di default come una semplice sequenza di caratteri. E' possibile specificare l'argomento `stringsAsFactors = TRUE` per ottenere che tutte le variabili di caratteri siano considerate come delle variabili catgoriali creando automaticamente dei fattori (vedi Capitolo \@ref(factor)). +Una variabile di caratteri all'interno di un DataFrame è considerata di default come una semplice sequenza di caratteri. È possibile specificare l'argomento `stringsAsFactors = TRUE` per ottenere che tutte le variabili di caratteri siano considerate come delle variabili categoriali creando automaticamente dei fattori (vedi Capitolo \@ref(factor)). Nota come il comportamento di default sia differente a seconda della versione di R. Versioni precedenti a R 4.0 avevano infatti come default `stringsAsFactors = TRUE` mentre dalla 4.0 in poi abbiamo `stringsAsFactors = FALSE`. @@ -117,7 +117,7 @@ Esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introductio 1. Crea il dataframe `data_wide` riportato in Tabella \@ref(tab:table-wide-db) 2. Crea il dataframe `data_long` riportato in Tabella \@ref(tab:table-long-db) -## Selezione Elementi {#sel-df} +## Selezione elementi {#sel-df} Per selezionare uno o pù valori da un dataframe è possibile, in modo analogo alle matrici, utilizzare gli indici di riga e di colonna all'interno delle parentesi quadre: @@ -125,7 +125,7 @@ Per selezionare uno o pù valori da un dataframe è possibile, in modo analogo a nome_dataframe[, ] ``` -Ricordiamo che l'ordine `[, ]` è prestabilito e deve essere rispettato affinché la selezione avvenga correttamente. Possiamo quindi eseguire diverse tipologie di selezioni a seconda delle necessità ussanto le stesse procedure viste per le matrici. Ad esempio, riprendeno il dataframe `my_data` creato precedentemente possiamo selezionare: +Ricordiamo che l'ordine `[, ]` è prestabilito e deve essere rispettato affinché la selezione avvenga correttamente. Possiamo quindi eseguire diverse tipologie di selezioni a seconda delle necessità usando le stesse procedure viste per le matrici. Ad esempio, riprendendo il dataframe `my_data` creato precedentemente possiamo selezionare: ```{r} @@ -156,9 +156,9 @@ my_data[c(3,5), c(2,4)] Tuttavia, nell'utilizzo dei dataframe è più comune indicare i nomi delle variabili e le condizioni logico relazionali per selezionare i valori di interesse. -#### Selezione Colonne con Nomi delle Variabili {-} +#### Selezione colonne con nomi delle variabili {-} -Una granade differenza tra le matrici ed i dataframe sta nel poter accedere alle colonne utilizzando l'operatore `$` ed indicando il loro nome attraverso la seguente sintassi: +Una grande differenza tra le matrici ed i dataframe sta nel poter accedere alle colonne utilizzando l'operatore `$` ed indicando il loro nome attraverso la seguente sintassi: ```{r, echo = TRUE, eval = FALSE} nome_dataframe$nome_variabile @@ -174,7 +174,7 @@ my_data$names my_data$faculty ``` -In alternativa è possibile utilizzare la normale procedura di selezione tramite parentesi quadre indicando al cposto degli indici di colonna i nomi delle variabili desiderate. Questo ci permette di selezionare anche più variabili contemporaneamente, ad esempio: +In alternativa è possibile utilizzare la normale procedura di selezione tramite parentesi quadre indicando al posto degli indici di colonna i nomi delle variabili desiderate. Questo ci permette di selezionare anche più variabili contemporaneamente, ad esempio: ```{r, echo = TRUE} # Seleziono solo la variabile "names" @@ -186,11 +186,11 @@ my_data[, c("names", "gender", "faculty")] Nota come i nomi delle variabili debbano essere forniti come delle stringhe. -#### Selezione Righe con Condizioni Logiche {-} +#### Selezione righe con condizioni logiche {-} -Avevamo visto precedentemete nel caso dei vettori e delle matrici come sia possibile costruire delle preposizioni logiche per selezionare solo i valori che rispettino una data condizione. Ora questa funzione si rivela particolarmente utile poichè ci permette di *interrogare* il nostro dataframe in modo semplice ed intuitivo. Utilizzando una condizione logica possiamo, infatti, *filtrare* le oservazioni che soddisfano una data condizione ed ottenere solo le informazioni di interesse. +Avevamo visto precedentemente nel caso dei vettori e delle matrici come sia possibile costruire delle preposizioni logiche per selezionare solo i valori che rispettino una data condizione. Ora questa funzione si rivela particolarmente utile poiché ci permette di *interrogare* il nostro dataframe in modo semplice ed intuitivo. Utilizzando una condizione logica possiamo, infatti, *filtrare* le osservazioni che soddisfano una data condizione ed ottenere solo le informazioni di interesse. -Nella canonica sintassi `[, ]`, gli indici di riga vengono sostituiti con una condizione logica che ci permette di filtrare le righe e al posto degli indici di colonna vengono indicati i nomi delle variabili di interesse. Utilizzeremo quindi la seguente sintassi: +Nella canonica sintassi `[, ]`, gli indici di riga vengono sostituiti con una condizione logica che ci permette di filtrare le righe e al posto degli indici di colonna vengono indicati i nomi delle variabili di interesse. Utilizzeremo quindi la seguente sintassi: ```{r, echo = TRUE, eval = FALSE} nome_dataframe[, ] @@ -205,19 +205,19 @@ my_data[my_data$Id == 4, ] # Tutti i dai delle ragazze my_data[my_data$gender == "F", ] -# Le facoltà dei soggeti con più di 24 anni +# Le facoltà dei soggetti con più di 24 anni my_data[my_data$age > 24, c("age", "faculty")] ``` -Nota come, nel definire una condizione logica utilizzano le variabili dello stesso dataframe, sia comunque necessario indicare sempre anche il nome del dataframe. Nel caso precendente avremmo ottenuto un errore indicando semplicemente `age > 24` poichè così indichiamo l'oggetto `age` (che non esiste) e non la variabile `age` contenuta in `my_data`. +Nota come, nel definire una condizione logica utilizzano le variabili dello stesso dataframe, sia comunque necessario indicare sempre anche il nome del dataframe. Nel caso precedente avremmo ottenuto un errore indicando semplicemente `age > 24` poiché così indichiamo l'oggetto `age` (che non esiste) e non la variabile `age` contenuta in `my_data`. ```{r, echo = TRUE, error = TRUE} my_data[age > 24, c("age", "faculty")] ``` -In modo analogo a quanto visto con i vettori, utlizzando la condizione `my_data$age > 24` otteniamo un vettore di valori `TRUE` e `FALSE` a seconda che la condizione sia rispettata o meno. +In modo analogo a quanto visto con i vettori, utilizzando la condizione `my_data$age > 24` otteniamo un vettore di valori `TRUE` e `FALSE` a seconda che la condizione sia rispettata o meno. -Utilizzando gli operatori logici **AND**(`&`) **OR**(`|`) e **NOT**(`!`) possiamo combinare più operazioni logiche insieme per ottenere indicizzazioni più complesse, ma sempre intuitive dal punto di vista della scrittura. Ad esempio, per selezionare "I soggetti tra i 20 e i 25 anni iscrittti a psicologia " eseguiremo: +Utilizzando gli operatori logici **AND**(`&`) **OR**(`|`) e **NOT**(`!`) possiamo combinare più operazioni logiche insieme per ottenere indicizzazioni più complesse, ma sempre intuitive dal punto di vista della scrittura. Ad esempio, per selezionare "I soggetti tra i 20 e i 25 anni iscritti a psicologia " eseguiremo: ```{r, echo = TRUE} my_data[my_data$age >= 20 & my_data$age <=25 & my_data$faculty == "Psicologia", ] @@ -225,12 +225,12 @@ my_data[my_data$age >= 20 & my_data$age <=25 & my_data$faculty == "Psicologia", Utilizzando questo metodo di indicizzazione possiamo apprezzare la vera potenza dei dataframe. Abbiamo, infatti, un metodo molto semplice ed intuitivo per lavorare con strutture di dati complesse formate da diverse tipologie di dati. -:::{.design title="Output Selezione" data-latex="[Output Selezione]"} -Due aspetti importanti riguardanti il risultato di una selezione sono la tipologia di ouput ottenuto e come salvarla. +:::{.design title="Output selezione" data-latex="[Output selezione]"} +Due aspetti importanti riguardanti il risultato di una selezione sono la tipologia di output ottenuto e come salvarla. -#### Tiplogia Output {-} +#### Tipologia output {-} -In modo analogo alle matrici, i comandi di selezione non restituiscono sempre la stessa tipologia di oggetto. Infatti, quando selezioniamo una singola variabile otteniamo come risultato un vettore mentre selezionando due o più variabili oteniamo un dataframe. +In modo analogo alle matrici, i comandi di selezione non restituiscono sempre la stessa tipologia di oggetto. Infatti, quando selezioniamo una singola variabile otteniamo come risultato un vettore mentre selezionando due o più variabili otteniamo un dataframe. ```{r, echo = TRUE} # Singola variabile @@ -240,17 +240,17 @@ class(my_data$age) class(my_data[ , c("names", "age")]) ``` -#### Salvare Selezione {-} +#### Salvare selezione {-} -Come per tutte le altre tipologie di oggetti, le operazioni di selezione non modificano l'oggetto iniziale. Pertanto è necessario salvare il risultato della selezione se si desidera mantenere le modifiche. In questo caso, è cosigliabile creare un nuovo oggetto e non sovrascrivere l'oggetto iniziale poichè non ci permetterebbe di compiere nuove selezioni od operazioni su tutti i dati iniziali. E' buona norma quindi mantenere sempre un dataframe con la versione dei dati originali. +Come per tutte le altre tipologie di oggetti, le operazioni di selezione non modificano l'oggetto iniziale. Pertanto è necessario salvare il risultato della selezione se si desidera mantenere le modifiche. In questo caso, è consigliabile creare un nuovo oggetto e non sovrascrivere l'oggetto iniziale poiché non ci permetterebbe di compiere nuove selezioni od operazioni su tutti i dati iniziali. È buona norma quindi mantenere sempre un dataframe con la versione dei dati originali. ::: -### Utilizzi Avanzati Selezione +### Utilizzi avanzati selezione Vediamo ora alcuni utilizzi avanzati della selezione di elementi di un dataframe. -#### Modificare gli Elementi {-} +#### Modificare gli elementi {-} In modo analogo agli altri oggetti, possiamo modificare dei valori selezionando il vecchio valore della matrice e utilizzo la funzione `<-` (o `=`) per assegnare il nuovo valore. @@ -264,7 +264,7 @@ my_data[1:5] ``` -#### Eliminare Righe o Colonne {-} +#### Eliminare righe o colonne {-} In modo analogo agli altri oggetti, per **eliminare** delle righe (o delle colonne) da un dataframe, è necessario indicare all'interno delle parentesi quadre gli indici di riga (o di colonna) che si intende eliminare, preceduti dall'operatore `-` (*meno*). Nel caso di più righe (o colone) è possibile indicare il meno solo prima del comando `c()`. @@ -279,7 +279,7 @@ my_data[-c(1:5), ] my_data[-c(1:5), -3] ``` -E' possibile anche escludere (ed eliminare in un certo senso) delle informazioni usando gli operatori logici in gli operatori **NOT**(`!`) e diverso da (`!=`): +È possibile anche escludere (ed eliminare in un certo senso) delle informazioni usando gli operatori logici in gli operatori **NOT**(`!`) e diverso da (`!=`): ```{r, echo = T} # Seleziono tutto tranne gli studenti di psicologia @@ -293,8 +293,8 @@ my_data[!my_data$faculty == "Psicologia", ] Nota come l'operazione di eliminazione sia comunque un'operazione di selezione. Pertanto è necessario salvare il risultato ottenuto se si desidera mantenere le modifiche. -:::{.warning title="Attenzione ad Eliminare" data-latex="[Attenzione ad Esliminare]"} -L'utilizzo dell'operatore `-` è sempre in qualche modo pericoloso, sopratutto se l'oggetto che viene creato (o sovrascritto) viene poi utilizzato in altre operazioni. Eliminare delle informazioni, tranne quando è veramente necessario, non è mai una buona cosa. Se dovete selezionare una parte dei dati è sempre meglio creare un nuovo dataframe (o un nuovo oggetto in generale) e mantendere una versione di quello originale sempre disponibile. +:::{.warning title="Attenzione ad eliminare" data-latex="[Attenzione ad eliminare]"} +L'utilizzo dell'operatore `-` è sempre in qualche modo pericoloso, sopratutto se l'oggetto che viene creato (o sovrascritto) viene poi utilizzato in altre operazioni. Eliminare delle informazioni, tranne quando è veramente necessario, non è mai una buona cosa. Se dovete selezionare una parte dei dati è sempre meglio creare un nuovo dataframe (o un nuovo oggetto in generale) e mantenere una versione di quello originale sempre disponibile. ::: ### Esercizi {-} @@ -307,7 +307,7 @@ Facendo riferimento ai dataframe `data_long` e `data_wide` precedentemente creat 4. Considerando il DataFrame `data_long` seleziona solamente i dati riguardanti le ragazze con etè superiore ai 20 anni. 5. Elimina dal DataFrame `data_long` le osservazioni riguardanti il soggetto `subj_2` e la variabile `"gender"`. -## Funzioni ed Operazioni +## Funzioni e operazioni Vediamo ora alcune funzioni frequentemente usate e le comuni operazioni eseguite con i dataframe (vedi Tabella \@ref(tab:table-df-functions)). @@ -351,7 +351,7 @@ kableExtra::kable(df_operators, col.names = c("Funzione", "Descrizione"), latex_options = c("hold_position")) ``` -Descriviamo ora nel dettaglio alcuni particolari utilizzi, considrando come esempio una versione ridotta del dataframe `my_data` precedentemente creata. +Descriviamo ora nel dettaglio alcuni particolari utilizzi, considerando come esempio una versione ridotta del dataframe `my_data` precedentemente creata. ```{r, echo = TRUE} data_short <- my_data[1:5, ] @@ -359,7 +359,7 @@ data_short ``` -### Attributi di un Dataframe +### Attributi di un dataframe Abbiamo visto nel Capitolo \@ref(attributes) che gli oggetti in R possiedono quelli che sono definiti *attributi* ovvero delle utili informazioni riguardanti l'oggetto stesso, una sorta di *metadata*. Vediamo ora, in modo analogo alle matrici, come valutare la dimensione di un dataframe e i nomi delle righe e delle colonne. @@ -377,7 +377,7 @@ ncol(my_data) In alternativa, come per le matrici, è possibile usare la funzione `dim()`che restituisce un vettore con due valori dove il primo rappresenta il numero di righe e il secondo il numero di colonne. -#### Nomi Righe e Colonne {-} +#### Nomi righe e colonne {-} In modo simile alle matrici, è possibile accedere ai nomi delle righe e delle colonne utilizzando rispettivamente le funzioni `rownames()` e `colnames()`. Di default il dataframe richiede dei nomi solo alle colonne mentre il alle righe viene assegnato un nome in accordo con l'indice di riga. Tuttavia, è possibile anche nominare le righe con valori arbitrari sebbene sia una funzione raramente utilizzata. @@ -390,7 +390,7 @@ colnames(data_short) Per impostare i nomi di righe e/o colonne, sarà quindi necessario assegnare a `rownames(nome_dataframe)` e `colnames(nome_dataframe)` un vettore di caratteri della stessa lunghezza della dimensione che stiamo rinominando. ```{r, echo=TRUE} -# Assegnamo i nomi alle righe +# Assegniamo i nomi alle righe rownames(data_short) <- paste0("Subj_", 1:nrow(data_short)) # Assegno i nomi alle colonne @@ -399,7 +399,7 @@ colnames(data_short) <- c("Id", "Nome", "Genere", "Eta", "Facolta") data_short ``` -Infine, nota come la funzione `names()` nel caso dei dataframe sia analoga alla funzione `colnames()` e sia possibile usare il vaore `NULL` per eliminare ad esempio i nomi delle righe. +Infine, nota come la funzione `names()` nel caso dei dataframe sia analoga alla funzione `colnames()` e sia possibile usare il valore `NULL` per eliminare ad esempio i nomi delle righe. ```{r, echo = TRUE} names(data_short) @@ -408,9 +408,9 @@ data_short ``` -### Unire Dataframe +### Unire dataframe -In modo analogo alle matrici è possibile unire più dataframe utilizzando le funzioni `cbind()` e `rbind()` per cui valgono gli stesssi accorgimenti riguardanti la dimensione rispettivamente di righe e colonne. Tuttavia, nel caso dei dataframe è possibile creare una nuova colonna anche utilizzando l'operatore `$`. Descriviamo ora in modo accurato i differenti utilizzi. +In modo analogo alle matrici è possibile unire più dataframe utilizzando le funzioni `cbind()` e `rbind()` per cui valgono gli stessi accorgimenti riguardanti la dimensione rispettivamente di righe e colonne. Tuttavia, nel caso dei dataframe è possibile creare una nuova colonna anche utilizzando l'operatore `$`. Descriviamo ora in modo accurato i differenti utilizzi. #### `dataframe$name <- new_var` {-} @@ -481,19 +481,19 @@ rbind(data_short, new_row) Anche in questo caso sarà necessario salvare il risultato ottenuto per mantenere i cambiamenti. -### Informazioni Dataframe +### Informazioni dataframe Vediamo infine alcune funzioni molto comuni usate per ottenere informazioni riassuntive riguardo ai dati contenuti in un dataframe: -- `head()` (o `tail()`) ci permete di visualizzare le prime (o le ulitme righe del nostro dataframe) +- `head()` (o `tail()`) ci permette di visualizzare le prime (o le ultime righe del nostro dataframe) ```{r, echo = TRUE} head(my_data) ``` -- `str()` ci permete di valutare la struttura del dataset ottenendo utili informazini quali in numero di osservazioni, il numero di variabili e la ipologia di variabili +- `str()` ci permette di valutare la struttura del dataset ottenendo utili informazioni quali in numero di osservazioni, il numero di variabili e la tipologia di variabili ```{r, echo = TRUE} str(my_data) ``` -- `summary()` ci permete avere delle informazioni riassuntive delle variabili a seconda della loro tipologia +- `summary()` ci permette avere delle informazioni riassuntive delle variabili a seconda della loro tipologia ```{r, echo = TRUE} summary(my_data) ``` @@ -513,7 +513,7 @@ data.frame(Id=c("subj_1","subj_2","subj_3"), ```{r} data.frame(Id=c("subj_1","subj_2","subj_3"), - gruppo=c("trattamento","trattemento","controllo")) + gruppo=c("trattamento","trattamento","controllo")) ``` 3. Aggiungi al DataFrame `data_wide` i dati del soggetto `subj_4` e `subj_5`. @@ -526,8 +526,8 @@ data.frame(Id=c("subj_4","subj_5"), item_2=c(0,1), item_3=c(2,0), memory_pre=c(1,3), - gruppo=c("trattemento","controllo")) + gruppo=c("trattamento","controllo")) ``` -4. Considerando il DataFrame `datawide` calcola la variabile `"memory_post"` data dalla somma degli item. +4. Considerando il DataFrame `data_wide` calcola la variabile `"memory_post"` data dalla somma degli item. 5. Considerando il DataFrame `data_wide` cambia i nomi delle variabili `item_1`, `item_2` e `item_3` rispettivamente in `problem_1`, `problem_2` e `problem_3`. diff --git a/13-lists.Rmd b/13-lists.Rmd index aa1da9b..d31c627 100644 --- a/13-lists.Rmd +++ b/13-lists.Rmd @@ -15,17 +15,17 @@ Le **liste** sono uno degli oggetti più versatili e utili in R. Possiamo pensar A differenza di dataframe e matrici dove gli elementi sono tra loro in relazione, gli elementi di una lista sono completamente indipendenti. Una `lista`, infatti, può contenere oggetti completamente diversi tra loro sia per tipologia che per dimensioni, senza che vi sia alcuna relazione o vincolo. -Un modo utile per immaginarsi una lista (vedi Figura \@ref(fig:list-example)) è pensare ad un corridoio di un albergo dove ogni porta conduce ad una stanza diversa per caratteristiche, numero di elementi e così via. E' importante notare come gli elementi siano disposti in un preciso ordine e quindi possano essere identificati tramite il loro **indice di posizione**, in modo analogo a quanto visto con gli elementi di un vettore. +Un modo utile per immaginarsi una lista (vedi Figura \@ref(fig:list-example)) è pensare ad un corridoio di un albergo dove ogni porta conduce ad una stanza diversa per caratteristiche, numero di elementi e così via. È importante notare come gli elementi siano disposti in un preciso ordine e quindi possano essere identificati tramite il loro **indice di posizione**, in modo analogo a quanto visto con gli elementi di un vettore. ```{r list-example, fig.cap="Esempio concettuale di una lista", out.height="30%", out.width="30%"} knitr::include_graphics("images/list_example.png") ``` -Da un punto di vista pratico la lista è un oggetto molto semplice, simile ad un vettore, e molte delle sue caratteristiche sono in comune con gli altri oggetti che abbiamo già affrontato. Tuttavia, la difficltà principale risiede nella sua indicizzazione poichè, data la loro grande versatilità, le strutture delle liste possono ragiungere notevoli livelli di complessità. +Da un punto di vista pratico la lista è un oggetto molto semplice, simile ad un vettore, e molte delle sue caratteristiche sono in comune con gli altri oggetti che abbiamo già affrontato. Tuttavia, la difficoltà principale risiede nella sua indicizzazione poiché, data la loro grande versatilità, le strutture delle liste possono raggiungere notevoli livelli di complessità. -Vediamo ora come creare una lista e i diversi modi per sselezionare i suoi elementi. Come vedremo ci sono molte somiglianze nell'utilizzo dei dataframe e delle matrici. Quando necessario, si farà riferimento al capitolo precedente per far notare aspetti in comune e differenze tra queste due strutture di dati. +Vediamo ora come creare una lista e i diversi modi per selezionare i suoi elementi. Come vedremo ci sono molte somiglianze nell'utilizzo dei dataframe e delle matrici. Quando necessario, si farà riferimento al capitolo precedente per far notare aspetti in comune e differenze tra queste due strutture di dati. -## Creazione di Liste +## Creazione di liste Il comando per creare una lista è `list()`: @@ -36,9 +36,9 @@ nome_lista <- list( nome_oggetto_n = oggetto_n) ``` -Nonostante il parametro `nome_oggetto_x` non sia necessario, come vedremo è assolutamente consigliato rinominare tutti gli elementi della lista per agevolare l'indicizzazione. Se non nominiamo gli elementi, infatti, questi saranno identificati solo tramite il loro indice di posizione, ovvero un numero progressivo $1...n$ esattamente come nel caso dei vettori. Questo rende meno intutiva la successiva selezione degli elementi. +Nonostante il parametro `nome_oggetto_x` non sia necessario, come vedremo è assolutamente consigliato rinominare tutti gli elementi della lista per agevolare l'indicizzazione. Se non nominiamo gli elementi, infatti, questi saranno identificati solo tramite il loro indice di posizione, ovvero un numero progressivo $1...n$ esattamente come nel caso dei vettori. Questo rende meno intuitiva la successiva selezione degli elementi. -Quindi, se nel nostro workspace abbiamo degli oggetti diversi come una semplice `variabile`, un `vettore` e un `dataframe`, possiamo raccoglieere tutti questi elementi dentro un'unica lista. Ad esempio: +Quindi, se nel nostro workspace abbiamo degli oggetti diversi come una semplice `variabile`, un `vettore` e un `dataframe`, possiamo raccogliere tutti questi elementi dentro un'unica lista. Ad esempio: ```{r, echo = TRUE} # Una variabile @@ -76,9 +76,9 @@ Considerando gli oggetti creati nei precedenti capitoli, esegui i seguenti eserc - il vettore `y` - la variabile `info = "Seconda raccolta dati"` -## Selezione Elementi +## Selezione elementi -Come dicevamo in precedenza, ogni elemento di una lista possiende il suo **indice di posizione**, ovvero un valore numerico progressivo in modo del tutto analogo a quanto visto per gli elementi di un vettore. Tuttavia, c'è un'importante differenza per quanto riguarda la modalità di selezione in base al tipo di oggetto che si vuole ottenere come risultato. Infatti, mentre con i vettori usavamo le singole parentesi quadre `my_vector[i]` per accedere direttamente all'elemento alla posizione $i$, con le liste abbiamo due alternative: +Come dicevamo in precedenza, ogni elemento di una lista possiede il suo **indice di posizione**, ovvero un valore numerico progressivo in modo del tutto analogo a quanto visto per gli elementi di un vettore. Tuttavia, c'è un'importante differenza per quanto riguarda la modalità di selezione in base al tipo di oggetto che si vuole ottenere come risultato. Infatti, mentre con i vettori usavamo le singole parentesi quadre `my_vector[i]` per accedere direttamente all'elemento alla posizione $i$, con le liste abbiamo due alternative: - `my_list[i]` - utilizzando le **singole parentesi quadre** (`[i]`) otteniamo come risultato un oggetto di tipo lista con all'interno l'elemento alla posizione $i$. Questo non ci permette, tuttavia, di accedere direttamente ai suoi valori. - `my_list[[i]]` - utilizzando le **doppie parentesi quadre** (`[[i]]`) estraiamo dalla lista l'elemento alla posizione $i$ e come risultato otteniamo l'oggetto stesso. Questo ci permette quindi di accedere direttamente ai suoi valori. @@ -96,7 +96,7 @@ my_list[[2]] class(my_list[[2]]) # un vettore ``` -Questa differenza nel risultato ottenuto usando le **singole parentesi quadre** (`[ ]`) o le **doppie parentesi quadre** (`[[ ]]`) è molto importante perché influirà sulle successive operazioni che potremmo compiere. Ricordiamo che nel primo caso (`[ ]`) ottenimo una lista con i soli elementi selezionati, mentre nel secondo caso (`[[ ]]`) accediamo direttamente all'oggetto selezionato. +Questa differenza nel risultato ottenuto usando le **singole parentesi quadre** (`[ ]`) o le **doppie parentesi quadre** (`[[ ]]`) è molto importante perché influirà sulle successive operazioni che potremmo compiere. Ricordiamo che nel primo caso (`[ ]`) otteniamo una lista con i soli elementi selezionati, mentre nel secondo caso (`[[ ]]`) accediamo direttamente all'oggetto selezionato. Questa distinzione diventa chiara applicando una funzione generica allo stesso elemento indicizzato in modo diverso oppure usando la funzione `str()` per capire la struttura. Vediamo come solo accedendo direttamente all'elemento possiamo eseguire le normali operazioni, mentre, indicizzando con una sola parentesi, l'oggetto ottenuto è una lista con un singolo elemento. @@ -111,13 +111,13 @@ str(my_list[[2]]) ``` -:::{.design title="[ ] vs [[ ]]" data-latex="[{[ ] vs [[ ]]}]"} +:::{.design title="\\texttt{[ ]} vs \\texttt{[[ ]]}" data-latex="\\texttt{[ ]} vs \\texttt{[[ ]]}"} Il diverso tipo di selezione ottenuto con l'utilizzo delle singole o doppie parentesi quadre è definito nel seguente modo: - **singole parentesi quadre** (`[ ]`) - restituisce un oggetto della stessa classe (i.e., tipologia) dell'oggetto iniziale - **doppie parentesi quadre** (`[[ ]]`) - estrae un elemento dall'oggetto iniziale restituendo un oggetto non necessariamente della stessa classe (i.e., tipologia) -Vediamo quindi come sia possibile utilizzare le doppie parentesi anche con i vettori e i dataframe ma in questo caso il risultato non differeisce dalla normale procedura di selezione. +Vediamo quindi come sia possibile utilizzare le doppie parentesi anche con i vettori e i dataframe ma in questo caso il risultato non differisce dalla normale procedura di selezione. ```{r, echo = TRUE} # Vettori my_vector[2] @@ -125,7 +125,7 @@ my_vector[[2]] # Dataframe my_data[, 2] -my_data[[2]] # la selezione è posibile solo sulle colonne +my_data[[2]] # la selezione è possibile solo sulle colonne ``` Nota infine come l'uso di singole parentesi quadre (`[ ]`) permette di selezionare più elementi contemporaneamente, mentre le doppie parentesi quadre (`[[ ]]`) permettono di estrarre solo un elemento alla volta @@ -137,7 +137,7 @@ my_list[[c(1,2)]] ``` ::: -#### Selezione Operatore `$` {-} +#### Selezione operatore `$` {-} In alternativa all'uso delle **doppie parentesi quadre** (`[[ ]]`) è possibile, in modo analogo ai dataframe, accedere agli elementi di una lista utilizzando l'operatore `$` ed indicando il loro nome: @@ -157,9 +157,9 @@ Nota come il nome degli elementi possa essere usato anche con le parentesi quadr my_list[c("elemento_1", "elemento_2")] ``` -#### Utilizzo Elementi e Successive Selezioni {-} +#### Utilizzo elementi e successive selezioni {-} -Una volta che abbiamo estratto un elemento da una lista, è possibile utilizzare l'oggetto nel modo che preferiamo. Possiamo sia assegnare l'elemento ad nuovo oggetto da utilizzare successvamente, oppure eseguire le funzioni o altre operazioni generiche direttamente sul comando della selezione. +Una volta che abbiamo estratto un elemento da una lista, è possibile utilizzare l'oggetto nel modo che preferiamo. Possiamo sia assegnare l'elemento ad nuovo oggetto da utilizzare successivamente, oppure eseguire le funzioni o altre operazioni generiche direttamente sul comando della selezione. ```{r, echo = T} # Media dei valori dell' "elemento_2" @@ -192,13 +192,13 @@ my_list[[3]][, 2] my_list[[3]][, "gender"] ``` -### Utilizzi Avanzati Selezione +### Utilizzi avanzati selezione Vediamo ora alcuni utilizzi avanzati della selezione di elementi di un dataframe. -#### Modificare gli Elementi {-} +#### Modificare gli elementi {-} -In modo analogo agli altri oggetti, possiamo modificare dei valori selezionando il vecchio elemento della lista e utilizzo la funzione `<-` (o `=`) per assegnare il nuovo elemento. Nota come in questo caso sia possibile uttilizzare sia le singole parentesi quadre (`[ ]`) che le doppie parentesi quadre (`[[ ]]`). +In modo analogo agli altri oggetti, possiamo modificare dei valori selezionando il vecchio elemento della lista e utilizzo la funzione `<-` (o `=`) per assegnare il nuovo elemento. Nota come in questo caso sia possibile utilizzare sia le singole parentesi quadre (`[ ]`) che le doppie parentesi quadre (`[[ ]]`). ```{r, echo = TRUE} my_list @@ -212,9 +212,9 @@ my_list[[2]] <- "Un altro nuovo elemento" my_list ``` -#### Eliminare Elementi {-} +#### Eliminare elementi {-} -In modo analogo agli altri oggetti, per **eliminare** degli elementi da una lista, è necessario indicare all'interno delle parentesi quadre gli indici di posizione degli elementi che si intende eliminare, preceduti dall'operatore `-` (*meno*). In questo caso è necessario l'utilizzo delle singole parentesi quadre (`[ ]`). +In modo analogo agli altri oggetti, per **eliminare** degli elementi da una lista, è necessario indicare all'interno delle parentesi quadre gli indici di posizione degli elementi che si intende eliminare, preceduti dall'operatore `-` (*meno*). In questo caso è necessario l'utilizzo delle singole parentesi quadre (`[ ]`). ```{r, echo = TRUE} # Elimino il secondo elemento @@ -227,12 +227,12 @@ Ricorda come l'operazione di eliminazione sia comunque un'operazione di selezion Esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-11-lists.R)) -1. Utilizzando gli **indici numerici** di posizione selziona i dati dei soggetti `subj_1` e `subj_4` riguardanti le variabili `age`,`gender` e `gruppo` dal DataFrame `data_wide` contenuto nella lista `esperimento_1`. +1. Utilizzando gli **indici numerici** di posizione seleziona i dati dei soggetti `subj_1` e `subj_4` riguardanti le variabili `age`,`gender` e `gruppo` dal DataFrame `data_wide` contenuto nella lista `esperimento_1`. 2. Compi la stessa selezione dell'esercizio precedente usando però questa volta il nome dell'oggetto per selezionare il DateFrame dalla lista. 3. Considerando la lista `esperimento_2` seleziona gli oggetti `data_long`, `y` e `info` 4. Cambia i nomi degli oggetti contenuti nella lista `esperimento_2` rispettivamente in `"dati_esperimento"`, `"matrice_VCV"`, `"codici_Id"` e `"note"` -## Funzioni ed Operazioni +## Funzioni e operazioni Vediamo ora alcune funzioni frequentemente usate e le comuni operazioni eseguite con le liste (vedi Tabella \@ref(tab:table-list-functions)). @@ -265,13 +265,13 @@ if (knitr::is_latex_output()) { } kableExtra::kable(list_operators, col.names = c("Funzione", "Descrizione"), - escape = escape, caption = "Funzioni ed operazioni con liste") %>% + escape = escape, caption = "Funzioni e operazioni con liste") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = F, latex_options = c("hold_position")) ``` -Descriviamo ora nel dettaglio alcuni particolari utilizzi, considrando come esempio la lista `my_list` qui definita. Nota che i nomi degli elemnti sono stati omessi volutamente. +Descriviamo ora nel dettaglio alcuni particolari utilizzi, considerando come esempio la lista `my_list` qui definita. Nota che i nomi degli elementi sono stati omessi volutamente. ```{r, echo = TRUE} my_list <- list(my_value, @@ -279,7 +279,7 @@ my_list <- list(my_value, my_data) ``` -### Attributi di una Lista +### Attributi di una lista Anche le liste come gli altri oggetti, hanno degli *attributi* ovvero delle utili informazioni riguardanti l'oggetto stesso. Vediamo ora come valutare la dimensione di una lista e i nomi dei suoi elementi. @@ -292,7 +292,7 @@ Per valutare la dimensione di una lista, ovvero il numero di elementi che contie length(my_list) ``` -#### Nomi Elementi {-} +#### Nomi elementi {-} Per accedere ai nomi degli elementi di una lista, è possibile utilizzare la funzione `names()`. Se i nomi non sono stati specificati al momento della creazione, otterremo il valore `NULL`. @@ -304,19 +304,19 @@ names(my_list) Per impostare i nomi degli elementi, sarà quindi necessario assegnare a `names(my_list)` un vettore di caratteri con i nomi di ciascun elemento. ```{r, echo=TRUE} -# Assegnamo i nomi +# Assegniamo i nomi names(my_list) <- c("Variabile", "Vettore", "Dataframe") my_list ``` -### Unire Liste +### Unire liste -Per aggiungere elementi ad una lista è possibile sia creare un nuovo elemento con l'operatore `$`, in modo annalogo ai datafame, sia combinare più liste con la funzione `c()`. +Per aggiungere elementi ad una lista è possibile sia creare un nuovo elemento con l'operatore `$`, in modo analogo ai datafame, sia combinare più liste con la funzione `c()`. #### `my_list$name <- new_obj` {-} -Con la scrittura `my_list$name <- new_obj` aggiungiamo alla lista in oggetto un nuovo elemento di cui dobbiamo specificare il nome e gli assegnamo l'oggetto `new_obj`. +Con la scrittura `my_list$name <- new_obj` aggiungiamo alla lista in oggetto un nuovo elemento di cui dobbiamo specificare il nome e gli assegniamo l'oggetto `new_obj`. ```{r, echo = T} # Aggiungiamo un nuovo elemento @@ -340,22 +340,22 @@ c(my_list, list(new_vector = 1:3)) In questo caso sarà necessario salvare il risultato ottenuto per mantenere i cambiamenti. -### Informazioni Lista +### Informazioni lista Vediamo infine alcune funzioni molto comuni usate per ottenere informazioni riassuntive riguardo gli elementi di una lista: -- `str()` ci permete di valutare la struttura della lista ottenendo utili informazini quali in numero di elementi e la loro tipologia +- `str()` ci permette di valutare la struttura della lista ottenendo utili informazioni quali in numero di elementi e la loro tipologia ```{r, echo = TRUE} str(my_list) ``` -- `summary()` ci permete avere delle informazioni riassuntive degli elementi tuttavia risulta poco utlie +- `summary()` ci permette avere delle informazioni riassuntive degli elementi tuttavia risulta poco utile ```{r, echo = TRUE} summary(my_list) ``` -## Struttura Nested +## Struttura nested -Al contrario dei vettori che si estendono in *lunghezza* o dei dataframe/matrici che sono caratterizzati da righe e colonne, la peculiarità della lista (oltre alla lunghezza come abbaimo visto) è il concetto di **profondità**. Infatti una lista può contenere al suo interno una o più liste di fatto creando una **struttura nidificata molto complessa**. Nonostante la struttura più complessa, il principio di indicizzazione e creazione è lo stesso. La Figura \@ref(fig:list-depth) rappresenta l'idea di una lista nidificata (o nested): +Al contrario dei vettori che si estendono in *lunghezza* o dei dataframe/matrici che sono caratterizzati da righe e colonne, la peculiarità della lista (oltre alla lunghezza come abbiamo visto) è il concetto di **profondità**. Infatti una lista può contenere al suo interno una o più liste di fatto creando una **struttura nidificata molto complessa**. Nonostante la struttura più complessa, il principio di indicizzazione e creazione è lo stesso. La Figura \@ref(fig:list-depth) rappresenta l'idea di una lista nidificata (o nested): ```{r list-depth, out.height="50%", out.width="50%", fig.cap="Rappresentazione concettuale di una lista nested"} knitr::include_graphics("images/list_depth.png") @@ -409,7 +409,8 @@ Se il vantaggio di un dataframe rispetto ad una matrice è palese, quale è la v I vantaggi principali che rendono le liste degli oggetti estremamente potenti sono: * **Organizzare strutture complesse di dati**: come abbiamo visto nell'esempio precedente, insiemi di oggetti nidificati possono essere organizzati in un oggetto unico senza avere decine di singoli oggetti nel workspace. -* **Effettuare operazioni complesse su più oggetti parallelamente**. Immaginate di avere una lista di dataframe strutturalmente simili ma con dati diversi all'interno. Se volete applicare una funzione ad ogni dataframe potete organizzare i dati in una lista e usare le funzioni dell'`apply` family che vedremo nei prossimi capitoli. TODO +* **Effettuare operazioni complesse su più oggetti parallelamente**. Immaginate di avere una lista di dataframe strutturalmente simili ma con dati diversi all'interno. Se volete applicare una funzione ad ogni dataframe potete organizzare i dati in una lista e usare le funzioni dell'`apply` family che vedremo nei prossimi capitoli. + -Infine, proprio per la loro flessibilità, le liste sono spesso utilizzate da vari pachetti per restituire i risultati delle analisi statistiche svolte. Saper accedere ai vari elementi di una lista risulta quindi necessario per ottenere specifiche infomazioni e risultati. +Infine, proprio per la loro flessibilità, le liste sono spesso utilizzate da vari pacchetti per restituire i risultati delle analisi statistiche svolte. Saper accedere ai vari elementi di una lista risulta quindi necessario per ottenere specifiche informazioni e risultati. ::: diff --git a/14-introduction-algorithms.Rmd b/14-introduction-algorithms.Rmd index 0aa6dc8..af7bddd 100644 --- a/14-introduction-algorithms.Rmd +++ b/14-introduction-algorithms.Rmd @@ -2,12 +2,11 @@ # Introduzione {#third-section -} -In questa sezione verranno introdotte le principali tipologie di oggetti usati in R . Ovvero le principali strutture in cui possono essere organizzati i dati: Vettori, Matrici, Dataframe e Liste. - -Per ognuna di esse descriveremo le loro caretteristiche e vedremo come crearle, modificarle e manipolarle a seconda delle necessità + +Work in progress. I capitoli sono così organizzati: - **Capitolo \@ref(functions) - Funzioni**. Vedremo come creare le proprie funzioni personalizzate in R per eseguire degli specifici compiti. -- **Capitolo \@ref(conditionals) - Programmazione Condizionale**. Impareremo come gestire l'esecuzione di un algoritmo attraverso l'uso degli operatori `if` e `else`. -- **Capitolo \@ref(loop) - Programmazione Iterativa**. Introdurremo l'uttilizzo degli operatori `for` e `while` per l'esecuzione di loop. +- **Capitolo \@ref(conditionals) - Programmazione condizionale**. Impareremo come gestire l'esecuzione di un algoritmo attraverso l'uso degli operatori `if` e `else`. +- **Capitolo \@ref(loop) - Programmazione iterativa**. Introdurremo l'utilizzo degli operatori `for` e `while` per l'esecuzione di loop. diff --git a/15-functions.Rmd b/15-functions.Rmd index 0854699..fb4b3bf 100644 --- a/15-functions.Rmd +++ b/15-functions.Rmd @@ -1,4 +1,4 @@ -# Definizione di Funzioni {#functions} +# Definizione di funzioni {#functions} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -12,7 +12,7 @@ Nel Capitolo \@ref(functions-def) abbiamo introdotto il concetto di funzioni e a Questo è uno dei vantaggi principali di utilizzare un linguaggio di programmazione, ovvero il poter sviluppare funzioni ad-hoc a seconda delle proprie esigenze e non limitarsi a quelle prestabilite. In questo capitolo descriveremo come creare le proprie funzioni in R. -## Creazione di una Funzione +## Creazione di una funzione Il comando usato per creare una funzione in R è `function()` seguito da una coppia di parentesi graffe `{ }` al cui interno deve essere specificato il corpo della funzione: @@ -43,13 +43,13 @@ my_sum <- function(){ my_sum() ``` -Quando chiamiamo la nostra funzione, R eseguirà il corpo della funzione e ci restituirà il risultato dell'ultimo comando eseguito. Le funzioni del precedente esempio, tuttavia, si rivelano poco utili poichè eseguono sempre le stesse operazioni senza che ci sia permesso di specificare gli input delle funzioni. Inoltre, sebbene siano funzioni molto semplici, potrebbe non risultare chiaro quale sia effettivamente l'output restituito dalla funzione. +Quando chiamiamo la nostra funzione, R eseguirà il corpo della funzione e ci restituirà il risultato dell'ultimo comando eseguito. Le funzioni del precedente esempio, tuttavia, si rivelano poco utili poiché eseguono sempre le stesse operazioni senza che ci sia permesso di specificare gli input delle funzioni. Inoltre, sebbene siano funzioni molto semplici, potrebbe non risultare chiaro quale sia effettivamente l'output restituito dalla funzione. :::{design title="Nomi Funzioni" data-latex="[Nomi Funzioni]"} Nel definire il nome di una funzione è utile seguire le stese indicazioni che riguardavano i nomi degli oggetti (vedi Capitolo \@ref(objects-names)). In questo caso affinché un nome sia **auto-descrittivo** si tende ad utilizzare verbi che riassumano l'azione eseguita dalla funzione. ::: -### Definire Input e Output +### Definire input e output Ricordiamo che in generale le funzioni, ricevuti degli oggetti in input, compiono determinate azioni e restituiscono dei nuovi oggetti in output. Input e ouput sono quindi due aspetti aspetti fondamentali di ogni funzione che richiedono particolare attenzione. @@ -103,12 +103,12 @@ happy_birthday <- function(){ happy_birthday() ``` -Nota che questa funzione possona essere usata solo in sessioni interattive di R poichè è richiesta un 'azione diretta da parte dell'utente. +Nota che questa funzione possona essere usata solo in sessioni interattive di R poiché è richiesta un 'azione diretta da parte dell'utente. ::: -#### Default Argomenti {-} +#### Valori di default degli argomenti {-} -Abbiamo visto come aggiungere degli argomenti che devono essere definiti dall'utente nell'utilizzare la funzione. Qualora l'utente non specifichi uno o più argomenti R riporterà un messaggio di errore indicando come ci siano degli argomenti non specificati e senza valori di default. +Abbiamo visto come aggiungere degli argomenti che devono essere definiti dall'utente nell'utilizzare la funzione. Qualora l'utente non specifichi uno o più argomenti R riporterà un messaggio di errore indicando come ci siano degli argomenti non specificati e senza valori di default. ```{r, echo = TRUE, error = TRUE} my_sum(x = 5) @@ -127,12 +127,12 @@ my_sum <- function(x, y = 10){ my_sum(x = 5) # Specifico il valore id y -my_sum(x = 5, y = 8) +my_sum(x = 5, y = 8) ``` Questa pratica è molto usata per specificare comportamenti particolari delle funzioni. In genere le funzioni sono definite con un funzionameto di default ma alcuni argomenti possono essere specificati per particolari essigenze solo quando necessario. -:::{.trick title="match.arg()" data-latex="[match.arg()]"} +:::{.trick title="\\texttt{match.arg()}" data-latex="[\\texttt{match.arg()}]"} Per imporre la scelta di un argomento tra una limitata serie di valori è possibile indicare nella definizione dell'argomento un vettore con le possibili entrate. Successivamente la scelta deve essere validata attraverso la funzione `match.arg()` come nell esempio successivo: ```{r, echo = TRUE, error = TRUE} @@ -172,9 +172,9 @@ Esegui i seguenti esercizi: 5. Definisci una funzione che calcoli lo stipendio mensile sulla base delle ore svolte nel mese e la paga oraria. -## Lavorare con le Funzioni +## Lavorare con le funzioni -Le funzioni sono sicuramente l'aspetto più utile e avanzato del linguaggio R e in generale dei linguaggi di programmazione. I pacchetti che sono sviluppati in R non sono altro che insieme di funzioni che lavorano assieme per uno scopo preciso. Oltre allo scopo della funzione è importante capire come gestire gli **errori e gli imprevisti**. Se la funzione infatti accetta degli argomenti, l'utente finale o noi stessi che la utilizziamo possiamo erroneamente usarla nel modo sbagliato. E' importante quindi capire come leggere gli errori ma sopratutto creare messaggi di errore o di avvertimento utili per l'utilizzo della funzione. +Le funzioni sono sicuramente l'aspetto più utile e avanzato del linguaggio R e in generale dei linguaggi di programmazione. I pacchetti che sono sviluppati in R non sono altro che insieme di funzioni che lavorano assieme per uno scopo preciso. Oltre allo scopo della funzione è importante capire come gestire gli **errori e gli imprevisti**. Se la funzione infatti accetta degli argomenti, l'utente finale o noi stessi che la utilizziamo possiamo erroneamente usarla nel modo sbagliato. È importante quindi capire come leggere gli errori ma sopratutto creare messaggi di errore o di avvertimento utili per l'utilizzo della funzione. Prendiamo ad esempio la funzione somma `+`, anche se non sembra infatti l'operatore `+` è in realtà una funzione. Se volessimo scriverlo come una funzione simile a quelle viste in precedenza possiamo: @@ -193,7 +193,7 @@ Abbiamo definito una (abbastanza inutile) funzione per calcolare la somma tra du ```{r, error=TRUE} my_sum("stringa", 5) ``` -In questo caso infatti, vediamo un messaggio denominato `Error...` con l'utile informazione che uno degli argomenti utilizzati risulta essere `non-numeric`. E' un messaggio semplice, mirato e sopratutto non fornisce un risultato perchè una condizione fondamentale (la somma vale solo per i numeri) non è rispettata. La funzione `+` ha già al suo interno questo controllo, ma se noi volessimo implementare un **controllo** e fornire un **messaggio** abbiamo a disposizione diverse opzioni: +In questo caso infatti, vediamo un messaggio denominato `Error...` con l'utile informazione che uno degli argomenti utilizzati risulta essere `non-numeric`. È un messaggio semplice, mirato e sopratutto non fornisce un risultato perché una condizione fondamentale (la somma vale solo per i numeri) non è rispettata. La funzione `+` ha già al suo interno questo controllo, ma se noi volessimo implementare un **controllo** e fornire un **messaggio** abbiamo a disposizione diverse opzioni: - `stop(, .call = TRUE)`: Se inserito all'interno di una funzione, interrompe l'esecuzione e fornisce il messaggio specificato denominato come `Error`. - `stopifnot(expr1, expr2, ...)`: Se inserito all'interno di una funzione interrompe l'esecuzione se almeno una di una serie di condizioni risulta come **non VERA**. @@ -279,7 +279,7 @@ res2 res3 # nessun output ``` -Come vedete infatti, quando abbiamo un errore e fermiamo l'esecuzione, la funzione pur prevedendo un output, non fornisce risultato perchè è stata interrotta. +Come vedete infatti, quando abbiamo un errore e fermiamo l'esecuzione, la funzione pur prevedendo un output, non fornisce risultato perché è stata interrotta. ## Ambiente della funzione @@ -292,7 +292,7 @@ my_fun <- function(x){ my_fun(10) ``` -Chiaramente otteniamo un errore perchè l'oggetto `y` non è stato creato. Se però creiamo l'oggetto `y` all'interno della funzione, questa esegue regolarmente la somma MA non crea l'oggetto `y` nell'ambiente globale. +Chiaramente otteniamo un errore perché l'oggetto `y` non è stato creato. Se però creiamo l'oggetto `y` all'interno della funzione, questa esegue regolarmente la somma MA non crea l'oggetto `y` nell'ambiente globale. ```{r} my_fun <- function(x){ @@ -348,7 +348,7 @@ Le cose importanti da ricordare quando si definiscono e utilizzano funzioni sono [^capitolo-7-hadley]: per una non semplice trattazione dell'argomento, il [capitolo 7](https://adv-r.hadley.nz/environments.html) del libro "Advanced R" di Hadley Wickam è un ottima risorsa. -## Best practice +## Best Practice Scrivere funzioni è sicuramente l'aspetto più importante quando si scrive del codice. Permette di automatizzare operazioni, ridurre la quantità di codice, rendere più chiaro il nostro script e riutilizzare una certa porzione di codice in altri contesti. Ci sono tuttavia delle convenzioni e degli accorgimenti per scrivere delle ottime e versatili funzioni: @@ -415,12 +415,12 @@ Questo potrebbe sembrare un argomento marginale tuttavia la scelta dei nomi sia - leggere chiaramente il nostro codice e renderlo comprensibile ad altri - organizzare facilmente un gruppo di funzioni. Quando avete più funzioni, usare una giusta denominazione permette di sfruttare i suggerimenti di RStudio in modo più efficace. Il pacchetto [`stringr`](https://stringr.tidyverse.org/) and esempio che fornisce strumenti per lavorare con stringhe, utilizza tutte le funzioni denominate come `str_` permettendo di cercare facilmente quella desiderata. -E' utile utilizzare **verbi** per nominare le funzioni mentre **nomi** per nominare argomenti. Ad esempio un nome adatto alla nostra ultima funzione potrebbe essere `center_var()` mentre il nome del nuovo vettore `centered_vec` o `c_vec`. Se troviamo `center_var` all'interno di uno script è subito chiaro il compito di quella funzione, anche senza guardare il codice al suo interno. +È utile utilizzare **verbi** per nominare le funzioni mentre **nomi** per nominare argomenti. Ad esempio un nome adatto alla nostra ultima funzione potrebbe essere `center_var()` mentre il nome del nuovo vettore `centered_vec` o `c_vec`. Se troviamo `center_var` all'interno di uno script è subito chiaro il compito di quella funzione, anche senza guardare il codice al suo interno. -### Semplificare la quantita di operazioni e output +### Semplificare la quantità di operazioni e output Questo è un punto molto importante ma allo stesso tempo variegato. Ci sono diversi stili di programmazione e quindi non ci sono regole fisse oppure delle pratiche migliori di altre. -Abbiamo detto che una funzione è un modo per astrarre, riutilizzare e semplificare una serie di operazioni. Possiamo quindi scrivere funzioni molto complesse che ricevono diversi input, eseguono diverse operazioni e restituiscono diversi output. E' buona pratica però scrivere funzioni che: +Abbiamo detto che una funzione è un modo per astrarre, riutilizzare e semplificare una serie di operazioni. Possiamo quindi scrivere funzioni molto complesse che ricevono diversi input, eseguono diverse operazioni e restituiscono diversi output. È buona pratica però scrivere funzioni che: - riducono il numero di operazioni interne - forniscono un singolo (o limitati) output @@ -473,7 +473,7 @@ In questo modo il codice è molto più leggibile e chiaro sia dentro le funzioni ### Commentare e documentare -La documentazione è forse la parte di più importante della scrittura del codice. Possiamo classificarla in documentazione *formale* e *informale* in base allo scopo. La documentazione *formale* è quella che troviamo facendo `help(funzione)` oppure `?funzione`. E' una documentazione standardizzata e necessaria quando si creano delle funzioni in un pacchetto che altri utenti devono utilizzare. La documentazione *informale* è quella che mettiamo nei nostri script e all'interno delle funzioni come `# commento`. Entrambe sono molto importati e permettono di descrivere lo scopo generale della funzione, i singoli argomenti e i passaggi eseguiti. +La documentazione è forse la parte di più importante della scrittura del codice. Possiamo classificarla in documentazione *formale* e *informale* in base allo scopo. La documentazione *formale* è quella che troviamo facendo `help(funzione)` oppure `?funzione`. È una documentazione standardizzata e necessaria quando si creano delle funzioni in un pacchetto che altri utenti devono utilizzare. La documentazione *informale* è quella che mettiamo nei nostri script e all'interno delle funzioni come `# commento`. Entrambe sono molto importati e permettono di descrivere lo scopo generale della funzione, i singoli argomenti e i passaggi eseguiti. ## Importare una funzione @@ -490,10 +490,12 @@ Anche in questo caso è una questione di stile e comodità, in generale: Nel secondo caso è sufficiente quindi scrivere la funzione e questa sarà salvata come oggetto nell'ambiente principale. Riguardo il primo scenario si può utilizzare la funzione `source("percorso/script.R")`. La funzione `source()` accetta il percorso di uno script R che verrà poi eseguito in background. Quindi se la vostra directory è organizzata in questo modo: ``` -- working directory/ -|-- main_script.R -|-- functions/ - |-- my_functions.R +working_directory/ + | + |- main_script.R + |- functions/ + | | + | |- my_functions.R ``` Dove lo script `my_functions.R` è uno script dove sono dichiarare tutte le funzioni: diff --git a/16-conditionals.Rmd b/16-conditionals.Rmd index 86a4f2f..d5f894f 100644 --- a/16-conditionals.Rmd +++ b/16-conditionals.Rmd @@ -1,4 +1,4 @@ -# Programmazione Condizionale {#conditionals} +# Programmazione condizionale {#conditionals} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -8,7 +8,7 @@ knitr::opts_chunk$set( ) ``` -Uno dei principali costrutti della programmazione sono proprio le espressioni condizionali. L'idea semplice alla base è quella di eseguire alcune operazioni o eseguire le operazioni in un certo modo in funzione di alcune *condizioni*. Le condizioni non sono altro che espressioni che resituiscono sempre un valore *booelan* ovvero `TRUE` oppure `FALSE`. +Uno dei principali costrutti della programmazione sono proprio le espressioni condizionali. L'idea semplice alla base è quella di eseguire alcune operazioni o eseguire le operazioni in un certo modo in funzione di alcune *condizioni*. Le condizioni non sono altro che espressioni che restituiscono sempre un valore *booelan* ovvero `TRUE` oppure `FALSE`. L'esempio classico è quello dell'ombrello, immaginate di scrivere il codice per un videogioco e avete scritto una funzione per far prendere prendere e aprire l'ombrello al vostro personaggio. Chiaramente per rendere tutto credibile, dovete far eseguire questa operazione solo quando è richiesto ovvero quando piove. In termini di programmazione, dovete prima verificare una certa condizione (la pioggia) e poi eseguire (o non eseguire) una serie di operazioni di conseguenza. @@ -79,13 +79,13 @@ my_function(-5) ### if...else -Il semplice utilizzo di un singolo `if` potrebbe non essere sufficiente in alcune situazioni. Sopratutto perchè possiamo vedere l'`if` come una deviazione temporanea dallo script principale (molto chiaro nella figura \@ref(fig:plot-if-chart)) che viene imboccata solo se è vera una condizione, altrimenti lo script continua. Se vogliamo una struttura più "simmetrica" possiamo eseguire delle operazioni se la condizone è vera `if` e altre per tutti gli altri scenari (`else`). La Figura \@ref(fig:plot-ifelse-chart) mostra chiaramente questa struttura diversa nel flusso. +Il semplice utilizzo di un singolo `if` potrebbe non essere sufficiente in alcune situazioni. Sopratutto perché possiamo vedere l'`if` come una deviazione temporanea dallo script principale (molto chiaro nella figura \@ref(fig:plot-if-chart)) che viene imboccata solo se è vera una condizione, altrimenti lo script continua. Se vogliamo una struttura più "simmetrica" possiamo eseguire delle operazioni se la condizione è vera `if` e altre per tutti gli altri scenari (`else`). La Figura \@ref(fig:plot-ifelse-chart) mostra chiaramente questa struttura diversa nel flusso. ```{r, plot-ifelse-chart, fig.cap="Rappresentazione if...else", out.width="65%"} knitr::include_graphics("images/ifelse_chart.png") ``` -#### Struttura if {-} +#### Struttura if...else {-} In R questo viene implementato nel seguente modo: @@ -142,7 +142,7 @@ my_function(15) my_function(-5) ``` -E' importante capire la differenza tra usare multipli `if` e `else if` rispetto a utilizzare un semplice `else`. Se noi vogliamo specificare un set **finito** di alternative, la scelta migliore e quella più chiara consiste di usere `else if` perchè al contrario di `else` richiede di specificare la condizione. Se invece siamo interessanti ad alcune condizioni mentre per tutto il resto applichiamo la stessa operazione, possiamo concludere il nostro flusso con un `else`. +È importante capire la differenza tra usare multipli `if` e `else if` rispetto a utilizzare un semplice `else`. Se noi vogliamo specificare un set **finito** di alternative, la scelta migliore e quella più chiara consiste di usare `else if` perché al contrario di `else` richiede di specificare la condizione. Se invece siamo interessanti ad alcune condizioni mentre per tutto il resto applichiamo la stessa operazione, possiamo concludere il nostro flusso con un `else`. ### Nested @@ -152,7 +152,7 @@ Oltre a concatenare una serie di `if` e `else if` è possibile inserire uno o pi knitr::include_graphics("images/ifnested.png") ``` -#### Struttura if {-} +#### Struttura if nested {-} ```{r, echo = TRUE, eval = FALSE} ... @@ -199,7 +199,7 @@ my_function(-5) Esegui i seguenti esercizi: - 1. Definisci una funzione per assegnare un voto in base alla percentuale di rispote corrette (*score*) segui le seguenti indicazioni: + 1. Definisci una funzione per assegnare un voto in base alla percentuale di risposte corrette (*score*) segui le seguenti indicazioni: - score < .55 insufficiente - .55 <= score < .65 - sufficiente @@ -209,10 +209,10 @@ Esegui i seguenti esercizi: 2. Definisci una funzione che determini se un numero è pari o dispari. 3. Definisci una funzione che determini se un numero è un multiplo di 3, 4, o 5. - 4. Definisci una funzione che calcoli lo stipendio mensile considerando gli straordinari che sono retribuiti 1.5 della paga oraria normale. Utilizza come parametrile ore svolte nel mese, la paga oraria ed il tetto ore lavorative, oltre cui si contano gli straordinari. + 4. Definisci una funzione che calcoli lo stipendio mensile considerando gli straordinari che sono retribuiti 1.5 della paga oraria normale. Utilizza come parametri le ore svolte nel mese, la paga oraria ed il tetto ore lavorative, oltre cui si contano gli straordinari. -## Altri Operatori Condizionali +## Altri operatori condizionali ### switch @@ -294,4 +294,4 @@ Veniamo avvertiti che `age` non è un singolo valore e che quindi solo il primo ifelse(age < 18, yes = print("Minorenne"), no = print("Maggiorenne")) ``` -In questo caso l'idea è di eseguire il codice precedente per ogni valore del nostro vettore in input. Questo è possibile perchè l'operazione `<` è vettorizzata. +In questo caso l'idea è di eseguire il codice precedente per ogni valore del nostro vettore in input. Questo è possibile perché l'operazione `<` è vettorizzata. diff --git a/17-loops.Rmd b/17-loops.Rmd index 86c4cab..2d533f6 100644 --- a/17-loops.Rmd +++ b/17-loops.Rmd @@ -1,4 +1,4 @@ -# Programmazione Iterativa {#loop} +# Programmazione iterativa {#loop} ```{r settings, echo = FALSE} knitr::opts_chunk$set( @@ -24,7 +24,7 @@ Il primo tipo di struttura iterativa viene denominata ciclo `for`. L'idea è que knitr::include_graphics("images/for_loop.png") ``` -#### Struttura For Loop {-} +#### Struttura ciclo for {-} In R la scrittura del ciclo `for` è la seguente: @@ -34,7 +34,7 @@ for (i in c(...)) { } ``` -- `i` è un nome generico per indicare la variabile conteggio che abbiamo introdotto prima. Può essere qualsiasi carattere, ma solitamente per un ciclo generico si utilizzano singole lettere come `i` o `j` proabilmente per una similarità con la notazione matematica che spesso utilizza queste lettere per indicare una serie di elementi +- `i` è un nome generico per indicare la variabile conteggio che abbiamo introdotto prima. Può essere qualsiasi carattere, ma solitamente per un ciclo generico si utilizzano singole lettere come `i` o `j` probabilmente per una similarità con la notazione matematica che spesso utilizza queste lettere per indicare una serie di elementi - `in` è l'operatore per indicare che `i` varia rispetto ai valori specificati di seguito - `c(...)` è il range di valori che assumerà `i` in per ogni iterazione @@ -89,7 +89,7 @@ for (i in seq_along(nomi)){ -:::{.trick title="seq_along() " data-latex="[Next e Break]"} +:::{.trick title="\\texttt{seq\\_along()}" data-latex="[\\texttt{seq\\_along()}]"} ```{r, echo = TRUE} my_vector <- c(93, 27, 46, 99) @@ -157,7 +157,7 @@ sum_cols sum_cols <- vector(mode = "double", length = ncol(my_matrix)) for( i in seq_along(sum_cols)){ sum_col <- sum(my_matrix[, i]) # calcolo i esima colonna - sum_cols[i] <- sum_col # aggiorno il risultato + sum_cols[i] <- sum_col # aggiorno il risultato } sum_cols @@ -171,9 +171,9 @@ Il ciclo `while` può essere considerato come una generalizzazione del ciclo `fo knitr::include_graphics("images/while_loop.png") ``` -#### Struttura While Loop {-} +#### Struttura ciclo while {-} -La scrittura è più concisa del ciclo `for` perchè non definiamo nessun counter o placeholder e nemmeno un vettore di valori. L'unica cosa che muove un ciclo `while` è una condizione logica (quindi con valori booleani `TRUE` e `FALSE`). Anche qui, parafrasando: +La scrittura è più concisa del ciclo `for` perché non definiamo nessun counter o placeholder e nemmeno un vettore di valori. L'unica cosa che muove un ciclo `while` è una condizione logica (quindi con valori booleani `TRUE` e `FALSE`). Anche qui, parafrasando: > Ripeti le operazioni incluse tra {} fino a che la condizione `` è VERA. @@ -200,8 +200,8 @@ while(count >= 0){ Quando si scrive un ciclo `while` è importante assicurarsi di due cose: -- Che la condizione sia `TRUE` inizialmente, altrimenti il ciclo non comincierà nemmeno -- Che ad un certo punto la condizione diventi `FALSE` (perchè abbiamo ottenuto il risultato o perchè è passato troppo tempo o iterazioni) +- Che la condizione sia `TRUE` inizialmente, altrimenti il ciclo non comincerà nemmeno +- Che ad un certo punto la condizione diventi `FALSE` (perché abbiamo ottenuto il risultato o perché è passato troppo tempo o iterazioni) Se la seconda condizione non è rispettata, otteniamo quelli che si chiamano `endless loop` come ad esempio: @@ -215,7 +215,7 @@ while(count >= 0){ } ``` -#### While e For +#### While e for Abbiamo introdotto in precedenza che il `for` è un tipo particolare di `while`. Concettualmente infatti possiamo pensare ad un `for` come un `while` dove il nostro counter `i` incrementa fino alla lunghezza del vettore su cui iterare. In altri termini possiamo scrivere un `for` anche in questo modo: @@ -229,9 +229,9 @@ while(i <= length(nomi)){ # condizione } ``` -### Next e Brake +### Next e break -All'interno di una struttura iterativa, possiamo eseguire qualsiasi tipo di operazione, ed anche includere strutture condizionali. Alcune volte può essere utile saltare una particolare iterazione oppure interrompere il ciclo iterativo. In R tali operazioni posso essere eseguite rispettivamene coni comandi `next` e `break`. +All'interno di una struttura iterativa, possiamo eseguire qualsiasi tipo di operazione, ed anche includere strutture condizionali. Alcune volte può essere utile saltare una particolare iterazione oppure interrompere il ciclo iterativo. In R tali operazioni posso essere eseguite rispettivamente coni comandi `next` e `break`. - `next` - passa all'iterazione successiva - `break` - interrompe l'esecuzione del ciclo @@ -264,7 +264,7 @@ while(count >= 0){ } ``` -## Nested loop +## Nested Loop Una volta compresa la struttura iterativa, è facile espanderne le potenzialità inserendo un ciclo all'interno di un altro. Possiamo avere quanti cicli *nested* necessari, chiaramente aumenta non solo la complessità ma anche il tempo di esecuzione. Per capire al meglio cosa succede all'interno di un ciclo nested è utile visualizzare gli indici: @@ -289,7 +289,7 @@ Un aspetto importante è l'utilizzo di indici diversi, infatti i valori `i`, `j` ### Esercizi {-} 1. Scrivi una funzione che calcoli la media di un vettore numerico usando un for loop. -2. Scrivi una funzione che dato un vettore numerico restituisca il valore massimo e minimo usando un for loop (attenti al valore di inizializzazione). +2. Scrivi una funzione che dato un vettore numerico restituisca il valore massimo e minimo usando un for loop (attenti al valore di inizializzazione). 3. Scrivi una funzione che per ogni iterazione generi $n$ osservazioni da una normale (funzione `rnorm()`) con media $mu$ e deviazione standard $sigma$, salva la media di ogni campione. I parametri della funzione saranno $n$, $mu$, $sigma$ e $iter$ (numero di iterazioni). ## Apply Family @@ -297,15 +297,15 @@ Un aspetto importante è l'utilizzo di indici diversi, infatti i valori `i`, `j` Ci sono una famiglia di funzioni in R estremamente potenti e versatili chiamate `*apply`. L'asterisco suggerisce una serie di varianti presenti in R che nonostante la struttura e funzione comune hanno degli obiettivi diversi: - `apply`: dato un dataframe (o matrice) esegue la stessa funzione su ogni riga o colonna -- `tapply`: dato un vettore di valori esegue la stessa funzione su ogni gruppo che è satato definito +- `tapply`: dato un vettore di valori esegue la stessa funzione su ogni gruppo che è stato definito - `lapply`: esegue la stessa funzione per ogni elemento di una lista. Restituisce ancora una lista -- `sapply`: esegue la stessa funzione per ogni elemento di una lista. Restituisce se possibile un oggetto seplificato (un vettore, una matrice o un array) +- `sapply`: esegue la stessa funzione per ogni elemento di una lista. Restituisce se possibile un oggetto semplificato (un vettore, una matrice o un array) - `vapply`: analogo a `sapply` ma richiede di definire il tipo di dati restituiti - `mapply`: è la versione multivariata. Permette di applicare una funzione a più liste di elementi Prima di illustrare le varie funzioni è utile capire la struttura generale. In generale queste funzioni accettano un oggetto **lista** quindi un insieme di elementi e una **funzione**. L'idea infatti è quella di avere una funzione che accetta altre funzioni come argomenti e applichi la funzione-argomento ad ogni elemento in input. Queste funzioni, sopratutto in R, sono spesso preferite rispetto ad utilizzare cicli `for` per velocità, compattezza e versatilità. -Hadley Wickam[^talk-map] riporta un bellissimo esempio per capire la diffenza tra `loop` e `*apply`. Immaginiamo di avere una serie di vettori e voler applicare alcune funzioni ad ogni vettore, possiamo impostare un semplice loop in questo modo: +Hadley Wickam[^talk-map] riporta un bellissimo esempio per capire la differenza tra `loop` e `*apply`. Immaginiamo di avere una serie di vettori e voler applicare alcune funzioni ad ogni vettore, possiamo impostare un semplice loop in questo modo: ```{r} list_vec <- list( @@ -329,7 +329,7 @@ for(i in seq_along(list_vec)){ Nonostante sia perfettamente corretto, questa scrittura ha diversi problemi: -- E' molto ridondante. Tra calcolare media, mediana e deviazione standard l'unica cosa che cambia è la funzione applicata mentre dobbiamo per ognuno preallocare una variabile, impostare l'indicizzazione in base all'iterazione per selezionare l'elemento della lista e memorizzare il risultato. Per migliorare questa scrittura possiamo mettere in una funzione tutta questa struttura (preallocazione, indicizzazione e memorizzazione) e utilizzare questa funzione con argomenti la lista di input e la funzione da applicare. Utilizzando la funzione `sapply`: +- È molto ridondante. Tra calcolare media, mediana e deviazione standard l'unica cosa che cambia è la funzione applicata mentre dobbiamo per ognuno preallocare una variabile, impostare l'indicizzazione in base all'iterazione per selezionare l'elemento della lista e memorizzare il risultato. Per migliorare questa scrittura possiamo mettere in una funzione tutta questa struttura (preallocazione, indicizzazione e memorizzazione) e utilizzare questa funzione con argomenti la lista di input e la funzione da applicare. Utilizzando la funzione `sapply`: ```{r} means <- lapply(list_vec, mean) @@ -350,7 +350,7 @@ Prima di descrivere nel dettaglio ogni funzione `*apply` è importante capire qu - funzioni personalizzate (create e salvate nell'ambiente principale) - funzioni **anonime** -Nell'esempio precedente, abbiamo utilizzato la funzione `mean` semplicemente scrivendo `lapply(lista, mean)`. Questo è possibile perchè `mean` necessita di un solo argomento. Se tuttavia volessimo applicare funzioni più complesse o aggiungere argomenti possiamo usare la scrittura più generale: +Nell'esempio precedente, abbiamo utilizzato la funzione `mean` semplicemente scrivendo `lapply(lista, mean)`. Questo è possibile perché `mean` necessita di un solo argomento. Se tuttavia volessimo applicare funzioni più complesse o aggiungere argomenti possiamo usare la scrittura più generale: ```{r} means <- lapply(list_vec, function(x) mean(x)) @@ -389,7 +389,7 @@ centered_list <- lapply(list_vec, function(x){ }) ``` -Un ultimo aspetto riguarda un parallismo tra `x` nei nostri esempi e `i`nei cicli `for` che abbiamo visto in precedenza. Proprio come `i`, `x` è una semplice convenzione e si può utilizzare qualsiasi nome per definire l'argomento generico. Inoltre, è utile pensare a `x` proprio con lo stesso ruolo di `i`, infatti se pensiamo alla funzione in precedenza, `x` ad ogni iterazione prende il valore di un elemento di `list_vec` proprio come utilizzare il ciclo `for` non con gli indici ma con i valori del vettore su cui stiamo iterando. Qualche volta infatti può essere utile applicare un principio di **indicizzazione** anche con l' `*apply` family: +Un ultimo aspetto riguarda un parallelismo tra `x` nei nostri esempi e `i` nei cicli `for` che abbiamo visto in precedenza. Proprio come `i`, `x` è una semplice convenzione e si può utilizzare qualsiasi nome per definire l'argomento generico. Inoltre, è utile pensare a `x` proprio con lo stesso ruolo di `i`, infatti se pensiamo alla funzione in precedenza, `x` ad ogni iterazione prende il valore di un elemento di `list_vec` proprio come utilizzare il ciclo `for` non con gli indici ma con i valori del vettore su cui stiamo iterando. Qualche volta infatti può essere utile applicare un principio di **indicizzazione** anche con l' `*apply` family: ```{r} means <- lapply(seq_along(list_vec), function(i) mean(list_vec[[i]])) @@ -473,7 +473,7 @@ tapply(my_data$y, INDEX = list(my_data$class, my_data$gender), FUN = mean) ### lapply -E' forse la funzione più utilizzata e generica. Viene applicata ad ogni tipo di dato che sia una lista di elementi o un vettore. La particolarità è quella di restituire sempre una lista come risultato, indipendentemente dal tipo di input. La scrittura è la seguente: +È forse la funzione più utilizzata e generica. Viene applicata ad ogni tipo di dato che sia una lista di elementi o un vettore. La particolarità è quella di restituire sempre una lista come risultato, indipendentemente dal tipo di input. La scrittura è la seguente: ```{r, echo = TRUE, eval = FALSE} lapply(X = , FUN = , ...) @@ -527,21 +527,21 @@ Come vedete, il risultato di queste operazioni corrisponde ad un valore per ogni ### vapply ```{r, echo = TRUE, eval = FALSE} -vapply(X = , FUN = , FUN.VALUE = ,... ) +vapply(X = , FUN = , FUN.VALUE = , ...) ``` #### Esempi {-} -`vapply` è una ancora una volta simile sia a `lapply` che a `sapply`. Tuttavia richiede che il tipo di output sia specificato in anticipo. Per questo motivo è ritenuta una versione più *solida* delle precedenti perchè permette più controllo su quello che accade. +`vapply` è una ancora una volta simile sia a `lapply` che a `sapply`. Tuttavia richiede che il tipo di output sia specificato in anticipo. Per questo motivo è ritenuta una versione più *solida* delle precedenti perché permette più controllo su quello che accade. ```{r, echo = TRUE} # Media vapply(my_list, FUN = mean, FUN.VALUE = numeric(length = 1L)) ``` -In questo caso come in precendeza definiamo la lista su cui applicare la funzione. Tuttavia l'argomento `FUN.VALUE = numeric(length = 1L)` specifica che ogni risultato dovrà essere un valore di tipo `numeric` di lunghezza 1. Infatti applicando la media otteniamo un singolo valore per iterazione e questo valore è necessariamente numerico. +In questo caso come in precedenza definiamo la lista su cui applicare la funzione. Tuttavia l'argomento `FUN.VALUE = numeric(length = 1L)` specifica che ogni risultato dovrà essere un valore di tipo `numeric` di lunghezza 1. Infatti applicando la media otteniamo un singolo valore per iterazione e questo valore è necessariamente numerico. -:::{.warning title="sapply() vs vapply()" data-latex="[sapply() vs vapply()]"} +:::{.warning title="\\texttt{sapply()} vs \\texttt{vapply()}" data-latex="[\\texttt{sapply()} vs \\texttt{vapply()}]"} `sapply()` non restituisce sempre la stessa tipologia di oggetto mentre `vapply()` richiede sia specificato il tipo di l'output di ogni iterazione. @@ -588,7 +588,7 @@ Quello che abbiamo fatto è creare una lista di funzioni e poi scrivere due `lap ### mapply -`mapply` è la versione più complessa di quelle considerate perchè estende a *n* il numero di liste che vogliamo utilizzare. La scrittura è la seguente: +`mapply` è la versione più complessa di quelle considerate perché estende a *n* il numero di liste che vogliamo utilizzare. La scrittura è la seguente: ```{r, echo = TRUE, eval = FALSE} mapply(FUN, ...) @@ -597,7 +597,7 @@ mapply(FUN, ...) Dove: - `FUN` è la funzione da applicare -- `...` sono le liste di elementi su cui applicare la funzione. E' importante che tutti gli elementi siano della stessa lunghezza +- `...` sono le liste di elementi su cui applicare la funzione. È importante che tutti gli elementi siano della stessa lunghezza Proviamo a generare dei vettori da una distribuzione normale, usando la funzione `rnorm()` con diversi valori di numerosità, media e deviazione standard. @@ -661,7 +661,7 @@ str(sample_info) head(sample_info) ``` -E' importante sottolineare che la ripetizione è alla base di qualsiasi struttura iterativa che abbiamo visto finora. Infatti lo stesso risultato (al netto di leggibilità, velocità e versalità) lo possiamo ottenere indistintamente con un ciclo `for`, `lapply` o `replicate`. Riprendendo l'esempio precedente: +È importante sottolineare che la ripetizione è alla base di qualsiasi struttura iterativa che abbiamo visto finora. Infatti lo stesso risultato (al netto di leggibilità, velocità e versatilità) lo possiamo ottenere indistintamente con un ciclo `for`, `lapply` o `replicate`. Riprendendo l'esempio precedente: ```{r} diff --git a/18-introduction-case-study.Rmd b/18-introduction-case-study.Rmd index df4baa1..43173f2 100644 --- a/18-introduction-case-study.Rmd +++ b/18-introduction-case-study.Rmd @@ -2,4 +2,5 @@ # Introduzione {-} + Working in progress. diff --git a/19-case-study-I.Rmd b/19-case-study-I.Rmd index 7175d73..00a4762 100644 --- a/19-case-study-I.Rmd +++ b/19-case-study-I.Rmd @@ -1,5 +1,6 @@ -# Caso Studio I: Attaccamento {#attachment} +# Caso studio I: Attaccamento {#attachment} + Working in progress. [Script Analisi](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-15-case-study-I.R) diff --git a/21-stringhe.Rmd b/21-stringhe.Rmd index 77aaea7..03b7788 100644 --- a/21-stringhe.Rmd +++ b/21-stringhe.Rmd @@ -17,7 +17,7 @@ Abbiamo visto che R oltre ai numeri è in grado di gestire anche i **caratteri** ``` - possono avere caratteri speciali come `?\$` oppure appartenere ad alfabeti diversi `ة α` -- l'indicizzazione per `numeri` e `stringhe` lavora in modo diverso. Se abbiamo un **vettore** di strighe, questo viene rappresentato allo stesso modo di un vettore numerico. Tuttavia la stringa stessa `ciao` può essere scomposta, manipolata e quindi indicizzata nei singoli caratteri che la compongono `c, i, a, o`: +- l'indicizzazione per `numeri` e `stringhe` lavora in modo diverso. Se abbiamo un **vettore** di stringhe, questo viene rappresentato allo stesso modo di un vettore numerico. Tuttavia la stringa stessa `ciao` può essere scomposta, manipolata e quindi indicizzata nei singoli caratteri che la compongono `c, i, a, o`: ```{r} vec_string <- c("ciao", "come", "stai") @@ -40,10 +40,10 @@ x <- "stringa con all'interno un'altra 'stringa'" x x <- "stringa con all'interno un'altra "stringa"" -# in questo caso abbaimo errore perchè non interpreta la doppia virgolettatura +# in questo caso abbiamo errore perché non interpreta la doppia virgolettatura ``` -All'interno delle stringhe possiamo utilizzare caratteri speciali come `/|\$%&`. Alcuni di questi vengono intepretati da R in modo particolare. Quando accade è necessario aggiungere il carattere `\` che funge da *escape*, ovvero dice ad R di trattare letterlamente quel carattere: +All'interno delle stringhe possiamo utilizzare caratteri speciali come `/|\$%&`. Alcuni di questi vengono interpretati da R in modo particolare. Quando accade è necessario aggiungere il carattere `\` che funge da *escape*, ovvero dice ad R di trattare letteralmente quel carattere: ```{r} x <- "ciao come stai? n io tutto bene" @@ -71,7 +71,7 @@ intero == double "female" == "feMale" ``` -Anche il concetto di spazio ` ` è rilevante perchè viene considerato come un carattere: +Anche il concetto di spazio ` ` è rilevante perché viene considerato come un carattere: ```{r} "ciao " == "ciao" @@ -83,7 +83,7 @@ Immaginate di avere un vettore dove una colonna rappresenta il genere dei partec genere <- c("maLe", "masChio", "Male", "f", "female", "malew") ``` -In questo vettore (volutamente esagerato) abbiamo chiaro il significato di `f` o di `malew` (probabilmente un errore di battitura) tuttavia se vogliamo lavorarci con R, diventa probelmatico: +In questo vettore (volutamente esagerato) abbiamo chiaro il significato di `f` o di `malew` (probabilmente un errore di battitura) tuttavia se vogliamo lavorarci con R, diventa problematico: ```{r} # Tabella di frequenza @@ -99,7 +99,7 @@ Vediamo quindi alcune funzioni utili per lavorare con le stringhe. ### `tolower()` e `toupper()` -Queste funzioni sono estremamente utili perchè permettono di forzare il carattere maiscolo o minuscolo +Queste funzioni sono estremamente utili perché permettono di forzare il carattere maiuscolo o minuscolo ```{r} tolower(genere) @@ -123,7 +123,7 @@ In questo caso nonostante `age` sia numerico, viene forzato a stringa per poter ### `sprinf()` -`sprinf()` è simile a `paste*()` come funzionamento ma permette di comporre strighe usando dei *placeholder* e fornendo poi il contenuto. +`sprinf()` è simile a `paste*()` come funzionamento ma permette di comporre stringhe usando dei *placeholder* e fornendo poi il contenuto. ```{r} sprintf("%s ha %d anni", nomi, age) @@ -151,7 +151,7 @@ gregexpr("t", "gatto") regexpr("t", "gatto") ``` -La differenza è che `regexpr()` restituisce solo la prima corrispondenza, nel nostro esempio la prima `t` si trova in 3 posizione mentre `gregexpr()` resituisce tutte le corrispondenze. +La differenza è che `regexpr()` restituisce solo la prima corrispondenza, nel nostro esempio la prima `t` si trova in 3 posizione mentre `gregexpr()` restituisce tutte le corrispondenze. ### `substr()` e `substring()` @@ -176,7 +176,7 @@ substring("gatto", 1:5, 1:5) # indice multiplo di inizio e fine substr("gatto", 1, 1:5) # non funziona, viene usato solo 1 indice di fine ``` -### `startWith()` e `endsWith()` +### `startsWith()` e `endsWith()` Alcune volte possiamo essere interessati all'inizio o alla fine di una stringa. Ad esempio `female` e `male` hanno una chiara differenza iniziale (`fe` e `ma`). E nonostante errori di battitura seguenti o altre differenze, selezionare solo l'inizio o la fine può essere efficiente. `startWith()` e `endsWith()` permettono rispettivamente di fornire `TRUE` o `FALSE` se una certa stringa o vettore di stringhe abbiamo un certo pattern iniziale o finale. @@ -185,7 +185,7 @@ startsWith("female", prefix = "fe") endsWith("female", suffix = "ale") ``` -Questa come le altre funzioni possono essere utilizzate in combinazione con `tolower()` o `toupper()` per ingnorare differenze non rilevanti. +Questa come le altre funzioni possono essere utilizzate in combinazione con `tolower()` o `toupper()` per ignorare differenze non rilevanti. ### `grep()` e `grepl()` @@ -207,7 +207,7 @@ genere[index_grep] genere[index_grepl] ``` -Da notare ancora come tutte queste funzioni lavorino su una **corrispondenza molto stringente** (in termini di maiscolo, minuscolo, etc.) tra pattern e target. +Da notare ancora come tutte queste funzioni lavorino su una **corrispondenza molto stringente** (in termini di maiuscolo, minuscolo, etc.) tra pattern e target. ## Manipolare stringhe @@ -283,7 +283,7 @@ Quello che otteniamo è un vettore (all'interno di una lista, possiamo usare `un ## Regular Expression (REGEX) -E' tutto così semplice con le stringhe? Assolutamente no! Fino ad ora abbiamo utilizzato dei semplici pattern come singoli caratteri o insieme di caratteri tuttavia possiamo avere problemi più complessi da affrontare come: +È tutto così semplice con le stringhe? Assolutamente no! Fino ad ora abbiamo utilizzato dei semplici pattern come singoli caratteri o insieme di caratteri tuttavia possiamo avere problemi più complessi da affrontare come: - trovare l'estensione di un insieme di file - trovare il dominio di un sito web @@ -311,11 +311,11 @@ Finora abbiamo visto 2 livelli di astrazione: Il terzo livello di astrazione è quello di trovare dei pattern comuni nelle stringhe ed estrarli, indipendentemente dai singoli caratteri, dal numero o dalla posizione. -Le Regular Expressions (REGEX) sono un insieme di caratteri (chiamati **metacaratteri**) che vengono intepretati e permettono di trovare dei pattern nelle stringhe senza indicare un pattern specifico o un indice di posizione. L'argomento è molto complesso e non R-specifico. Ci sono parecchie guide online e tutorial che segnaliamo alla fine del capitolo. La cosa importante da sapere è che la maggior parte delle funzioni che abbiamo visto permettono di usare una `regex` oltre ad un pattern specifico in modo da risolvere problemi più complessi. +Le Regular Expressions (REGEX) sono un insieme di caratteri (chiamati **metacaratteri**) che vengono interpretati e permettono di trovare dei pattern nelle stringhe senza indicare un pattern specifico o un indice di posizione. L'argomento è molto complesso e non R-specifico. Ci sono parecchie guide online e tutorial che segnaliamo alla fine del capitolo. La cosa importante da sapere è che la maggior parte delle funzioni che abbiamo visto permettono di usare una `regex` oltre ad un pattern specifico in modo da risolvere problemi più complessi. Per fare un esempio se vogliamo estrarre l'estensione da una lista di file il ragionamento è: -- dobbiamo trovare un `.` perchè (circa) tutti i file sono composti da `nomefile.estensione` +- dobbiamo trovare un `.` perché (circa) tutti i file sono composti da `nomefile.estensione` - dobbiamo selezionare tutti i caratteri dal punto alla fine della stringa La "traduzione" in termini di REGEX è questa `"\\.([^.]+)$"` e quindi possiamo usare questo come *pattern* e quindi estrarre le informazioni che ci servono. Possiamo usare la funzione `regmatches(text, match)` che richiede la stringa da analizzare e un oggetto `match` che è il risultato della funzione `regexpr` che abbiamo già visto: @@ -327,7 +327,7 @@ regmatches(files, match_regex) ## Per approfondire -In tutto questo libro abbiamo sempre cercato di affrontare R come linguaggio di programmazione concentrandosi sulle funzioni di base. Tuttavia in alcuni settori, come quello delle stringhe e delle REGEX ci sono dei pacchetti esterni altamente consigliati che non solo rendono più semplice ma anche più organizzato e consistente l'insieme di funzioni. Il pacchetto [`stringr`](https://stringr.tidyverse.org/index.html) è una fantastica risorsa per imparare ma anche lavorare in modo più efficiace con le stringhe. Contiene una serie di funzioni costruite al di sopra di quelle che abbiamo affrontato, semplificandole e uniformando il tutto. +In tutto questo libro abbiamo sempre cercato di affrontare R come linguaggio di programmazione concentrandosi sulle funzioni di base. Tuttavia in alcuni settori, come quello delle stringhe e delle REGEX ci sono dei pacchetti esterni altamente consigliati che non solo rendono più semplice ma anche più organizzato e consistente l'insieme di funzioni. Il pacchetto [`stringr`](https://stringr.tidyverse.org/index.html) è una fantastica risorsa per imparare ma anche lavorare in modo più efficace con le stringhe. Contiene una serie di funzioni costruite al di sopra di quelle che abbiamo affrontato, semplificandole e uniformando il tutto. L'ultimo esempio descritto non è molto leggibile contenendo il risultato di un'altra funzione e chiamando l'oggetto `target` due volte, in `stringr` abbiamo la funzione `str_extract()` che estrae un certo pattern o REGEX: diff --git a/exercises/chapter-03-first-comands.R b/exercises/chapter-03-first-commands.R similarity index 100% rename from exercises/chapter-03-first-comands.R rename to exercises/chapter-03-first-commands.R diff --git a/index.Rmd b/index.Rmd index 926d43c..60ac74a 100755 --- a/index.Rmd +++ b/index.Rmd @@ -2,7 +2,7 @@ title: "Introduction to R" subtitle: "Corso per imparare le basi di **R**" author: "[Claudio Zandonella Callegher](https://claudiozandonella.netlify.app/) and [Filippo Gambarota](https://filippogambarota.netlify.app/) members of [Psicostat](https://psicostat.dpss.psy.unipd.it/)" -date: "`r format(Sys.Date(), format = '%d-%m-%Y')`" +date: "`r format(Sys.Date(), format = '%d-%m-%Y')`" site: bookdown::bookdown_site documentclass: book bibliography: [book.bib, packages.bib] @@ -29,30 +29,30 @@ knitr::opts_chunk$set( In questo libro impareremo le basi di *R*, uno dei migliori software per la visualizzazione e l'analisi statistica dei dati. Partiremo da zero intorducendo gli aspetti fondamentili di R e i concetti alla base di ogni linguaggio di programmazione che ti pemetteranno in seguito di approfondire e sviluppare le tue abilità in questo bellissimo mondo. -## Perchè R {-} +## Perché R {-} -Ci sono molte ragioni per cui scegliere R rispetto ad altri programmi usati per condurre le analisi statistiche. Innanzitutto è un linguaggio di programmazione (come ad esempio Python, Java, C++, o Julia) e non semplicemente un'interfaccia punta e clicca (come ad esempio SPSS o JASP). Questo comporta si maggiori difficoltà iniziali ma ti ricompenserà in futuro poichè avari imparato ad utilizza uno strumennto molto potente. +Ci sono molte ragioni per cui scegliere R rispetto ad altri programmi usati per condurre le analisi statistiche. Innanzitutto è un linguaggio di programmazione (come ad esempio Python, Java, C++ o Julia) e non semplicemente un'interfaccia punta e clicca (come ad esempio SPSS o JASP). Questo comporta sì maggiori difficoltà iniziali, ma ti ricompenserà in futuro poiché avari imparato a utilizzare uno strumento molto potente. Inoltre, R è: -- nato per la statistica -- open-source -- ricco di pacchetti -- supportato da una grande community -- gratis +- nato per la statistica, +- open-source, +- ricco di pacchetti, +- supportato da una grande community, +- gratis. ## Struttura del libro {-} Il libro è suddiviso in quattro sezioni principali: -- **Get started**. Una volta installato R ed RStudio, famiglierizzeremo con l'ambiente di lavoro introducendo alcuni aspetti generali e le funzioni principali. Verranno inoltre descritte alcune buone regole per iniziare una sessione di lavoro in R. +- **Get started**. Una volta installato R ed RStudio, familiarizzeremo con l'ambiente di lavoro introducendo alcuni aspetti generali e le funzioni principali. Verranno inoltre descritte alcune buone regole per iniziare una sessione di lavoro in R. - **Struttura dei dati**. Impareremo gli oggetti principali che R utilizza al suo interno. Variabili, vettori, matrici, dataframe e liste non avranno più segreti e capiremo come manipolarli e utlizzarli a seconda delle varie necessità. - **Algoritmi**. Non farti spaventare da questo nome. Ne avrai spesso sentito parlarne come qualcosa di molto complicato, ma in realtà gli algoritmi sono semplicemente una serie di istruzioni che il computer segue quando deve eseguire un determinato compito. In questa sezione vedremo i principali comandi di R usati per definire degli algoritmi. Questo è il vantaggio di conoscere un linguaggio di programmazione, ci permette di creare nuovi programmi che il computer eseguirà per noi. -- **Case study**. Eseguiremo passo per passo un analisi che ci permetterà di imparare come importare i dati, codificare le variabili, manipolare e preprare i dati perle analisi, condurre delle analisi descrittive e creare dei grafici. +- **Case study**. Eseguiremo passo dopo passo un'analisi che ci permetterà di imparare come importare i dati, codificare le variabili, manipolare e preprare i dati per le analisi, condurre delle analisi descrittive e creare dei grafici. Alla fine di questo libro probabilmente non sarete assunti da Google, ma speriamo almeno che R non vi faccia più così paura e che magari a qualcuno sia nato l'interesse di approfondire questo fantastico mondo fatto di linee di codice. -## Risorse Utili {-} +## Risorse utili {-} Segnaliamo qui per il lettore interessato del materiale online (in inglese) per approfondire le conoscenze sull'uso di R. @@ -72,16 +72,16 @@ Materiale avanzato: ## Psicostat {-} -Questo libro è stato prodotto da [Claudio Zandonella Callegher](https://claudiozandonella.netlify.app/) and [Filippo Gambarota](https://filippogambarota.netlify.app/), membri di **Psicostat**. Un gruppo di ricerca interdisciplinare dell'universita di Padova che unisce la passione per la statistica e la psicologia. Se vuoi conoscere di più riguardo le nostre attività visita il nosto sito https://psicostat.dpss.psy.unipd.it/ o aggiungiti alla nostra mailing list https://lists.dpss.psy.unipd.it/postorius/lists/psicostat.lists.dpss.psy.unipd.it/. +Questo libro è stato prodotto da [Claudio Zandonella Callegher](https://claudiozandonella.netlify.app/) and [Filippo Gambarota](https://filippogambarota.netlify.app/), membri di **Psicostat**, un gruppo di ricerca interdisciplinare dell'università di Padova che unisce la passione per la statistica e la psicologia. Se vuoi conoscere di più riguardo le nostre attività visita il nosto sito https://psicostat.dpss.psy.unipd.it/ o aggiungiti alla nostra mailing list https://lists.dpss.psy.unipd.it/postorius/lists/psicostat.lists.dpss.psy.unipd.it/. ## Collaborazione {-} -Se vuoi collaborare alla revione e scrittura di questo libro (ovviamente è tutto in R) visita la nostra repository di Github https://github.com/psicostat/Introduction2R. +Se vuoi collaborare alla revione e scrittura di questo libro (ovviamente è tutto in R) visita la nostra repository di GitHub https://github.com/psicostat/Introduction2R. ## Riconoscimenti {-} -Il template di questo libro è basato su [Rstudio Bookdown-demo](https://github.com/rstudio/bookdown-demo) rilasciato con licenza [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/) e [rstudio4edu-book](https://rstudio4edu.github.io/rstudio4edu-book/) rilasciato con licenza [CC BY](https://creativecommons.org/licenses/by/2.0/). Nota che le illustrazioni utilizzate nelle vignette appartengono sempre a [rstudio4edu-book](https://rstudio4edu.github.io/rstudio4edu-book/) e sono rilasciate con licenza [CC BY-NC](https://creativecommons.org/licenses/by-nc/2.0/). +Il template di questo libro è basato su [RStudio Bookdown-demo](https://github.com/rstudio/bookdown-demo) rilasciato con licenza [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/) e [rstudio4edu-book](https://rstudio4edu.github.io/rstudio4edu-book/) rilasciato con licenza [CC BY](https://creativecommons.org/licenses/by/2.0/). Nota che le illustrazioni utilizzate nelle vignette appartengono sempre a [rstudio4edu-book](https://rstudio4edu.github.io/rstudio4edu-book/) e sono rilasciate con licenza [CC BY-NC](https://creativecommons.org/licenses/by-nc/2.0/). ## Licenza {-} diff --git a/preamble.tex b/preamble.tex index 17ea72d..4f72e94 100755 --- a/preamble.tex +++ b/preamble.tex @@ -39,57 +39,59 @@ % tip \newenvironment{tip}[1][Title] - { +{ \setlength{\fboxsep}{1em} \begin{mybox}[tip-line] - \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/lightbulb.png}} \large \textcolor{tip-text}{Tip-Box: #1}\\ - } - { + \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/lightbulb.png}} \large \textcolor{tip-text}{Suggerimento: #1}\\ +} +{ \end{mybox} - } +} % warning \newenvironment{warning}[1][Title] - { +{ \setlength{\fboxsep}{1em} \begin{mybox}[warning-line] - \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/gotcha.png}} \large \textcolor{warning-text}{Warning-Box: #1}\\ - } - { + \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/gotcha.png}} \large \textcolor{warning-text}{Avvertimento: #1}\\ +} +{ \end{mybox} - } +} % deffun \newenvironment{deffun}[1][Title] - { +{ \setlength{\fboxsep}{1em} \begin{mybox}[deffun-line] - \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/gears.png}} \large \textcolor{deffun-text}{Definition-Box: #1}\\ - } - { + \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/gears.png}} \large \textcolor{deffun-text}{Definizione: #1}\\ +} +{ \end{mybox} - } +} % design \newenvironment{design}[1][Title] - { +{ \setlength{\fboxsep}{1em} \begin{mybox}[design-line] - \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/design.png}} \large \textcolor{design-text}{Approfondimento: #1}\\ - } - { + \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/design.png}} \large \textcolor{design-text}{Approfondimento: #1}\\ +} +{ \end{mybox} - } +} % trick \newenvironment{trick}[1][Title] - { +{ \setlength{\fboxsep}{1em} \begin{mybox}[trick-line] - \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/hat.png}} \large \textcolor{trick-text}{Trick-Box: #1}\\ - } - { + \raisebox{-.2\height}{\includegraphics[height=.6cm]{images/hat.png}} \large \textcolor{trick-text}{Trucco: #1}\\ +} +{ \end{mybox} - } - +} +% rinomina tabelle e figure +\renewcommand{\figurename}{Figura} +\renewcommand{\tablename}{Tabella}