1. ANALISI DELLE VARIABILI

Analizzo le variabili presenti nel dataset Real Texas Estate.csv
L’obiettivo è identificare il tipo di ciascuna variabile, descriverne la natura statistica e commentare sul tipo di analisi applicabile.

Caricamento del dataset

# Carico il dataset
dati <- read.csv("realestate_texas.csv")
#View(realestate_texas) # visuallizzo il dataset per intero
# Visualizzo le prime 5 righe per capire la struttura
head(dati,5)
##       city year month sales volume median_price listings months_inventory
## 1 Beaumont 2010     1    83 14.162       163800     1533              9.5
## 2 Beaumont 2010     2   108 17.690       138200     1586             10.0
## 3 Beaumont 2010     3   182 28.701       122400     1689             10.6
## 4 Beaumont 2010     4   200 26.819       123200     1708             10.6
## 5 Beaumont 2010     5   202 28.833       123100     1771             10.9

Il data set contiene: 240 osservazioni di 8 variabili.

str(dati) #mostro la struttura dei dati
## 'data.frame':    240 obs. of  8 variables:
##  $ city            : chr  "Beaumont" "Beaumont" "Beaumont" "Beaumont" ...
##  $ year            : int  2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
##  $ month           : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ sales           : int  83 108 182 200 202 189 164 174 124 150 ...
##  $ volume          : num  14.2 17.7 28.7 26.8 28.8 ...
##  $ median_price    : num  163800 138200 122400 123200 123100 ...
##  $ listings        : int  1533 1586 1689 1708 1771 1803 1857 1830 1829 1779 ...
##  $ months_inventory: num  9.5 10 10.6 10.6 10.9 11.1 11.7 11.6 11.7 11.5 ...
dim(dati) #mostro la dimensione del dataset n.righe e n.colonne
## [1] 240   8

Nella seguente tabella sono riportate le variabili presenti nel dataset, la loro tipologia statistica e il tipo di analisi che si può eseguire.

  • Le variabili quantitative discrete (temporali) year e month rappresentano la dimensione temporale del dataset. Si potrebbe calcolare la media, la moda o la mediana ma sono poco indicative. Queste variabili servono più per costruire le serie storiche e vedere come variano nel tempo le altre variabili quantitative (es. come varia il prezzo durante gli ultimi 5 anni). Quindi, si possono eseguire analisi di tipo time series (per es. trend delle vendite, variazioni di prezzo nel tempo). Le altre variabili quantitative (sales, volume, median_price….) si possono usare per fare delle analisi descrittive e relazionali. La variabile qualitativa city consente confronti tra gruppi.

Visualizzare la tabella per una descrizione più dettagliata e sintetica

Variabile CITY: (città di riferimento)

Eseguirò le frequenze assolute e relative per generare le tabelle di contingenza. Essendo una variabile categorica non ha senso calcolare media, mediana. Valuterò con la moda qual è la città che ha più osservazioni nel database.

Variabili YEAR e MONTHS:
le userò come time series per vedere come si comportano le altre variabili nel tempo

VARIABILI: SALES , VOLUME e MEDIAN_PRICE :
Valuterò tutti gli indici di posizione. Controllerò il numero totale di vendite per ogni anno, la media, la vendità maggiore/minore, si potrà controllare con l’utilizzo di city anche dove è stata registrata la vendita maggiore e minore e il numero di più alto di vendite. Valutare l’utilizzo di media geometrica.

VARIABILI: LISTING E MONTHS_INVENTORY:
Valuterò gli indici di posizione per identidicare le zone dove ci sono più annunci attivi ( percentuali, frequenze). Si può effettuare un calcolo di probabilità per verificare qual è la probabilità che per una x città tutte le inserzioni vengano vendute nell’arco di x mesi.

