data <- read.csv("realestate_texas.csv")
str(data)
## '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(data)
## [1] 240   8

La variabile month è una variabile categorica ordinale espressa in numeri da 1 a 12. La rendo categorica ordinale per maggiore comprensione

data$month<-factor(data$month, labels = month.name) 

il dataframe ha 240 osservazioni e 8 variabili. city - var categorica nominale year - var quant discr month - var categorica ordinale - dopo aver sostituito la var numerica sales - var quant discreta volume - var quant cont median_price - var quant cont listings - var quant discr month_inventory - var quant cont

ANALISI VARIABILI TEMPORALI: La variabile “month” si può usare per trend stagionali - effetti mensili - boxplot per confrontare distribuzione delle vendite per mese oppure si puo effettuare un confronto dell’ammontare medio delle vendite per ogni mese (ind dall’anno). La variabile “year” si puo utilizzare per analizzare trend storici longitudinali come per esempio per osservare come vendite, prezzi ed inventari mutino nel tempo - line chart

Calcolo indici di posizione, variabilità e forma per le variabili continue e creo distribuzione di frequenza per variabili categoriche

attach(data)
library(moments)

seleziono solo le variabili continue e creo un data frame con gli indici

var_cont<-data[, c("sales", "volume", "median_price", "listings", "months_inventory")]

statistiche <- data.frame(
  #Var = colnames(var_cont),
  Media = sapply(var_cont, mean),
  Mediana = sapply(var_cont, median),
  Dev_Std = sapply(var_cont, sd),
  Range = sapply(var_cont, function(x) max(x) - min(x)),
  IQR = sapply(var_cont, IQR),
  Skewness = sapply(var_cont, skewness),
  Kurtosis = sapply(var_cont, kurtosis)-3 #centro la curtosi sullo 0
)

statistiche
##                         Media     Mediana      Dev_Std      Range        IQR
## sales               192.29167    175.5000    79.651111    344.000   120.0000
## volume               31.00519     27.0625    16.651447     75.381    23.2335
## median_price     132665.41667 134500.0000 22662.148687 106200.000 32750.0000
## listings           1738.02083   1618.5000   752.707756   2553.000  1029.5000
## months_inventory      9.19250      8.9500     2.303669     11.500     3.1500
##                     Skewness   Kurtosis
## sales             0.71810402 -0.3131764
## volume            0.88474203  0.1769870
## median_price     -0.36455288 -0.6229618
## listings          0.64949823 -0.7917900
## months_inventory  0.04097527 -0.1744475

Nei 5 anni che vanno dal 2010 al 2014 compresi sono stati vendute in media 192.3 immobili al mese. Con un minimo di 79 vendite a Gennaio 2013 e Febbraio 2011 ed un massimo di 423 a Giugno 201a (Range = 344). La deviazione standard di 79,6 indica una varianza significiativa tra i mesi, evidenziata anche da un IQR di 120. L’indice di Fischer pari a 0.7 significa che la maggior parte dei mesi ha vendite relativamente basse (la coda della distribuzione si allunga verso destra) mentre alcuni mesi hanno vendite molto piu alte rispetto alla media. La forma platicurtica della curva (indice di curtosi negativo) conferma la dispersione dei valori rispetto alla media. L’alta varianza della variabile riflette l’eterogeneità delle vendite tra mesi e città, suggerendo che non c’è una chiara stabilità nel numero di transazioni immobiliari

Il valore medio delle vendite ammonta a circa 31 milioni di dollari e il 50% delle osservazioni si trova tra i 17.6 e i 40.9 milioni. Anche per questa variabile osserviamo un’assimmetria positiva. Tuttavia, rispetto alle vendite, in termini di unità immobiliari, il volume delle vendite mostra una maggiore concentrazione dei valori attorno alla media, come indicato da una curtosi positiva pari a 0.18