#dataframe con nomi e tipi di variabili
tabella_var <- data.frame(
  Variabile = c("city", "year", "month", "sales", "volume", 
                "median_price", "listings", "months_inventory"),
  
  Tipo = c("Qualitativa nominale (categorica)", 
           "Quantitativa discreta (temporale)", 
           "Quantitativa discreta (temporale)",
           "Quantitativa discreta",
           "Quantitativa continua",
           "Quantitativa continua",
           "Quantitativa discreta",
           "Quantitativa continua"),
  
  Indici_posizione = c("Moda","Media, Mediana, Moda,(pocointerpretabili)","Media, Mediana, Moda (poco interpretabili)","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda"),
  
  Indici_dispersione = c("Frequenze, percentuali",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range"),
  
  Analisi = c("Grafici a barre, tabelle di contingenza","Analisi temporali, trend, serie storiche","Analisi temporali, trend, serie storiche",
"Analisi descrittive, regressione, correlazione","Analisi descrittive, regressione, correlazione","Analisi temporali, regressione, trend di prezzo","Analisi descrittive, correlazione con sales","Analisi temporali, equilibrio domanda/offerta"))

#mostro la tabella
knitr::kable(tabella_var, caption = "Tabella 1: Tipologia, indici e analisi per ciascuna variabile")
Tabella 1: Tipologia, indici e analisi per ciascuna variabile
Variabile Tipo Indici_posizione Indici_dispersione Analisi
city Qualitativa nominale (categorica) Moda Frequenze, percentuali Grafici a barre, tabelle di contingenza
year Quantitativa discreta (temporale) Media, Mediana, Moda,(pocointerpretabili) Varianza, Deviazione standard, Range Analisi temporali, trend, serie storiche
month Quantitativa discreta (temporale) Media, Mediana, Moda (poco interpretabili) Varianza, Deviazione standard, Range Analisi temporali, trend, serie storiche
sales Quantitativa discreta Media, Mediana, Moda Varianza, Deviazione standard, Range Analisi descrittive, regressione, correlazione
volume Quantitativa continua Media, Mediana, Moda Varianza, Deviazione standard, Range Analisi descrittive, regressione, correlazione
median_price Quantitativa continua Media, Mediana, Moda Varianza, Deviazione standard, Range Analisi temporali, regressione, trend di prezzo
listings Quantitativa discreta Media, Mediana, Moda Varianza, Deviazione standard, Range Analisi descrittive, correlazione con sales
months_inventory Quantitativa continua Media, Mediana, Moda Varianza, Deviazione standard, Range Analisi temporali, equilibrio domanda/offerta

2 INDICI DI POSIZIONE, VARIABILITA’ E FORMA

Calcola Indici di posizione, variabilità e forma per tutte le variabili per le quali ha senso farlo, per le altre crea una distribuzione di frequenza. Infine, commenta tutto brevemente.

GLI INDICI DI POSIZIONE VERRANNO CALCOLATI PER LE VARIABILI :
SALES, VOLUME , MEDIAN_PRICE, LISTING, MONTHS_INVENTORY

LA VARIABILITA’ VERRA’ CALCOLATA PER LE VARIABILI:
SALES, VOLUME, MEDIAN_PRICE, LISTING, MONTHS_INVENTORY E CITY

ANALIZZERO’ LA FORMA DI DISTRIBUZIONE DELLE VARIABILI:
SALES, VOLUME, MEDIAN_PRICE, LISTING E MONTHS_INVENTORY

La forma di distribuzione ha senso svolgerla per variabili quantitative (discrete o continue).

LA DISTRIBUZIONE DI FREQUENZA VERRA’ FATTA PER LE VARIABILI:
CITY, YEAR. MONTHS.

  1. CITY
#preparo il dataset
attach(dati) # uso attach per poter estrarre più facilimente le colonne di riferimento e richiamare le mie variabili
table(city) 
## city
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60
N<-dim(dati)[1] #corrisponde al n.di osservazioni 240

#distribuzione di frequenze
table(dati["city"]) # oppure table(city) visto che ho usato attach
## city
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60
freq_ass_city<-table(dati$city) 
freq_rel_city<-table(city)/N 
freq_ass_city
## 
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60
freq_rel_city #per mostrare le tab di contingenza
## city
##              Beaumont Bryan-College Station                 Tyler 
##                  0.25                  0.25                  0.25 
##         Wichita Falls 
##                  0.25
#per combiare freq ass e freq rel uso cbind

distr_freq_city<-cbind(freq_ass_city,freq_rel_city)
distr_freq_city
##                       freq_ass_city freq_rel_city
## Beaumont                         60          0.25
## Bryan-College Station            60          0.25
## Tyler                            60          0.25
## Wichita Falls                    60          0.25
#trasformo il tutto in dataframe per migliore visibilità

distr_freq_city<-as.data.frame(cbind(freq_ass_city,freq_rel_city))

#Indice di Gini: non esiste una funzione specifica. quindi creo la mia funzione 

gini_index_city <- function(city){
  ni=freq_ass_city
  fi=freq_rel_city
  fi2=freq_rel_city^2
  J=length(table(city))
  gini=1-sum(fi2)
  gini.norm=gini/((J-1)/J)

return(gini.norm)
}

gini_index_city(city)
## [1] 1
  1. YEAR AND MONTHS
attach(dati)
## The following objects are masked from dati (pos = 3):
## 
##     city, listings, median_price, month, months_inventory, sales,
##     volume, year
#Numero totale osservazioni 
N<-dim(dati)[1] 
table(year)
## year
## 2010 2011 2012 2013 2014 
##   48   48   48   48   48
table(month)
## month
##  1  2  3  4  5  6  7  8  9 10 11 12 
## 20 20 20 20 20 20 20 20 20 20 20 20
#freq assolute
ni_year<-table(year) 
ni_month<-table(month) 
#freq relative 
fi_year<-table(year)/N 
fi_month<-table(month)/N 

#data frame 

distr_year<-as.data.frame(cbind(ni_year,fi_year))
distr_month<-as.data.frame(cbind(ni_month,fi_month))

print(distr_year)
##      ni_year fi_year
## 2010      48     0.2
## 2011      48     0.2
## 2012      48     0.2
## 2013      48     0.2
## 2014      48     0.2
print(distr_month)
##    ni_month   fi_month
## 1        20 0.08333333
## 2        20 0.08333333
## 3        20 0.08333333
## 4        20 0.08333333
## 5        20 0.08333333
## 6        20 0.08333333
## 7        20 0.08333333
## 8        20 0.08333333
## 9        20 0.08333333
## 10       20 0.08333333
## 11       20 0.08333333
## 12       20 0.08333333
View(distr_month)
View(distr_year)
# Frequenze assolute e relative
distr_year <- data.frame(
  Year = names(ni_year),
  ni_year = as.numeric(ni_year),
  fi_year = round(as.numeric(fi_year), 3)
)

distr_month <- data.frame(
  Month = names(ni_month),
  ni_month = as.numeric(ni_month),
  fi_month = round(as.numeric(fi_month), 3)
)

# Visualizzazione in RMarkdown
library(knitr)
kable(distr_year, caption = "Distribuzione frequenze per Year")
Distribuzione frequenze per Year
Year ni_year fi_year
2010 48 0.2
2011 48 0.2
2012 48 0.2
2013 48 0.2
2014 48 0.2
kable(distr_month, caption = "Distribuzione frequenze per Month")
Distribuzione frequenze per Month
Month ni_month fi_month
1 20 0.083
2 20 0.083
3 20 0.083
4 20 0.083
5 20 0.083
6 20 0.083
7 20 0.083
8 20 0.083
9 20 0.083
10 20 0.083
11 20 0.083
12 20 0.083
  1. VARIABILE SALES

Sales è una variabile quantitativa discreta.
DISTRIBUZIONE DI FREQUENZE:

INDICI DI POSIZIONE E VARIABILITA’

FORMA DELLA DISTRIBUZIONE:

##### DISTRIBUZIONE DI FREQUENZA #####
mu_sales <- mean(dati$Sales, na.rm = TRUE)
## Warning in mean.default(dati$Sales, na.rm = TRUE): argument is not numeric or
## logical: returning NA
media_sales <- mean(dati$Sales, na.rm = TRUE)
## Warning in mean.default(dati$Sales, na.rm = TRUE): argument is not numeric or
## logical: returning NA
sd_sales <- sd(dati$Sales, na.rm = TRUE)

contingenza_tab <- function(sales, nclass = 5) { #divisione in n.5 classi
  
  # Creazione delle classi
  classi_sales <- cut(sales, breaks = nclass, include.lowest = TRUE)
  
  # Frequenze
  ni <- table(classi_sales)
  fi <- ni / length(sales)
  
  # Frequenze cumulate
  Ni <- cumsum(ni)
  Fi <- cumsum(fi)
  
  # Tabella finale
  tab_sales <- data.frame(
    Sales_num_tot = names(ni), # diviso in classe in base al n.tot vendite
    Frequenza = as.numeric(ni),
    Frequenza_relativa = round(as.numeric(fi), 3),
    Frequenza_cumulata = Ni,
    Frequenza_rel_cumulata = round(Fi, 3)
  )
  
  return(tab_sales)
}

# Esempio di uso:
contingenza_tab(sales)
##            Sales_num_tot Frequenza Frequenza_relativa Frequenza_cumulata
## [78.7,148]    [78.7,148]        84              0.350                 84
## (148,217]      (148,217]        77              0.321                161
## (217,285]      (217,285]        41              0.171                202
## (285,354]      (285,354]        27              0.112                229
## (354,423]      (354,423]        11              0.046                240
##            Frequenza_rel_cumulata
## [78.7,148]                  0.350
## (148,217]                   0.671
## (217,285]                   0.842
## (285,354]                   0.954
## (354,423]                   1.000
View(contingenza_tab(sales))
#in Rmarkdown
library(knitr)
kable(contingenza_tab(sales), caption = "Distribuzione frequenze per Sales")
Distribuzione frequenze per Sales
Sales_num_tot Frequenza Frequenza_relativa Frequenza_cumulata Frequenza_rel_cumulata
[78.7,148] [78.7,148] 84 0.350 84 0.350
(148,217] (148,217] 77 0.321 161 0.671
(217,285] (217,285] 41 0.171 202 0.842
(285,354] (285,354] 27 0.112 229 0.954
(354,423] (354,423] 11 0.046 240 1.000
#BARPLOT

# Barplot delle frequenze relative
barplot(contingenza_tab(sales)$Frequenza_relativa,
        names.arg = contingenza_tab(sales)$Sales_num_tot,
        main = "Distribuzione delle vendite (Sales)",
        xlab = "N totale vendite divisi in classi",
        ylab = "Frequenze relative ",
        col = "lightgreen",
        las = 2)  # ruota le etichette verticalmente

############ INDICI DI POSIZIONE E VARIABILITA' ############

# Funzione per calcolare la moda
moda_sales <- function(sales) {
  moda <- names(table(sales))[which.max(table(sales))]
  return(as.numeric(moda))
}

# Funzione principale per gli indici di posizione
pos_index_sales <- function(sales) {
  
  # Calcoli principali
  mu_sales <- mean(sales)            # media
  me_sales <- median(sales)           # mediana
  mo_sales <- moda_sales(sales)       # moda usando la funzione creata
  quant_sales <- quantile(sales)      # quantili (0%, 25%, 50%, 75%, 100%)
  
  # Tabella finale
  tab_pos_sales <- data.frame( 
    Media = mu_sales,
    Mediana = me_sales,
    Moda = mo_sales,
    Min = quant_sales[1],
    Q1 = quant_sales[2],
    Q2 = quant_sales[3],
    Q3 = quant_sales[4],
    Max = quant_sales[5]
  )
  
  return(tab_pos_sales)
}

# Esempio di uso:
View(pos_index_sales(sales))
pos_index_sales(sales)
##       Media Mediana Moda Min  Q1    Q2  Q3 Max
## 0% 192.2917   175.5  124  79 127 175.5 247 423
library(knitr)
kable(pos_index_sales(sales), caption = "Indici di posizione per variabile Sales") 
Indici di posizione per variabile Sales
Media Mediana Moda Min Q1 Q2 Q3 Max
0% 192.2917 175.5 124 79 127 175.5 247 423
######## VARIABILITA'########
#pacchetti utili
#install.packages("dplyr")
#library(dplyr)
range(sales)
## [1]  79 423
IQR(sales)
## [1] 120
mu_sales
## [1] NA
#creo la funzione per calcolare il coefficiente di variazione
cv<- function(x){
  return(sd(x)/mean(x)*100)
}
cv_sales<-cv(sales) # la ds di questa variabile è circa al 40% dalla media 
varianza_sales <- var(sales)
dev_std_sales <- sd(sales)

#boxplot - creazione del grafico

# Imposta i margini del grafico per fare più spazio  par(mar = c(basso, sinistra, alto, destra))
par(mar = c(5, 5, 5, 2))
boxplot(sales,
        main= "Analisi della Variabilità delle Vendite tot (sales)",
        ylab = "valore delle vendite",
        xlab="variabile sales",
        col = "lightblue",
        border="darkblue",
        notch =TRUE, #stringe al centro per indicare la mediana
        horizontal= FALSE #orientamento verticale
        )
#informazioni h= oriz v = vert
abline(h=quantile(sales),col="lightblue")
abline(h=IQR(sales),col="red")

# Aggiungi un punto rosso a forma di rombo per indicare la MEDIA
points(1, media_sales, col = "red", pch = 18, cex = 1.5)

# Aggiungi linee di riferimento per la media e la ds
# Linea tratteggiata per la media
abline(h = media_sales, col = "tomato", lty = 2) 
# Linee punteggiate per la media +/- 1 deviazione standard
abline(h = media_sales + dev_std_sales, col = "darkgreen", lty = 3)
abline(h = media_sales - dev_std_sales, col = "darkgreen", lty = 3)


#LEGENDA

legend("topright", # Posizione riquadro
       legend = c("Mediana", "Media", "Media +/- 1 Dev. Std.", "Quantili"),
       col = c("darkblue", "red", "darkgreen","lightblue"),
       lty = c(1, 2, 3, 1), # Stile delle linee (1=continua, 2=tratteggiata, 3=punteggiata)
       pch = c(NA, 18, NA, NA, NA), # Simbolo del punto (NA = nessuno)
       cex = 0.8, # Dimensione del testo della legenda
       bty = "n"  # Rimuove il bordo dalla legenda
)

######### FORMA ##############

#pacchetti utili
#install.packages("moments")
#install.packages("ggplot2")

library(moments)
library(ggplot2)

#sintesi della variabile sales 
summary(sales)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    79.0   127.0   175.5   192.3   247.0   423.0
#asimmetria 
skewness(sales) # calcolo dell'asimmetria per la funzione sales gamma 3 > 1 è asimmetrica a sinistra. i valori più bassi sono quelli più frequenti in questa distribuzione. 
## [1] 0.718104
plot((density(sales))) #mostro la distribuzione della variabile sales
mu_line=192.3
abline(v=192.3 ,col=2) #mostro la linea della media

#curtosi 
kurtosis(sales)-3 #gamma 4 = 0 è più vicino a zero. quindi la curva ha un ampiezza simile a quella di una distribuzione normale. mesocurtica
## [1] -0.3131764
plot((density(sales)))

ggplot()+
  geom_density(aes(x=sales),col='black',fill='lightblue')

VARIABILI: VOLUME, MEDIAN_PRICE, LISTINGS, MONTH_INVENTORy
Volume: La variabile volume (vendite totali) mostra una variabilità alta( Coefficiente di Variazione del 53.7%).La distribuzione è caratterizzata da una forte asimmetria positiva (a destra), Skewness di 0.885. Infatti la media (31.01) è più alta della mediana (27.06) e della moda (14.00).Questo significa che la maggior parte delle osservazioni (il 75%, Q3) si concentra su valori inferiori a 40.89M, con il valore più frequente (Moda) a soli 14M. I valori che stanno nella porzione destra della curva (sopra il 75%,Q4,Q5) arrivano fino a 83.54M (max) , questi valori spostano la media verso destra, distanziandola dal centro. La curtosi (0.177) è molto vicina a 0, questo indica che la punta della forma è simile a quella di una distribuzione normale (mesocurtica).

Median_price: i prezzi medi sembrano stabili
La variabile median_price (quantitativa continua) mostra una variabilità bassa (CV 17.1%), questo indica che i prezzi sono abbastanza concentrati attorno alla media. La distribuzione ha una leggera asimmetria negativa, la coda tende a sinistra. (infatti Skewness = -0.365; media < mediana), la maggior parte dei prezzi si trova nella fascia alta (intorno a 130ml-134ml), ma con una coda di pochi valori più bassi. La forma è platicurtica (Kurtosis = -0.623), la curva è leggermente più piatta rispetto a una distribuzione normale.

Listing: gli annunci sono disomogenei, non ben equilibrati
In qeusta variabile i osserva una asimmetria positiva (a destra). Questo è evidenziato sia dal valore di Skewness (0.649) sia dal fatto che la media (1738.02) è > della mediana (1618.5). Ciò indica che la maggior parte delle osservazioni si concentra nella parte sinistra della distribuzione (valori più bassi), ma la presenza di pochi valori molto elevati sposta la media verso destra. La variabilità è molto alta. il coef di variabilità (cv) è al 43.3% (superiore al 30%), possiamo concludere che i dati sono molto dispersi e poco concentrati attorno alla media. Inoltre, la kurtosi indica una distribuzione platicurtica, con una forma più schiacciata e piatta rispetto alla distribuzione normale.

Months_inventory: distribuzione simile a una distr. normale, osservazioni sufficientemente ben distribuite.

Dall’analisi descrittiva di questa variabile possiamo notare che in media (mean = 9.19) le inserzioni attive vengono vendute in 9 mesi.La media è leggermente maggiore della mediana e della moda, questo dato indica che la maggior parte dei lavori è concentrata nella porzione sinistra della curva. quindi ci sono molte più osservazioni con valori più bassi ( min 3.4 = in 3 mesi sono state vendute tutte le inserzioni). Sembra che la distribuzione ha comunque un asimmetria positiva perchè ci sono pochi valori alti ( Q3 10,95 e Max 14.9) che spostano la media verso la parte destra della distribuzione (significa che in alcuni periodi o luoghi il totale delle inserzioni ci hanno messo quasi più di 1 anno per esser vendute tutte). Concludiamo che la distribuzione ha una leggerissima asimmetria positiva (0.041). Però 0.041 è un valore molto vicino a 0 quindi a una distribuzione normale (media=mediana=moda). Possiamo concludere che i dati sono omogenei e distrubuiti quasi perfettamente simmetrica .I n generale le inserzioni vengono vendute abbastanza rapidamente, possiamo notarlo dalla varianza e dal CV perchè è relativamente bassa (CV 25%, <30%). Similmente la deviazione standard, non è elevata e rispetto alla media i dati sembrano non essere molto dispersi. Infine la curtosi , con un valore vicino allo 0 ci indica che è leggermente platicurtica ma assomiglia molto alla distribuzione mesocurtica della tipica distribuzione normale. In conclusione, le inserzioni totali (in base al periodo o luogo) sono abbastanza distribuite e vengono vendute entro 1 anno dalla pubblicazione dell’annuncio.

# INIDICI DI POSIZIONE 

# FUNZIONE MODA 

calcola_moda <- function(x) {
  x_pulito <- x[!is.na(x)] 
  if (length(x_pulito) == 0) return(NA_real_) 
  
  tabella_freq <- table(x_pulito)
  moda <- names(tabella_freq)[which.max(tabella_freq)]
  return(as.numeric(moda))
}


# --- funzione calcolo indici di posizione 

indici_posizione <- function(x) {  
  
  mu <- round(mean(x, na.rm = TRUE), digits = 2)
  sdev <-round(sd(x,na.rm = TRUE), digits = 2)
  me <- median(x, na.rm = TRUE)
  mo <- calcola_moda(x) 
  quant <- quantile(x, probs = c(0, 0.25, 0.5, 0.75, 1), na.rm = TRUE)

  

  # Crea un VETTORE 
  results <- data.frame(
    Media = mu,
    St.dev= sdev,
    Mediana = me,
    Moda = mo,
    Min = quant[1],
    Q1 = quant[2],
    Q2 = quant[3],
    Q3 = quant[4],
    Max = quant[5]
)
  
  return(results) 
}

# creo vettore contentente le variabili restanti 
other_variables <- c("volume", "median_price", "listings", "months_inventory")

#  Seleziono solo quelle colonne specifiche del  dataset
dati_subset <- dati[, other_variables] 

# invece di un ciclo for,  uso sapply per applicare la mia funzione a ciascun elemento del vettore c other_variable.

matrice_results <- sapply(dati_subset, indici_posizione)

#  uso trasponi (t) per avere le variabili sulle righe
final_tab <- t(matrice_results)

print(final_tab)
##                  Media    St.dev   Mediana Moda   Min   Q1      Q2      Q3    
## volume           31.01    16.65    27.0625 14.003 8.166 17.6595 27.0625 40.893
## median_price     132665.4 22662.15 134500  130000 73800 117300  134500  150050
## listings         1738.02  752.71   1618.5  1581   743   1026.5  1618.5  2056  
## months_inventory 9.19     2.3      8.95    8.1    3.4   7.8     8.95    10.95 
##                  Max   
## volume           83.547
## median_price     180000
## listings         3296  
## months_inventory 14.9
library(knitr)
kable(final_tab, caption = "Indici posizioni altre variabili")
Indici posizioni altre variabili
Media St.dev Mediana Moda Min Q1 Q2 Q3 Max
volume 31.01 16.65 27.0625 14.003 8.166 17.6595 27.0625 40.893 83.547
median_price 132665.42 22662.15 134500 130000 73800 117300 134500 150050 180000
listings 1738.02 752.71 1618.5 1581 743 1026.5 1618.5 2056 3296
months_inventory 9.19 2.3 8.95 8.1 3.4 7.8 8.95 10.95 14.9
#### Variabilità per tutte le variabili restanti 
cv_var<- function(x, na.rm = TRUE) {
  return(sd(x)/mean(x)*100)
}


all_variability <- function(x) {
  
  range_vals <- range(x, na.rm = TRUE)
  range_diff <- range_vals[2] - range_vals[1] 
  
  iqr_var <- IQR(x, na.rm = TRUE)
  varianza <- var(x, na.rm = TRUE)
  sdev <- round(sd(x, na.rm = TRUE), digits = 2)
  coef_var <- cv_var(x, na.rm = TRUE)
  
  results_var <- c(
    Range = range_diff,
    IQR = iqr_var,
    Varianza = varianza,
    SD = sdev,
    CV = coef_var
  )
  
  return(results_var)
}

other_variables <- c("volume", "median_price", "listings", "months_inventory")

dati_subset <- dati[, other_variables] 

matrice_results_var <- sapply(dati_subset, all_variability)

final_tab_var <- t(matrice_results_var)

print(final_tab_var)
##                       Range        IQR     Varianza       SD       CV
## volume               75.381    23.2335 2.772707e+02    16.65 53.70536
## median_price     106200.000 32750.0000 5.135730e+08 22662.15 17.08218
## listings           2553.000  1029.5000 5.665690e+05   752.71 43.30833
## months_inventory     11.500     3.1500 5.306889e+00     2.30 25.06031
library(knitr)
kable(final_tab_var, caption = "Variabilità altre variabili")
Variabilità altre variabili
Range IQR Varianza SD CV
volume 75.381 23.2335 2.772707e+02 16.65 53.70536
median_price 106200.000 32750.0000 5.135730e+08 22662.15 17.08218
listings 2553.000 1029.5000 5.665690e+05 752.71 43.30833
months_inventory 11.500 3.1500 5.306889e+00 2.30 25.06031
## indici di FORMA per le variabili restanti


#pacchetti utili

library(moments)
library(ggplot2)


#funzione calcolo asimmetria 
asimmetry<- function(x, na.rm=TRUE){
  sk <- round(skewness(x, na.rm=na.rm), digits = 3)
  kurt_ex <- round(kurtosis(x, na.rm=na.rm)-3, digits =3)
  
  results_form <-c(
    Skewness = sk,
    Kurtosis_Excess= kurt_ex
  )
  
  return(results_form)
}

other_variables <- c("volume", "median_price", "listings", "months_inventory")

dati_subset <- dati[, other_variables] 

matrice_results_form <- sapply(dati_subset, asimmetry)

final_tab_form <- t(matrice_results_form)

print(final_tab_form)
##                  Skewness Kurtosis_Excess
## volume              0.885           0.177
## median_price       -0.365          -0.623
## listings            0.649          -0.792
## months_inventory    0.041          -0.174
library(knitr)
kable(final_tab_form, caption = "Indici di forma: asimmetria e kurtosi")
Indici di forma: asimmetria e kurtosi
Skewness Kurtosis_Excess
volume 0.885 0.177
median_price -0.365 -0.623
listings 0.649 -0.792
months_inventory 0.041 -0.174
#per i grafici non posso usare supply( opera su vettori e semplifica risultati in 1 vettore) perciò utilizzo direttamente ggplo e creo il ciclo for per le variabili contenute in "other_variables".

library(ggplot2)

# ciclo for per creare i plot 

for (var in other_variables) {
  
  # Calcola la media per quella colonna

  media_val <- mean(dati_subset[[var]], na.rm = TRUE)
  
  # Crea il ggplot
  plot_var <- ggplot(dati_subset, aes(x = dati[[var]])) +
    geom_density(col = 'black', fill = 'lightblue', alpha = 0.7) +
    
    # Agg la linea della media
    geom_vline(xintercept = media_val, 
               col = "red", 
               linetype = "dashed", 
               size = 1) +
    
    # Titolo
    ggtitle(paste("Densità e Media di:", var)) +
    theme_minimal()
  
  # STAMPA il grafico
  print(plot_var)
  
}
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

3. Identificazione delle variabili con maggiore variabilità e asimmetria

La variabile con la più alta variabilità è Volume. Per confrontare la variabilità tra variabili che hanno unità di misura diverse (es. milioni di dollari, numero di annunci), ho osservato il coefficiente di variazione.
Volume ha un CV di 53.7% , un valore alto che indica un’elevata dispersione dei dati intorno alla media. Infatti, questa alta dispersione è visibile anche negli altri indici. Se consideriamo IQR (23.23) è un valore simile alla mediana (27.06), quindi il 50% dei dati centrali è molto sparso.

Confronto con altre variabili: Listing ha un CV del 43.3% (moderatamente variabile) mentre Median_price (17.1%) e months_inventory(25.1%) sono molto più stabili.

La variabile con la distribuzione più asimmetrica è sempre volume.
Per studiare l’asimmetria ho prima osservato gli indici di posizione (media>mediana>moda) e successivamente ho osservato se il valore di skewness fosse lontano da 0.Valori lontani da 0 indicano una forte asimmetria.
Volume, rispetto alle altre variabili, mostra un’evidente asimmetria positiva (a destra), con la media (31.01) più alta della mediana (27.06). La Skewness è 0.885, ed è il valore più alto tra tutte le variabili. Questi dati confermano che la distribuzione ha una marcata pendenza a destra. Questo significa che la maggior parte dei volumi di vendita è bassa, ma ci sono poche osservazioni con valori alti che spostano la media verso l’alto, verso la parte destra della curva. Infine ho carcato di capire anche la forma della punta della curca attraverso l’analisi della Kurtosi (0.177), che, essendo vicina a 0, indica una forma mesocurtica (simile quindi alla distribuzione normale).

4. Creazione di classi per una variabile quantitativa

Ho selezionato la variabile quantitativa “sales” e l’ho suddivisa in 5 classi. Ho creato una distribuzione di frequenze includendo nella tabella il calcolo dell’indice di Gini. Infine, ho rappresentato i dati con un barbox.

Discussione: la distribuzione di frequenza relativa mostra che in generale il campione di n tot vendite è fortemente sbilanciato. Infatti il maggior numero di vendite totali è distribuito nelle classi più piccole. Dalle frequenze relative possiamo osservare che quindi la prima e la seconda classe hanno un maggior numero di vendite. Infatti, se osserviamo le frequenze relative cumulate, la prima e la seconda classe rappresentano più del 50 % delle vendite (67%). Poi ancora, si nota che la prima classe è la classe modale (quella con la frequenza più alta, 35%).Dalle precedenti analisi abbiamo visto che la forma della distribuzione è asimmetrica con pendenza a destra (skewness positiva: 0.71).Questo dato è rafforzato dall’indice di gini che è vicino all’1. ciò signfica che le unità statistiche sono eterogenee, c’è massima concentrazione nelle prime classi e quindi esiste una forte disuguaglianza nel campione. Il 67% delle unità sta nelle prime due classi (valori bassi) mentre solo il 4.6% delle unità sta nell’ultima classe (valori alti).

contingenza_tab <- function(sales, nclass = 5) {
  # Creazione delle classi
  classi <- cut(sales, breaks = nclass, include.lowest = TRUE)
  
  # Frequenze assolute e relative
  ni <- table(classi)
  fi <- ni / length(sales)
  
  # Frequenze cumulate
  Ni <- cumsum(ni)
  Fi <- cumsum(fi)
  
  # Calcolo del Gini index (normalizzato)
  gini_index <- 1 - sum((fi)^2)
  J <- length(ni)  # numero di classi
  gini_norm <- gini_index / ((J - 1) / J)
  
  # Tabella finale
  tabella <- data.frame(
    Classe = names(ni),
    Frequenza = as.numeric(ni),
    Frequenza_relativa = round(as.numeric(fi), 3),
    Frequenza_cumulata = as.numeric(Ni),
    Frequenza_rel_cumulata = round(as.numeric(Fi), 3)
  )
  
  # Aggiungo indice di Gini alla tabella 
  tabella <- rbind(tabella, 
                   data.frame(
                     Classe = "Indice di Gini (norm.)",
                     Frequenza = NA,
                     Frequenza_relativa = round(gini_norm, 3),
                     Frequenza_cumulata = NA,
                     Frequenza_rel_cumulata = NA
                   ))
  
  return(tabella)
}

# Esempio di uso:
contingenza_tab(sales)
##                   Classe Frequenza Frequenza_relativa Frequenza_cumulata
## 1             [78.7,148]        84              0.350                 84
## 2              (148,217]        77              0.321                161
## 3              (217,285]        41              0.171                202
## 4              (285,354]        27              0.112                229
## 5              (354,423]        11              0.046                240
## 6 Indice di Gini (norm.)        NA              0.913                 NA
##   Frequenza_rel_cumulata
## 1                  0.350
## 2                  0.671
## 3                  0.842
## 4                  0.954
## 5                  1.000
## 6                     NA
#BARPLOT SALES 
# Seleziona tutto tranne l'ultima riga
tab_dati <- contingenza_tab(sales)
dati_per_plot <- head(tab_dati, 5) 

# Barplot delle frequenze relative
etichette_asse_x = c("1","2","3","4","5")
colori_barre= c("darkblue", "lightblue","purple","pink","lavender")
barplot(dati_per_plot$Frequenza_relativa,
        names.arg = etichette_asse_x, #num da 1 a 5 (indicano le classi)
        main = "Distribuzione delle vendite (Sales)",
        xlab = "N totale vendite divisi in classi",
        ylab = "Frequenze relative (%) ",
        col = colori_barre,
        las = 1)  # ruota le etichette orizz


testo_legenda <- paste(etichette_asse_x, "=", dati_per_plot$Classe)


legend("topright", # Posizione riquadro
       legend = testo_legenda, #usa i numeri e i valori delle classi
       title= "Legenda Classi",
       fill= colori_barre,
       cex = 0.8, # Dimensione del testo della legenda
       bty = "n"  # Rimuove il bordo dalla legenda
) 

5. Calcolo della probabilità

Qual è la probabilità che, presa una riga a caso di questo dataset, essa riporti la città “Beaumont”? E la probabilità che riporti il mese di Luglio? E la probabilità che riporti il mese di dicembre 2012?

Estraggo i dati totali (240 osservazioni) e i casi favorevoli per le condizioni richieste. Calcolo la probabilità come: Probabilità = Casi Favorevoli / Casi Totali. 1) 240/60= 25% 2) 240/20 = 0.083% 3) 0.016%

#install.packages("dplyr")
#library(dplyr)
table(city)
## city
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60
sum(dati$city == "Beaumont", na.rm = TRUE) # 60
## [1] 60
#Casi Favorevoli 
conteggio_beaumont <- sum(dati$city == "Beaumont", na.rm = TRUE)
#Casi Totali
conteggio_totale <- nrow(dati) 

# Calcolo della probabilità
probabilità <- conteggio_beaumont / conteggio_totale

print(probabilità) 
## [1] 0.25
#funzione per estrarre 1 riga dalla variabile city e calcolare probabilità

prob_cities <- function(dati, var_city ="city") {
rand_city <- sample((dati[[var_city]]), 1) #Estrae una città a caso
conteggio_fav <- sum(dati[[var_city]] == rand_city, na.rm = TRUE) #casi favorevoli
conteggio_tot <- nrow(dati) # casi totali
prob<- conteggio_fav / conteggio_tot # Calcolo probabilità
  return(list(
    città = rand_city,
    probability = prob
  ))
}
results_cities <- prob_cities(dati)
print(results_cities)
## $città
## [1] "Bryan-College Station"
## 
## $probability
## [1] 0.25
#probabilità mese luglio: 
table(month)
## month
##  1  2  3  4  5  6  7  8  9 10 11 12 
## 20 20 20 20 20 20 20 20 20 20 20 20
sum(dati$month == "7", na.rm = TRUE) #
## [1] 20
calcola_prob_categ <- function(vettore_categorico) {
#useNA = "ifany" include i valori NA nel conteggio, se esistono
conteggi <- table(vettore_categorico, useNA = "ifany")
probabilita <- prop.table(conteggi)#probabilità
  return(probabilita)
}

 # Calcolo probabilità 