Il prezzo mediano degli immobili è 132.665, range e deviazione standard molto elevati, rispettivamente di 106200 e 22662$, indicando un’alta variabilità tra le osservazioni. Sebbene la distribuzione sia quasi simmetrica (skewness = -0.364, vicino a 0), i prezzi mediani variano significativamente tra le città e i periodi, mostrando un mercato immobiliare con forte eterogeneità dei prezzi.

Il numero totale degli annunci attivi (listings) è estremamente variabile, con un range di 2553 e un IQR di 1029, suggerendo una forte eterogeneità nel mercato immobiliare. La distribuzione presenta una leggera asimmetria positiva (skewness = 0.649), indicando che la maggior parte delle città ha un numero di annunci inferiore alla media. Inoltre, la bassa curtosi (-0.791) suggerisce che i valori sono dispersi su un ampio intervallo senza una forte concentrazione centrale, confermando un’alta variabilità nel numero di annunci attivi tra le città.

La quantità di tempo necessaria media per vendere tutte le inserzioni correnti è di 9.19 mesi. La variabile ha una distribuzione quasi simmetrica (skewness ≈ 0) e una concentrazione delle osservazioni vicino alla media.

#distr freq per var categoriche
N<-nrow(data)

calcola.freq<-function(x){
  ni<-table(x)
  fi<-ni/N
  Ni<-cumsum(ni)
  Fi<-cumsum(fi)
  
  tab_freq <- data.frame(
    Classi=names(ni),
    Freq_Ass=as.numeric(ni),
    Freq_Rel=as.numeric(fi),
    Freq_Ass_Cum=as.numeric(Ni),
    Freq_Rel_cum=as.numeric(Fi)
  )
  
  return(tab_freq)
}

distr_freq_city<-calcola.freq(city)
distr_freq_month<-calcola.freq(month)
distr_freq_year<-calcola.freq(year)

Le tre variabili categoriche sono equamente distribuite, il dataset è stato costruito con una distribuzione uniforme tra le categorie.

La variabile con la maggiore variabilità è “median_price” con una deviazione standard di 22662 e un IQR di 32750, segnalando una forte disomogeneità nei prezzi degli immobili e una distribuzione molto dispersa rispetto alla media. La variabile,invece, che presenta maggiore asimmetria è “volume” con un indice di Fisher pari a 0.88474203. Questo suggerisce che alcuni mesi hanno volumi di vendita eccezionalmente alti rispetto agli altri.

Divido median_price in 3 classi di ampiezza 35400 perchè è la variabile con il range più alto e la maggiore variabilità.

ampiezza<-(max(median_price)-min(median_price))/3
ampiezza
## [1] 35400
breaks <- seq(min(median_price), max(median_price), ampiezza)
labels <- paste0("[", round(head(breaks, -1), 0), " - ", round(tail(breaks, -1), 0), "]")

median_price_cl<- cut(median_price, breaks = breaks, 
                         include.lowest = TRUE, labels=labels)

                    