prob_month <- calcola_prob_categ(dati$month)
print(prob_month)
## vettore_categorico
##          1          2          3          4          5          6          7 
## 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333 
##          8          9         10         11         12 
## 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333
prob_city <- calcola_prob_categ(dati$city)
print(prob_city)
## vettore_categorico
##              Beaumont Bryan-College Station                 Tyler 
##                  0.25                  0.25                  0.25 
##         Wichita Falls 
##                  0.25
#probabilità dicembre 2012
# Casi favorevoli 
month_year <- sum(dati$month == 12 & dati$year == 2012, na.rm = TRUE)
#Casi Totali
conteggio_totale <- nrow(dati)
#Probabilità
prob_month_year <- month_year/ conteggio_totale
print(prob_month_year)
## [1] 0.01666667
#BARPLOT


library(ggplot2)
library(scales) 

# Grafico a barre per le probabilità (frequenze relative)
ggplot(dati, aes(x = city)) +
#group = 1 serve per calcolare la proporzione sul totale
  geom_bar(aes(y = after_stat(prop), group=1 ), 
           fill = "lightblue", col = "black") +
  
  # Aggiunge etichette in % sopra le barre
  geom_text(aes(y = after_stat(prop), 
                label = percent(after_stat(prop), accuracy = 1)), 
            group = 1,
            stat = "count", 
            vjust = -0.5) +
  
  # Formatta l'asse Y come percentuale

  ggtitle("Probabilità (Frequenza Relativa) per Città") +
  xlab("Città") +
  ylab("Probabilità")

# Grafico a barre per le probabilità (frequenze relative) dei mesi
ggplot(dati, aes(x = month)) +
  geom_bar(aes(y = after_stat(prop), group = 1), 
           fill = "lightgreen", col = "black") +
  
  scale_y_continuous(labels = percent) +
  ggtitle("Probabilità (Frequenza Relativa) per Mese") +
  xlab("Mese") +
  ylab("Probabilità") +
  theme_minimal()

6. Creazione di nuove variabili

Abbiamo già a disposizione la variabile median_price(prezzo mediano). Ho deciso di aggiungere una nuova variabile chiamata mean_price che calcola il prezzo medio delle case vendute per città e volendo anche per mese.
Abbiamo a disposizione le variabili, “volume” che contiene il valore totale delle vendite (in milioni di dollari) e “sales” che contiene il numero totale di vendite. Se dividiamo “volume” valore totale delle vendite per il n. totale di vendite (come se fosse il n. delle nostre osservazioni) possiamo trovare il prezzo medio degli immobili per ogni città. mean_price=volume/sales Ho notato che volume è in milioni di dollari. Riportare il prezzo medio in milioni può essere poco comprensibile o in generale difficile da analizzare a colpo d’occhio. Per semplificare moltiplico per 10^6 e ottengo il valore medio in dollari.

Calcolo dell’efficaciia: Per calcolare l’efficacia ho pensato di creare un indice da 0 a 1 che indica quante vendite vengono effettuate in base al numero di annunci (listing) e il tempo mensile che ci impiegano gli annunci ad essere completati ( month_inventory). Valori più elevati indicano città o mesi in cui gli immobili si vendono più rapidamente, espressione un mercato che è più attivo e vendite efficaci.

si può usare per confrontrare le città in cui ci sono più vendite (es. max(efficacy)). o per vedere se nel tempo gli immobili vengono venduti meglio o peggio. oppure per vedere se ci sono mesi in cui si vende di più o di meno. (es. quando il mercato è dinamico o saturo).

Commento e analisi:

nel 2014 nella città di Bryan College c’è stato il maggior numero di efficienza nell vendite nel mese di luglio. 1041 annunci sono stati esauriti in 4 mesi circa (vedi: max(efficacy). il mercato sembra dinamico.

Andando più a fondo a questa analisi, ho creato un boxplot per vedere qual è la città che effettivamente ha livelli di efficacy maggiori, e che quindi ha un mercato più attivo. Senza questa analisi sarei potuto andare andato incontro ad un errore. Ovvero: inizialmente non avevo considerato gli outliers!. Infatti, come si può notare dal boxplot, è verò che il valore massimo di efficacia è stato registrato nella città di BC nel 2014, però questè è un valore unico e molto lontano dalla media per la stessa città di BC!. Da notare inoltre che, in media anche la città di Wichita Falls mostra di avere un mercato abbastanza dinamico. Wichita Falls ha meno variabilità nelle vendite rispetto a Brayan College e sono abbastanza efficaci nel tempo. Quindi rispetto a tutte le altre città, a BC si registrano delle vendite efficaci da record ( efficacy 0.23) , a Wichita Falls mediamente le vendite sono comunque efficaci ( efficacy 0.16) e guadagna il secondo posto.

mean_price <- mean(dati$Price, na.rm = TRUE)
## Warning in mean.default(dati$Price, na.rm = TRUE): argument is not numeric or
## logical: returning NA
attach(dati)
## The following objects are masked from dati (pos = 7):
## 
##     city, listings, median_price, month, months_inventory, sales,
##     volume, year
## The following objects are masked from dati (pos = 8):
## 
##     city, listings, median_price, month, months_inventory, sales,
##     volume, year
#creare una nuova variabile
dati$mean_price <- (volume * 1e6) / sales
summary(mean_price)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##      NA      NA      NA     NaN      NA      NA       1
head(mean_price,5)
## [1] NA
#efficacy: creo la variabile efficacia 
dati$efficacy <- dati$sales / (dati$listings * dati$months_inventory)
View(dati)

# esempio: riga dove efficacy ha il valore maggiore
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
dati %>%
  filter(efficacy == max(efficacy))
##                    city year month sales volume median_price listings
## 1 Bryan-College Station 2014     7   403 83.547       172600     1041
##   months_inventory mean_price   efficacy
## 1              4.1   207312.7 0.09442141
#grafico 1 come
library(ggplot2)

ggplot(dati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = mean_price, color = city)) +
  geom_line() +
  labs(title = "Andamento del prezzo medio degli immobili in Texas",
       x = "Data", y = "Prezzo medio ($)") +
  theme_minimal()