median_price_cl
##   [1] [144600 - 180000] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##   [5] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##   [9] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
##  [13] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [17] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [21] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [25] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [29] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [33] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [37] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [41] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [45] [144600 - 180000] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [49] [73800 - 109200]  [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [53] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [57] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
##  [61] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [65] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [69] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [73] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [77] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [81] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [85] [109200 - 144600] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [89] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [93] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
##  [97] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [101] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [105] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [109] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [113] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [117] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [121] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [125] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [129] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [133] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [137] [109200 - 144600] [144600 - 180000] [109200 - 144600] [144600 - 180000]
## [141] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [145] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [149] [109200 - 144600] [144600 - 180000] [144600 - 180000] [109200 - 144600]
## [153] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [157] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [161] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [165] [144600 - 180000] [144600 - 180000] [109200 - 144600] [109200 - 144600]
## [169] [109200 - 144600] [144600 - 180000] [109200 - 144600] [144600 - 180000]
## [173] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [177] [144600 - 180000] [109200 - 144600] [144600 - 180000] [144600 - 180000]
## [181] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [185] [73800 - 109200]  [109200 - 144600] [73800 - 109200]  [73800 - 109200] 
## [189] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [109200 - 144600]
## [193] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [109200 - 144600]
## [197] [109200 - 144600] [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [201] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [205] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [209] [73800 - 109200]  [109200 - 144600] [109200 - 144600] [73800 - 109200] 
## [213] [73800 - 109200]  [73800 - 109200]  [109200 - 144600] [73800 - 109200] 
## [217] [73800 - 109200]  [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [221] [109200 - 144600] [73800 - 109200]  [73800 - 109200]  [73800 - 109200] 
## [225] [109200 - 144600] [109200 - 144600] [73800 - 109200]  [109200 - 144600]
## [229] [73800 - 109200]  [109200 - 144600] [73800 - 109200]  [73800 - 109200] 
## [233] [109200 - 144600] [109200 - 144600] [73800 - 109200]  [73800 - 109200] 
## [237] [73800 - 109200]  [109200 - 144600] [73800 - 109200]  [73800 - 109200] 
## Levels: [73800 - 109200] [109200 - 144600] [144600 - 180000]
distr_freq_median_price_cl<-calcola.freq(median_price_cl)

Per vedere quanta informazione perdo raggruppando il prezzo mediano in sole tre classi faccio il confronto suddividendo anche in 11 classi.

?nclass.FD
## avvio in corso del server httpd per la guida ... fatto
num_classi <- nclass.FD(median_price)  
breaks <- seq(min(median_price), max(median_price), length.out = num_classi + 1)
labels_cl <- paste0("[", round(head(breaks, -1)), " - ", round(tail(breaks, -1)), "]")

median_price_cl2 <- cut(median_price, breaks = breaks, include.lowest = TRUE, labels = labels_cl)

distr_freq_median_price_cl2<-calcola.freq(median_price_cl2)

Creo grafico a barre per la distribuzione di frequenza:

library(ggplot2)

ggplot()+
  geom_bar(aes(x=median_price_cl2), 
           fill="steelblue", col="black")+
  labs(title = "Prezzo Mediano mensile di Vendita degli immobili in Texas (2010-2014)",
       subtitle = "Distribuzione di Frequenza delle Classi",
       x="Prezzo Mediano ($)",
       y="Frequenza")+
  scale_y_continuous(breaks=seq(0, 50, 5)) + 
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Il valore della y rappresenta il numero di mesi (sulle 240 osservazioni totali) in cui il prezzo mediano è ricaduto in quell’intervallo; le classi con più alta frequenza indicano gli intervalli di prezzo più comuni: il prezzo mediano di vendita piu frequente è compreso tra i 131727 e 141382$.

#misurare la disuguaglianza tra le classi di prezzo
gini.index<-function(x){
  ni=table(x)
  fi=ni/length(x)
  fi2=fi^2
  J=length(table(x))
  gini = 1-sum(fi2)
  gini.normalizzato = gini/((J-1)/J)
  return(gini.normalizzato)
}

gini.index(median_price_cl2)
## [1] 0.9668542

L’indice di Gini calcolato per la distribuzione delle classi di prezzo mediano è 0.96 (la massima eterogeneità si avrebbe per gini.index=1), indicando un’elevata eterogeneità nella distribuzione dei prezzi tra le fasce di prezzo. Questo valore suggerisce che le osservazioni sono distribuite in modo abbastanza uniforme tra le classi, senza una forte concentrazione in una sola categoria.

Questo risultato è coerente col grafico delle distribuzioni di frequenza: le classi centrali (tra 131.727 e 160.691 dollari ) presentano le frequenze più elevate, indicando che la maggior parte dei mesi ha avuto un prezzo mediano compreso in questa fascia. Tuttavia, esistono anche classi con frequenze molto basse segnalando che alcuni mesi hanno registrato prezzi significativamente diversi rispetto alla media.