#grafico 2 città con valore più alto di efficacia nel tempo. 
ggplot(dati,aes(x=city,y=efficacy, fill= city)) +
  geom_boxplot()+
  labs(title = "Efficacia del mercato immobiliare per città", 
       x= "città", y="indice efficacia")+
  theme_minimal()

library(ggplot2)
library(dplyr)

# Calcola la media generale di efficacy
media_generale <- mean(dati$efficacy, na.rm = TRUE)

# Calcola la media per ogni città
medie_città <- dati %>%
  group_by(city) %>%
  summarise(media_city = mean(efficacy, na.rm = TRUE))

# Grafico
ggplot(dati, aes(x = reorder(city, efficacy), y = efficacy, fill = city)) +
  geom_boxplot(alpha = 0.7) +  # boxplot semi-trasparenti
  # Linea rossa della media generale
  geom_hline(yintercept = media_generale, linetype = "dashed", color = "red", linewidth = 1) +
  # Punti neri per la media di ogni città
  geom_point(data = medie_città, 
             aes(x = reorder(city, media_city), y = media_city),
             color = "black", size = 2.5) +
  labs(
    title = "Efficacia del mercato immobiliare per città",
    subtitle = paste("Linea rossa = media generale (", round(media_generale, 2), ")", sep = ""),
    x = "Città (ordinate per efficacia media)",
    y = "Indice di efficacia"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none"  # rimuove la legenda 
  )

mean(dati$efficacy[dati$city == "Wichita Falls"], na.rm = TRUE)
## [1] 0.01664188
mean(dati$efficacy[dati$city=="Bryan-College Station"], na.rm = TRUE)
## [1] 0.02389662

7 ANALISI CONDIZIONALE

Ho iniziato raggruppando i dati nel mio nuovo dataset, e generando dei summary: summary_mydati, summary city, season_summary).Questi summary contengono alcune nuove variabili ( totally sales, totally listings , mean_price e sd_price) rispetto al dataset originale.

Summary_city è stato usato per creare una tabella markdown per mostrare il prezzo medio e la variabilità (deviazione standard).

Grafici: Ho usato dei boxplot, lineplot e barplot per analizzare e visualizzare l’anndamento nel tempo (mesi e anni) per valutare per le varie città il cambio del prezzo medio, il numero di vendite, le vendite stagionali e l’andamento del numero di annunci.

library(dplyr)
library(ggplot2)

#_____SUMMARY________________________________________

#Raggruppo i dati per citta, mese e anno in un nuovo dataset
#con nuove variabili utili per i miei grafici. 

summary_mydati <- dati %>% # concatenare le funzioni in dplyr "pipe"
  group_by(city,year,month) %>% #raggruppo per città, anno e mese
  summarise(
  mean_price = mean((volume * 1e6) / sales, na.rm=TRUE),
  sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
  totally_sales =sum(sales, na.rm = TRUE), 
  totally_listings = sum(listings, na.rm = TRUE),
  .groups = "drop"
)

View(summary_mydati)


#Summary per raggruppare le 4 città

summary_city <- dati %>%
  group_by(city) %>%   # raggruppo solo per città
  summarise(
    mean_price = mean((volume * 1e6) / sales, na.rm = TRUE),
    sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
    totally_sales = sum(sales, na.rm = TRUE),
    totally_listings = sum(listings, na.rm = TRUE),
    .groups = "drop"
  )

summary_city
## # A tibble: 4 × 5
##   city                  mean_price sd_price totally_sales totally_listings
##   <chr>                      <dbl>    <dbl>         <int>            <int>
## 1 Beaumont                 146640.   11232.         10643           100759
## 2 Bryan-College Station    183534.   15149.         12358            87488
## 3 Tyler                    167677.   12351.         16185           174303
## 4 Wichita Falls            119430.   11398.          6964            54575
#creo la tabella in Rmarkdown
summary_city %>%
  arrange(desc(mean_price)) %>%
  knitr::kable(caption = "Sintesi per città: media, deviazione standard")
Sintesi per città: media, deviazione standard
city mean_price sd_price totally_sales totally_listings
Bryan-College Station 183534.3 15149.35 12358 87488
Tyler 167676.8 12350.51 16185 174303
Beaumont 146640.4 11232.13 10643 100759
Wichita Falls 119430.0 11398.48 6964 54575
#____________________________________________________________________________

# GRAFICI

#1) PREZZO MEDIO

# confronto tra le città: come cambia il prezzo medio per città nei mesi tra il 2010 e il 2014

ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = mean_price, color = city)) +
  geom_line() +
  labs(title = "Prezzo medio per città (2010-2014)",
       x = "Data", y = "Prezzo medio ($)") +
  theme_minimal()

# prezzo medio nei mesi e negli anni con linea di tendenza: 
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
                           y = mean_price)) +
  geom_line(color = "steelblue", alpha = 0.7, size = 1) +
  geom_point(size = 1) +
  geom_smooth(method = "lm", color = "orange", se = FALSE, linewidth = 1.2) +
  facet_wrap(~ city, ncol = 2, scales = "free_y") +
  scale_x_date(
    date_breaks = "3 months",
    date_labels = "%b-%Y"
  ) +
  labs(
    title = "Andamento del prezzo medio per città (2010–2014)",
    subtitle = "Linea arancione = trend line (retta di regressione)",
    x = "Mese e anno",
    y = "Prezzo medio in dollari ($)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
    strip.text = element_text(face = "bold")
  )
## `geom_smooth()` using formula = 'y ~ x'

# Calcolo ledia generale di tutte le città utile per il boxplot per le città
media_generale <- mean(summary_city$mean_price, na.rm = TRUE)

# Grafico boxplot prezzi medi per città
ggplot(summary_mydati, aes(x = city, y = mean_price, fill = city)) +
  geom_boxplot(alpha = 0.7) +
  # Linea rossa della media generale
  geom_hline(yintercept = media_generale, linetype = "dashed", color = "red", linewidth = 1) +
  # Punti neri per la media di ciascuna città
  geom_point(data = summary_city, 
             aes(x = city, y = mean_price),
             color = "black", size = 3) +
  labs(
    title = "Prezzo medio degli immobili per città",
    subtitle = paste("Linea rossa = media generale (", round(media_generale,2), ")", sep=""),
    x = "Città",
    y = "Prezzo medio (€)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none"
  )

#2) VENDITE 

# confronto tra le città: come cambia il numero di vendite per città nei mesi tra il 2010 e il 2014
# in più la linea di tendenza per vedere il trend nel tempo.

ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
                           y = totally_sales)) +
  geom_line(color = "steelblue", alpha = 0.7, size = 1) +
  geom_point(size = 1) +
  geom_smooth(method = "lm", color = "red", se = FALSE, linewidth = 1.2) +
  facet_wrap(~ city, ncol = 2, scales = "free_y") +
  scale_x_date(
    date_breaks = "3 months",
    date_labels = "%b-%Y"
  ) +
  labs(
    title = "Andamento mensile delle vendite per città (2010–2014)",
    subtitle = "Linea rossa = trend line (retta di regressione)",
    x = "Mese e anno",
    y = "Numero totale di vendite"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
    strip.text = element_text(face = "bold")
  )
## `geom_smooth()` using formula = 'y ~ x'

# ANALISI VENDITE STAGIONALI 
#barplot vendite nei  mesi estivi vs mesi invernali 

# creare la variabile "season" che contiene i mesi estivi o invernali 
summary_mydati2 <- summary_mydati %>%  #con mutate creo la nuova variab season
  mutate(season = case_when(
    month %in% c(6, 7, 8) ~ "Estate", # case_when come ifelse se in month c'è il vet. c allora
    month %in% c(12, 1, 2) ~ "Inverno",TRUE ~ NA_character_)) #gli altri sono NA. 

#Calcola vendite totali per città e stagione
season_summary <- summary_mydati2 %>%
  filter(!is.na(season)) %>% #rimuove i NA da season
  group_by(city, season) %>% #raggruppa per città e stagione
  summarise(
    total_sales_season = sum(totally_sales, na.rm = TRUE),
    .groups = "drop"
  ) #scioglie il raggruppamento