p_Beaumont<-sum(city=="Beaumont")/nrow(data)
p_Beaumont
## [1] 0.25
library(dplyr)
## Warning: il pacchetto 'dplyr' è stato creato con R versione 4.2.3
## 
## Caricamento pacchetto: 'dplyr'
## I seguenti oggetti sono mascherati da 'package:stats':
## 
##     filter, lag
## I seguenti oggetti sono mascherati da 'package:base':
## 
##     intersect, setdiff, setequal, union
p_July<-sum(month=="July")/nrow(data)
subset_July<-data%>% filter(month=="July")
p_July
## [1] 0.08333333
subset_dec_2012 <- data %>% filter(month == "December", year == 2012)
subset_dec_2012
##                    city year    month sales volume median_price listings
## 1              Beaumont 2012 December   160 25.714       134700     1570
## 2 Bryan-College Station 2012 December   134 22.887       148400     1442
## 3                 Tyler 2012 December   234 36.965       140000     2633
## 4         Wichita Falls 2012 December   115 11.820        87500      801
##   months_inventory
## 1              9.1
## 2              7.3
## 3             10.0
## 4              7.1
p_Dec_2012<-sum((month=="December")& (year==2012))/nrow(data)
p_Dec_2012
## [1] 0.01666667

La probabilità che presa a caso una riga dal dataset questa riporti Beaumont è del 25%, quella che riporti il mese di luglio è dell’8% mentre quella che esce una riga di dicembre 2012 è dell’1,6 %.

Creo la variabile per osservare il prezzo medio, espressa in centinaia di migliaia di dollari.

options(scipen = 999)
data$avg_price<-(volume*1e6)/sales

str(data)
## 'data.frame':    240 obs. of  9 variables:
##  $ city            : chr  "Beaumont" "Beaumont" "Beaumont" "Beaumont" ...
##  $ year            : int  2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
##  $ month           : Factor w/ 12 levels "January","February",..: 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 ...
##  $ avg_price       : num  170627 163796 157698 134095 142738 ...
head(data$avg_price)
## [1] 170626.5 163796.3 157697.8 134095.0 142737.6 144015.9

Creo una misura per l’efficacia degli annunci di vendita (scala 0-1)

data$efficacy<-(sales/listings)
head(data$efficacy)
## [1] 0.05414220 0.06809584 0.10775607 0.11709602 0.11405985 0.10482529
#confronto variabili
summary(data$avg_price)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   97010  132939  156588  154320  173915  213234
summary(data$efficacy)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.05014 0.08980 0.10963 0.11874 0.13492 0.38713
summary(data$median_price)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   73800  117300  134500  132665  150050  180000

L’efficacia delle vendite (efficacy) ha una media del 11.87% e una mediana del 10.96%, quindi nella maggior parte dei casi meno del 12% degli annunci porta effettivamente a una vendita. Il massimo (38.71%) suggerisce che in alcune aree o periodi le vendite sono molto più rapide ed efficaci, mentre in altri casi (minimo 5%) il mercato è più stagnante.

Il prezzo medio è sempre superiore a al prezzo mediano, il che è atteso perché la media può essere influenzata da vendite molto alte (outliers).

Provo un grafico di confronto per vedere il prezzo medio e quello mediano nelle quattro città.

ggplot(data, aes(x = city)) +
  geom_boxplot(aes(y = median_price, fill = "Median Price"), alpha = 0.5) +
  geom_boxplot(aes(y = avg_price, fill = "Avg Price"), alpha = 0.5) +
  labs(title = "Confronto tra Prezzo Mediano e Prezzo Medio per Città",
       x = "Città", y = "Prezzo ($)") +
  scale_fill_manual(values = c("Median Price" = "steelblue", "Avg Price" = "yellow2")) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))+
  theme_minimal()+
  guides(fill = guide_legend(title = NULL))

Bryan-College Station mostra la maggiore varianza nei prezzi.

Creo un grafico anche per il confronto tra le vendite e l’efficacia degli annunci.