#  Crea il barplot, facet per città
ggplot(season_summary, aes(x = season, y = total_sales_season, fill = season)) +
  geom_col(width = 0.6) +
  facet_wrap(~ city, ncol = 2, scales = "free_y") + #intervalli diversi su asse y
  labs(
    title = "Confronto vendite tra mesi estivi e invernali (2010–2014)",
    x = "Stagione",
    y = "Totale vendite"
  ) +
  scale_fill_manual(values = c("Inverno" = "steelblue", "Estate" = "orange")) +
  theme_minimal() +
  theme(
    strip.text = element_text(face = "bold", size = 10),
    axis.text.x = element_text(angle = 0, size = 9),
    legend.position = "none"
  )

#3 ANNUNCI 
#confronto tra le città: come cambia il numero di annunci per città nei mesi tra il 2010 e il 2014

ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = totally_listings, color = city)) +
  geom_line() +
  labs(title = "annunci per città (2010-2014)",
       x = "Data", y = " numero totale di annunci") +
  theme_minimal()

8 e 9 Creazione di visualizzazioni con ggplot2 e CONCLUSIONI

1 Boxplot per confrontare la distribuzione del prezzo mediano tra le città:

Commento:

La città di Bryan-College Station ha una mediana più alta rispetto a tutte le altre. Se notiamo la grandezza dei box (IQR), la variabilità del 50% centrale dei dati per questa città è ridotta. I valori non sono molto dispersi attorno alla mediana (box IQR stretto) e possiamo immaginare un tipo di mercato piuttosto omogeneo; in generale i prezzi rimangono simili. Però allo stesso tempo i whiskers (baffi) allungati verso l’alto, e la media (pallino blu) posizionata sopra la mediana, ci informano che c’è una tendenza a prezzi più elevati. Questo dato è confermato anche dalla presenza di outliers, informandoci così che in questa città si registrano i prezzi più alti rispetto a tutte le altre. Deduco così che è l’area in cui le case sono mediamente più costose.

A seguire, in ordine dal più costoso al più economico, troviamo le città di Tyler e Beaumont. I loro prezzi mediani sono più bassi rispetto a Bryan-College Station. Nonostante qualche valore eccezionale a Beaumont (outlier alto), nella città di Tyler i prezzi mediani si mantengono più elevati. È importante notare che a Beaumont i prezzi hanno la maggiore variabilità centrale (la scatola IQR è visibilmente più larga delle altre), suggerendo un mercato più eterogeneo in quella fascia di prezzo.

Infine, la città che ha un prezzo mediano più economico di tutte è Wichita Falls. I valori degli immobili qui mostrano una chiara tendenza ad assumere prezzi più economici, come indicato dal baffo inferiore molto lungo (forte asimmetria negativa).

Riepilogo :Bryan-College Station ha la mediana più alta (prezzo mediano più alto) e una tendenza verso prezzi costosi (asimmetria positiva)

Beaumont ha la maggiore dispersione nella fascia centrale dei prezzi (IQR più largo), indicando un mercato eterogeneo

Wichita Falls ha il prezzo mediano più basso e una forte asimmetria verso prezzi economici (baffo inferiore lungo)

Tyler si posiziona come seconda città più costosa, con una distribuzione piuttosto simmetrica attorno alla sua mediana

library(dplyr)
library(ggplot2)

#summary city

summary_median_city <- dati %>%
  group_by(city) %>%
  summarize(
    median_prezzo = median(median_price, na.rm=TRUE),
    mean_price = mean((volume * 1e6) / sales, na.rm=TRUE),
    sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
    .groups = "drop"
  )

summary_median_city
## # A tibble: 4 × 4
##   city                  median_prezzo mean_price sd_price
##   <chr>                         <dbl>      <dbl>    <dbl>
## 1 Beaumont                     130750    146640.   11232.
## 2 Bryan-College Station        155400    183534.   15149.
## 3 Tyler                        142200    167677.   12351.
## 4 Wichita Falls                102300    119430.   11398.
#boxplot confronto città

ggplot(dati, aes(x=city, y=median_price,fill=city))+
         geom_boxplot(alpha= 0.5) + #trasparenza
         geom_point(data=summary_median_city, aes(x=city,y=median_prezzo),
         color="blue",size=3)+
         labs( title="Confronto della distribuzione del prezzo mediano tra le città", 
               x= "città", 
               y=" prezzo mediano ($)")+
         theme_minimal()+
         theme(axis.text.x = element_text(angle = 45, hjust = 1),
         legend.position = "none")

2. Boxplot per confrontare la distribuzione del valore totale delle vendite tra le varie città e tra i vari anni

Commento: Dall’analisi del confronto della distribuzione del valore totale delle vendite tra le varie città nel periodo di tempo compreso dal 2010 al 2014 si può osservare che tutte le cittè eccetto Wichita Falls,la quale rimane costante nel tempo, mostrano un aumento del valore totale delle vendite. In particolare, il valore mediano delle vendite come visto precedentemente aumenta anno dopo anno. Un esempio è la città di Bryan College che dal 2013 al 2014 registra un aumento notevole superando ampiamente Beaumont. Nella città di Tyler si registra un valore totale di vendite mediano costantemente più alto rispetto a tutte le altre città e in tutti i 5 anni. Anche la città di Bryan College Station mostra un numero elevato di vendite totali (raggiungendo quasi Tyler). però si distingue per avere una variabilità dei valori molto elevata (i suoi box e baffi sono spesso i più lunghi, ad esempio nel 2013 e 2014).

library(dplyr)
library(ggplot2)

#summary city

summary_vendite <- dati %>%
  group_by(city,year,month) %>%
  summarize(
    totally_sales =sum(sales, na.rm = TRUE),
    .groups = "drop"
  )
summary_vendite
## # A tibble: 240 × 4
##    city      year month totally_sales
##    <chr>    <int> <int>         <int>
##  1 Beaumont  2010     1            83
##  2 Beaumont  2010     2           108
##  3 Beaumont  2010     3           182
##  4 Beaumont  2010     4           200
##  5 Beaumont  2010     5           202
##  6 Beaumont  2010     6           189
##  7 Beaumont  2010     7           164
##  8 Beaumont  2010     8           174
##  9 Beaumont  2010     9           124
## 10 Beaumont  2010    10           150
## # ℹ 230 more rows
#boxplot confronto città e anno

ggplot(dati, aes(x=city, y=sales,fill= factor(year)))+ #factor discreta non continua
         geom_boxplot(alpha= 0.6, position= position_dodge(width=0.8)) + #trasparenza e sovrapposizione boxplot
         labs( 
           title="Distribuzione delle vendite per città e anno", 
           x= "città", 
           y=" valore totale  ($)",
           fill="Anno")+
         theme_minimal()+
         theme(axis.text.x = element_text(angle = 45, hjust = 1))

3 Grafici a barre per il confronto il totale delle vendite per mese e città

1)barplot vendite totali per città e trend

2)barplot a barre sovraimposte

3)barplot a barre sovraimposte normalizzato

Commento:

1)il grafico a barre 1 mostra il confronto totale delle vendite tra le città dell’arco di tempo dal 2010 al 2014. La città che mostra il numero di elevato di vendite è Tyler(max=423, mean=269). A seguire troviamo le città di Bryan College Station e Beaumont. Per la città di Bryan College le vendite sono molto fluttuanti durante i 5 anni e si può notare come aumentano e diminuiscono: all’inizio e alla fine di ogni anno si notano dei picchi positivi e negativi. Nonostante ciò, le vendite hanno avuto un trend in aumento, specialmente nell’ultimo anno (2014). Similmente possiamo osservare a Beaumont, dove la variabilità di vendite è più bassa e il trend di n.di vendite negli anni è in lieve ma costante aumento positivo. Infine all’ultimo posto troviamo Wichita Falls dove il numero di vendite è rimasto costante negli anni, senza variazioni trend di crescita e registra i valori di vendite più bassi rispetto alle altre città (max 167, mean 116).

2)Il grafico 2 a barre sovrapposte mostra e conferma il contributo maggiore della città di Tyler nel n.totale di vendite nel tempo. Le vendite sembrano seguire un pattern stagionale, con picchi di vendite di mesi primaverili/estivi e un calo nei mesi autunnali/invernali, creando così un’onda sinusoidale che mostra l’andamento oscillatorio delle vendite durante l’anno. Questo andamento oscillatorio però è caratterizzato dall’ un trend di crescita positivo dal 2010 al 2014 per tuttè le cittè tranne che per Wichita Falls.

3) Il grafico 3 mostra le stesse informazioni del precedente, ma in forma percentuale. Si nota che Tyler e Bryan College Station sono le città che contribuiscono in modo più consistente alle vendite totali (ciascuna con circa il 30–35%), seguite da Beaumont e infine Wichita Falls, che mantiene una quota intorno al 10–15%. Le proporzioni restano abbastanza stabili nel tempo, indicando che la distribuzione delle vendite tra le città non è cambiata in modo significativo tra il 2010 e il 2014.

library(dplyr)
library(ggplot2)


summary_vendite <- dati %>%
  group_by(city,year,month) %>%
  summarize(
    totally_sales =sum(sales, na.rm = TRUE),
    .groups = "drop"
  )
summary_vendite
## # A tibble: 240 × 4
##    city      year month totally_sales
##    <chr>    <int> <int>         <int>
##  1 Beaumont  2010     1            83
##  2 Beaumont  2010     2           108
##  3 Beaumont  2010     3           182
##  4 Beaumont  2010     4           200
##  5 Beaumont  2010     5           202
##  6 Beaumont  2010     6           189
##  7 Beaumont  2010     7           164
##  8 Beaumont  2010     8           174
##  9 Beaumont  2010     9           124
## 10 Beaumont  2010    10           150
## # ℹ 230 more rows
#grafico 1) Barplot vendite per città e trend 
ggplot(dati,aes(x = as.Date(paste(year, month, "01", sep="-")), y = sales, color = city)) +
  geom_col(width= 0.5)+
  geom_smooth(method = "lm", color = "tomato", se = FALSE, linewidth = 1) +
  facet_wrap(~ city, ncol=2)+ #città tutte sulla stessa scala
  #facet_wrap(~city,ncol=2, scales="free_y")+ #scales="free_y da usare per vedere la scala propria di ogni città
  labs(title= "confronto totale vendite tra le città",
       x= "Mesi/Anni",
       y=" N.tot Vendite")+
   theme_minimal() +
  theme(
    strip.text = element_text(face = "bold", size = 10),
    axis.text.x = element_text(angle = 0, size = 9),
    legend.position = "none")
## `geom_smooth()` using formula = 'y ~ x'

#grafico 2) barre sovrapposte non normalizzato
# creo nuova variabile "periodo" che rappresenta mese/anno - per evitare date doppie
summary_mydati <- summary_mydati %>%
  mutate(periodo = paste(year, month, sep = "-")) #nuova variabile periodo

# grafico a barre sovrapposte
ggplot(summary_mydati, aes(x = periodo, y = totally_sales, fill = city)) +
  geom_col(position = "stack") +
  labs(
    title = "Confronto totale vendite mensili tra città (2010–2014)",
    subtitle = "Le barre sovrapposte mostrano il contributo di ogni città al totale mensile",
    x = "Mese e anno",
    y = "Totale vendite",
    fill = "Città"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 80, hjust = 1, size = 6),
    plot.title = element_text(face = "bold"),
    legend.position = "right"
  )

#grafico 3) grafico a barre normalizzato (per mostrare le percentuali)
#creo nuovo summary e aggiungo una nuova variabile con dati vendite normalizzati
normalize_sales <-summary_mydati %>%
  group_by(year,month) %>%
  mutate(sales_norm= totally_sales/sum(totally_sales)) #percentuale

#grafico normalizzato 

ggplot(normalize_sales,aes(x= as.Date(paste(year,month,"01",sep="-")),
                           y=sales_norm, fill=city))+
  geom_col(position="stack")+
  scale_y_continuous(labels = scales::percent)+ #Mostra i numeri come percentuali asse y
  labs(
    title= "Vendite per città con valori in percentuale",
    x= "Anni (2010-2014)",
    y="percentuale di vendite",
    fill="Città")+
  theme_minimal()+
  theme( axis.text.x=element_text(angle=45,hjust=1,size=8))

4 Line charts per confrontare l’andamento delle vendite nel tempo

  1. linechart per confrontare l’andamento delle vendite in periodi storici differenti.

  2. Prova a creare un line chart di una variabile a tua scelta per fare confronti commentati fra città e periodi storici. Ho scelto la variabile listings: numero totale di annunci.

Commento:

Linechart 1) : Dall’analisi della linechart si può osservare che il numerodi vendite nel tempo è fluttuante. Però si può notare per ttutte le città tranne Wichita Falls, un trend di aumento delle vendite nei 5 anni. Il trend sembra crescere in maniera oscillatoria: ci sono periodi di basse vendite all’inizio dell’anno corrispondenti ai mesi invernali, i quali sono seguiti da picchi positivi nei mesi estivi. Questo pattern stagionale si ripete negli anni ed è accompagnato da un aumento del numero di vendite mediano i tutte le città tranne Wichita Falls.In quest’ultima città, questo trend di crescita non è visibile e al contrario si nota una situzione di stazionarietà (mercato fermo). Sebbene siano presenti anche qui delle oscillazioni stagionali come le altre città, queste avvengono attorno a un numero di vendite medio che rimane basso e costante nel tempo (linea di regressione piatta).

Linechart 2): come nel grafico precedente, possiamo assistere ad un pattern con andamento oscillatorio. il numero di annunci per città nel tempo è sottoposto a un incremento nei mesi estivi e un decremento nei mesi invernali. questo pattern si può sovrapporre a quello precedente del numero delle vendite e si potrebbe avanzare un ipotesi di correlazione: ” l’aumento del numero di vendite potrebbe essere correlato all’aumentare del numero di annunci”. Diversamente dall’altro grafico, però , è evidente un trend negativo negli anni. Anno dopo anno ,nelle varie città ,si registrano minori numeri di annunci. In particolare nelle città di Tyler e Bryan College station, le quali sono le città con il maggior numero di vendite. Questo dato potrebbe essere giustificato dall numero elevato di vendite, e quindi un mercato che sta andando incontro a saturazione ( poche vendite di immobili disponibili) e quindi minore inserimento di annunci. anche qui si potrebbe ipotizzare una possibile correlazione tra l’aumentare del numero di vendite e la riduzione del numero di annunci. Per una possibile conferma di queste ipotesi torna utile osservare l’andamento a Wichita Falls. il numero delle vendite è piatto e lo è anche quello degli annunci. Non c’è la dinamica “vendite in crescita vs. annunci in calo” delle altre città.

library(ggplot2)
library(dplyr)


# 1) Linechart per confronto vendite in periodi storici differenti: 
# confronto tra le città: come cambia il numero di vendite per città nei mesi tra il 2010 e il 2014. la linea di tendenza per vedere il trend nel tempo.

ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
                           y = totally_sales)) +
  geom_line(color = "black", alpha = 0.7, size = 1) +
  geom_point(size = 0.5, color="tomato") +
  geom_smooth(method = "lm", color = "orange", se = FALSE, linewidth = 1) +
  facet_wrap(~ city, ncol = 2) +
  scale_x_date(
    date_breaks = "3 months",
    date_labels = "%b-%Y"
  ) +
  labs(
    title = "Andamento mensile delle vendite per città (2010–2014)",
    subtitle = "Linea rossa = trend line (retta di regressione)",
    x = "Mese e anno",
    y = "Numero totale di vendite"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
    strip.text = element_text(face = "bold")
  )
## `geom_smooth()` using formula = 'y ~ x'

#2)linechart variabile a scelta:
#confronto tra le città: come cambia il numero di annunci per città nei mesi tra il 2010 e il #2014


#creo  summary

summary_list <- dati %>%
  group_by(city,year,month,listings)%>%
summarize(tot_list=sum(listings, na.rm = TRUE),
          .group="drop")
## `summarise()` has grouped output by 'city', 'year', 'month'. You can override
## using the `.groups` argument.
summary_list
## # A tibble: 240 × 6
## # Groups:   city, year, month [240]
##    city      year month listings tot_list .group
##    <chr>    <int> <int>    <int>    <int> <chr> 
##  1 Beaumont  2010     1     1533     1533 drop  
##  2 Beaumont  2010     2     1586     1586 drop  
##  3 Beaumont  2010     3     1689     1689 drop  
##  4 Beaumont  2010     4     1708     1708 drop  
##  5 Beaumont  2010     5     1771     1771 drop  
##  6 Beaumont  2010     6     1803     1803 drop  
##  7 Beaumont  2010     7     1857     1857 drop  
##  8 Beaumont  2010     8     1830     1830 drop  
##  9 Beaumont  2010     9     1829     1829 drop  
## 10 Beaumont  2010    10     1779     1779 drop  
## # ℹ 230 more rows
#grafico
ggplot(summary_list, aes(x= as.Date(paste(year,month,"01",sep = "-")),
                         y=tot_list, color=city))+
  geom_line()+
  geom_smooth(method = "lm", color = "black", se = FALSE, linewidth = 0.5) +
  facet_wrap(~ city, ncol = 2) +
  labs(title="N. annunci per città dal 2010 al 2014",
       x="anni / mesi ", y=" n.tot annunci")+
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'