#ridefinisco e inserisco nel dataset la var che avevo creato divisa in 3 classi
data$median_price_cl <- cut(data$median_price,
                            breaks = c(73800, 109200, 144600, 180000), 
                            include.lowest = TRUE,
                            labels = c("Basso", "Medio", "Alto"))


#verificare le differenze tra città

ggplot(data, aes(x = median_price_cl, y = efficacy * 100, fill = city)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_manual(values = c("Beaumont" = "indianred",   
                               "Bryan-College Station" = "darkseagreen",  
                               "Tyler" = "thistle",      
                               "Wichita Falls" = "slategrey")) +  
  labs(title = "Efficacia degli Annunci Pubblicitari per Fasce di Prezzo Mediano e Città",
       x = "Fasce di Prezzo (Prezzo Mediano)",
       y = "Efficacia  (%)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

La variazione dell’efficacia tra città suggerisce che in alcuni mercati, come Bryan-College Station, le case più costose possono avere un’efficacia di vendita molto variabile, mentre in altre città l’efficacia è più stabile tra le fasce di prezzo.

Creo un box plot per confrontare la distribuzione delle vendite negli anni per le quattro città.

ggplot(data, aes(x = factor(year), y = sales, fill = city)) +
  geom_boxplot() +
  scale_fill_manual(values = c("Beaumont" = "indianred",  
                               "Bryan-College Station" = "darkseagreen",  
                               "Tyler" = "thistle",      # Steelblue
                               "Wichita Falls" = "slategrey")) +  # Slategray
  labs(title = "Distribuzione delle Vendite per Anno e Città",
       x = "Anno", y = "Numero di Vendite") +
  theme_minimal()

Il grafico evidenzia variazioni significative tra le città e una tendenza all’aumento delle vendite nel tempo, con un incremento particolarmente marcato dal 2012 al 2014. Bryan-College Station e Tyler hanno una maggiore variabilità e un numero di vendite più elevato rispetto alle altre città. Confrontando il risultato con il grafico precedente sull’efficacia si può ipotizzare che gli anni con vendite più alte (es. 2013-2014) abbiano risentito dellàimpatto dellàefficacia degli annunci, specialmente per le case più costose. Nella città di Wichita Falls, la bassa efficacia potrebbe spiegare le vendite più contenute nel tempo.

library(dplyr)
library(reshape2)
## Warning: il pacchetto 'reshape2' è stato creato con R versione 4.2.3
summary_city <- data %>%
  group_by(city) %>%
  summarise(
    mean_sales = mean(sales),
    sd_sales = sd(sales),
    mean_price = mean(median_price),
    sd_price = sd(median_price),
    mean_volume = mean(volume),
    sd_volume = sd(volume))

summary_city
## # A tibble: 4 × 7
##   city             mean_sales sd_sales mean_price sd_price mean_volume sd_volume
##   <chr>                 <dbl>    <dbl>      <dbl>    <dbl>       <dbl>     <dbl>
## 1 Beaumont               177.     41.5    129988.   10105.        26.1      6.97
## 2 Bryan-College S…       206.     85.0    157488.    8852.        38.2     17.2 
## 3 Tyler                  270.     62.0    141442.    9337.        45.8     13.1 
## 4 Wichita Falls          116.     22.2    101743.   11320.        13.9      3.24
standardize <- function(x) {
  return((x - mean(x)) / sd(x))
}

summary_city$mean_sales_st<-standardize(summary_city$mean_sales)
summary_city$mean_price_st<-standardize(summary_city$mean_price)
summary_city$mean_volume_st<-standardize(summary_city$mean_volume)

summary_year <- data %>%
  group_by(year) %>%
  summarise(
    mean_sales = mean(sales),
    sd_sales = sd(sales),
    mean_price = mean(median_price),
    sd_price = sd(median_price),
    mean_volume = mean(volume),
    sd_volume = sd(volume)
  )


summary_month <- data %>%
  group_by(month) %>%
  summarise(
    mean_sales = mean(sales),
    sd_sales = sd(sales),
    mean_price = mean(median_price),
    sd_price = sd(median_price),
    mean_volume = mean(volume),
    sd_volume = sd(volume)
  )

summary_year$mean_sales_st<-standardize(summary_year$mean_sales)
summary_year$mean_price_st<-standardize(summary_year$mean_price)
summary_year$mean_volume_st<-standardize(summary_year$mean_volume)


ggplot(summary_year, aes(x = year)) +
  geom_line(aes(y = mean_sales_st, color = "Vendite"), lwd = 1) +
  geom_line(aes(y = mean_price_st, color = "Prezzo Mediano"), lwd = 1) +
  #geom_line(aes(y = mean_volume_st, color = "Volume"), lwd = 1) +
  geom_point(aes(y = mean_sales_st), color = "red", size = 3) +
  geom_point(aes(y = mean_price_st), color = "steelblue", size = 3) +
  #geom_point(aes(y = mean_volume_st), color = "green4", size = 3) +
  labs(
    title = "Andamento Standardizzato di Vendite e Prezzo nel Tempo",
    x = "Anno",
    y = "Valore Standardizzato",
    color = NULL 
  ) +
  scale_color_manual(
    values = c("Vendite" = "red", "Prezzo Mediano" = "steelblue")#, "Volume" = "green4")
  ) +
  guides(color = guide_legend(title = NULL)) +  
  theme_minimal() +
  scale_x_continuous(breaks = unique(summary_year$year))+
  scale_y_continuous(limits = c(-2, 3), breaks = seq(-2, 3, by = 1)) #+

  #geom_text(aes(y = mean_sales_st -0.5, label = round(mean_sales_st, 2)), color = "red4", size = 3) +
  #geom_text(aes(y = mean_price_st +0.5, label = round(mean_price_st, 2)), color = "blue4", size = 3) #+
  #geom_text(aes(y = mean_volume_st + 1.5, label = round(mean_volume_st, 2)), color = "green4", size = 3)

Dopo aver standardizzato le variabili per renderle confrontabili, ho deciso di escludere dal grafico il volume delle vendite, poiché esso risulta strettamente correlato al numero di vendite e non aggiunge informazioni significative. Tra il 2010 e il 2011, sia il prezzo mediano che il numero di vendite mostrano un andamento negativo, con un calo più marcato del prezzo che dal 2012 ha invece un aumento più significativo, mentre l’incremento delle vendite rimane costante dal 2011. Nel 2010, 2011, 2012 si osservano valori di prezzo e vendite inferiori alla media.

Creo un dataset aggregato per città mese e anno e visualizzo il totale delle vendite Ogni segmento rappresenta un anno in ordine temporale.

summary_month_city_year <- data %>%
  group_by(year, month, city) %>%
  summarise(
    mean_sales = mean(sales, na.rm = TRUE), 
    .groups = "drop"
  )

#summary_month_city_year$mean_sales_st <- standardize(summary_month_city_year$mean_sales)

ggplot(data=summary_month_city_year, aes(x = month, y = mean_sales, 
                                         fill = city)) +
  geom_col(position = "stack", color="black") +
  scale_fill_manual(values = c("Beaumont" = "indianred",    
                               "Bryan-College Station" = "darkseagreen",
                               "Tyler" = "thistle",      
                               "Wichita Falls" = "slategrey")) +
  labs(
    title = "Totale delle Vendite per Mese e Città",
    x = "Mese",
    y = "Vendite Totali",
    fill = "Città"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Per rendere più chiaro il grafico creo un grafico a barre normalizzato.

summary_month_city_year <- summary_month_city_year %>%
  group_by(month) %>%
  mutate(percent_sales = mean_sales / sum(mean_sales))


ggplot(data = summary_month_city_year, aes(x = month, y = percent_sales, fill = city)) +
  geom_col(position = "fill", color = "black") +  # "fill" normalizza le altezze a 1 (100%)
  scale_fill_manual(values = c("Beaumont" = "indianred",    
                               "Bryan-College Station" = "darkseagreen",
                               "Tyler" = "thistle",      
                               "Wichita Falls" = "slategrey")) +
  labs(
    title = "Distribuzione Percentuale delle Vendite per Mese e Città",
    x = "Mese",
    y = "Quota di Vendite (%)",
    fill = "Città"
  ) +
  scale_y_continuous(labels = scales::percent_format()) +  # Mostra asse Y in percentuale
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Come già evidenziato dai grafici precedenti Wichita Falls mantiene una quota di mercato inferiore rispetto alle altre città. Si evidenzia stagionalità nelle vendite.

Infine, provo a visualizzare una serie storica del numero totale di vendite negli anni.

library(lubridate)  
## Warning: il pacchetto 'lubridate' è stato creato con R versione 4.2.3
## 
## Caricamento pacchetto: 'lubridate'
## I seguenti oggetti sono mascherati da 'package:base':
## 
##     date, intersect, setdiff, union
data$date <- as.Date(paste(data$year, match(data$month, month.name), "1", sep = "-"))


ggplot(data, aes(x = date, y = sales, col = city)) +
  geom_line(linewidth = 0.5) +  
  geom_point(size = 1) +
  scale_color_manual(values = c("Beaumont" = "indianred",    
                               "Bryan-College Station" = "darkseagreen",
                               "Tyler" = "thistle",      
                               "Wichita Falls" = "slategrey")) +
  labs(
    title = "Andamento delle Vendite Immobiliari (2010-2014)",
    x = "Anno",
    y = "Numero di Vendite",
    color = "Città"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
 # scale_x_date(date_labels = "%b %Y", date_breaks = "6 months") 
  scale_x_date(date_labels = "%Y", date_breaks = "1 year") 

max(data$sales)
## [1] 423
min(data$sales)
## [1] 79
data[data$sales == min(data$sales), ]
##              city year    month sales volume median_price listings
## 194 Wichita Falls 2011 February    79  8.747        90800      950
## 217 Wichita Falls 2013  January    79  9.666        99300      854
##     months_inventory avg_price   efficacy median_price_cl       date
## 194              7.8  110721.5 0.08315789           Basso 2011-02-01
## 217              7.7  122354.4 0.09250585           Basso 2013-01-01
data[data$sales == max(data$sales), ]
##      city year month sales volume median_price listings months_inventory
## 174 Tyler 2014  June   423 80.814       155700     2855              9.3
##     avg_price  efficacy median_price_cl       date
## 174  191049.6 0.1481611            Alto 2014-06-01

La città di Tyler ha raggiunto il numero maggiore di vendite, con un totale di 423 immobili venduti a Giugno 2014. La città di Wichita Falls ha, invece, registrato il minor numero di vendite (79) sia a Gennaio 2013 che a Febbraio 2011.

CONCLUSIONI L’andamento mensile mostra una chiara stagionalità, con picchi di vendite nei mesi estivi e una riduzione nei mesi invernali.

Il trend di crescita del prezzo mediano è più marcato rispetto a quello del numero di vendite. Questo potrebbe suggerire una crescente domanda che ha fatto aumentare i prezzi, oppure una riduzione dell’offerta, portando a un incremento dei valori immobiliari.

L’analisi dell’efficacia degli annunci di vendita ha evidenziato significative differenze tra città e fasce di prezzo. Alcuni mercati si distinguono per un’attività più dinamica, sia in termini di volume di vendite che di prezzo mediano mentre, in particolare Wichita Falls si distingue per la minore efficacia degli annunci e una domanda immobiliare meno sostenuta. Bryan-College Station mostra la maggiore variabilità e i valori più alti di efficacia, indicando una forte domanda e una gestione più efficiente delle vendite. Beaumont si posiziona in una situazione intermedia, con un mercato più stabile e meno soggetto a variazioni estreme.