knitr::opts_chunk$set(
echo = TRUE,
eval = TRUE,
include = TRUE,
message = FALSE,
warning = FALSE
)
library(dplyr)
library(ggplot2)
dati <- read.csv("realestate_texas.csv", sep = ",")
head(dati)
## 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
## 6 Beaumont 2010 6 189 27.219 122800 1803 11.1
str(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 ...
summary(dati)
## city year month sales
## Length:240 Min. :2010 Min. : 1.00 Min. : 79.0
## Class :character 1st Qu.:2011 1st Qu.: 3.75 1st Qu.:127.0
## Mode :character Median :2012 Median : 6.50 Median :175.5
## Mean :2012 Mean : 6.50 Mean :192.3
## 3rd Qu.:2013 3rd Qu.: 9.25 3rd Qu.:247.0
## Max. :2014 Max. :12.00 Max. :423.0
## volume median_price listings months_inventory
## Min. : 8.166 Min. : 73800 Min. : 743 Min. : 3.400
## 1st Qu.:17.660 1st Qu.:117300 1st Qu.:1026 1st Qu.: 7.800
## Median :27.062 Median :134500 Median :1618 Median : 8.950
## Mean :31.005 Mean :132665 Mean :1738 Mean : 9.193
## 3rd Qu.:40.893 3rd Qu.:150050 3rd Qu.:2056 3rd Qu.:10.950
## Max. :83.547 Max. :180000 Max. :3296 Max. :14.900
Il dataset contiene informazioni sul mercato immobiliare in diverse città del Texas, con dati mensili relativi a vendite, volume, prezzi e offerta.
In questa sezione le variabili del dataset vengono classificate in base alla loro tipologia statistica e viene illustrato il tipo di analisi appropriata per ciascuna di esse.
Le variabili presenti nel dataset sono di diversa natura:
Le variabili temporali permettono analisi di trend e stagionalità, mentre le variabili quantitative consentono il calcolo di indici descrittivi e confronti tra città.
In questa sezione vengono calcolati gli indici descrittivi per le variabili quantitative del dataset.
In particolare: - Media e mediana (indici di posizione) - Deviazione standard e IQR (indici di variabilità) - Skewness (indice di forma) - Kurtosis Per le variabili qualitative verranno invece calcolate distribuzioni di fre-quenza.
library(moments)
indici <- data.frame(
variabile = c("sales","volume","median_price","listings","months_inventory"),
media = c(mean(dati$sales),
mean(dati$volume),
mean(dati$median_price),
mean(dati$listings),
mean(dati$months_inventory)),
mediana = c(median(dati$sales),
median(dati$volume),
median(dati$median_price),
median(dati$listings),
median(dati$months_inventory)),
sd = c(sd(dati$sales),
sd(dati$volume),
sd(dati$median_price),
sd(dati$listings),
sd(dati$months_inventory)),
IQR = c(IQR(dati$sales),
IQR(dati$volume),
IQR(dati$median_price),
IQR(dati$listings),
IQR(dati$months_inventory)),
skewness = c(skewness(dati$sales),
skewness(dati$volume),
skewness(dati$median_price),
skewness(dati$listings),
skewness(dati$months_inventory)),
kurtosis = c(kurtosis(dati$sales),
kurtosis(dati$volume),
kurtosis(dati$median_price),
kurtosis(dati$listings),
kurtosis(dati$months_inventory))
)
indici$CV <- indici$sd / indici$media
indici
## variabile media mediana sd IQR skewness
## 1 sales 192.29167 175.5000 79.651111 120.0000 0.71810402
## 2 volume 31.00519 27.0625 16.651447 23.2335 0.88474203
## 3 median_price 132665.41667 134500.0000 22662.148687 32750.0000 -0.36455288
## 4 listings 1738.02083 1618.5000 752.707756 1029.5000 0.64949823
## 5 months_inventory 9.19250 8.9500 2.303669 3.1500 0.04097527
## kurtosis CV
## 1 2.686824 0.4142203
## 2 3.176987 0.5370536
## 3 2.377038 0.1708218
## 4 2.208210 0.4330833
## 5 2.825552 0.2506031
table(dati$city)
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
table(dati$year)
##
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
table(dati$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
ggplot(dati, aes(x = city)) +
geom_bar(fill = "lightblue") +
theme_classic() +
labs(title = "Distribuzione delle osservazioni per città",
x = "Città",
y = "Frequenza") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Dalla tabella si osserva che:
La combinazione tra CV, skewness e kurtosis consente di valutare contemporaneamente stabilità, asimmetria e presenza di valori anomali.
Le distribuzioni di frequenza mostrano che:
Ogni città è rappresentata con lo stesso numero di osservazioni (60), indicando un dataset bilanciato rispetto alla variabile city.
Anche gli anni risultano equamente distribuiti (48 osservazioni per anno).
I mesi sono distribuiti uniformemente (20 osservazioni per ciascun mese), garantendo una copertura temporale completa e omogenea.
Il grafico per city conferma che il dataset è bilanciato rispetto alla variabile city, con lo stesso numero di osservazioni per ciascuna città.
In questa sezione si analizza: - la variabile con maggiore variabilità relativa (CV massimo) - la variabile con distribuzione più asimmetrica (|skewness| massimo)
var_max_cv <- indici$variabile[which.max(indici$CV)]
var_max_sk <- indici$variabile[which.max(abs(indici$skewness))]
var_max_cv
## [1] "volume"
var_max_sk
## [1] "volume"
La variabile con coefficiente di variazione (CV) massimo presenta la maggiore variabilità relativa, ossia una dispersione più elevata in rapporto al proprio valore medio.
La variabile con valore assoluto della skewness più elevato è quella che mostra il maggiore grado di asimmetria, indicando una distribuzione caratterizzata da una coda più pronunciata e dalla presenza di valori relativamente più distanti dalla media.
Si seleziona la variabile sales e si suddivide in 5 classi. Viene costruita la distribuzione di frequenza e viene rappresentata con un grafico a barre. Si calcola infine l’indice di eterogeneità di Gini sulle classi ottenute.
# Creazione classi per sales
dati$classi_sales <- cut(dati$sales, breaks = 5)
# Distribuzione di frequenza
frequenze_sales <- table(dati$classi_sales)
frequenze_sales
##
## (78.7,148] (148,217] (217,285] (285,354] (354,423]
## 84 77 41 27 11
prop.table(frequenze_sales)
##
## (78.7,148] (148,217] (217,285] (285,354] (354,423]
## 0.35000000 0.32083333 0.17083333 0.11250000 0.04583333
barplot(frequenze_sales,
main = "Distribuzione di sales in 5 classi",
xlab = "Classi di sales",
ylab = "Frequenza",
col = "lightblue",
las = 2)
## Gini
gini.index <- function(x){
ni <- table(x)
fi <- ni / length(x)
J <- length(ni)
gini <- 1 - sum(fi^2)
gini.normalizzato <- gini / ((J-1)/J)
return(gini.normalizzato)
}
gini_sales <- gini.index(dati$classi_sales)
gini_sales
## [1] 0.9132812
L’indice di Gini normalizzato misura il grado di eterogeneità della distribuzione tra le classi.
Un valore vicino a 1 indica forte concentrazione delle osservazioni in alcune classi, mentre un valore vicino a 0 indica distribuzione più uniforme.
Il valore ottenuto suggerisce il livello di concentrazione delle vendite all’interno delle classi individuate.
Si calcolano le probabilità richieste come frequenze relative nel dataset:
prob_beaumont <- mean(dati$city == "Beaumont")
prob_luglio <- mean(dati$month == 7)
prob_dic2012 <- mean(dati$year == 2012 & dati$month == 12)
prob_beaumont
## [1] 0.25
prob_luglio
## [1] 0.08333333
prob_dic2012
## [1] 0.01666667
Queste probabilità rappresentano la quota di osservazioni del dataset che soddisfa ciascuna condizione (interpretazione frequentista).
Il dataset non contiene i prezzi delle singole abitazioni, ma solo: - il volume totale delle vendite (in milioni di dollari) - il numero di vendite effettuate nel periodo
Non è quindi possibile calcolare la vera media dei prezzi individuali. È tuttavia possibile stimare un prezzo medio per transazione come rapporto tra volume totale e numero di vendite.
dati$price_estimate <- ifelse(dati$sales > 0,
(dati$volume * 1e6) / dati$sales,
NA_real_)
summary(dati$price_estimate)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 97010 132939 156588 154320 173915 213234
L’efficacia degli annunci è definita come il rapporto tra vendite concluse e annunci attivi:
dati$efficacia_annunci <- ifelse(dati$listings > 0,
dati$sales / dati$listings,
NA_real_)
summary(dati$efficacia_annunci)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.05014 0.08980 0.10963 0.11874 0.13492 0.38713
Si misura l’efficacia degli annunci come rapporto tra vendite concluse e annunci attivi. Valori più alti indicano un mercato dinamico e una maggiore capacità di assorbire l’offerta, mentre valori più bassi suggeriscono eccesso di offerta o maggiore difficoltà di vendita.
Vengono calcolate statistiche condizionate per città e anno (media e deviazione standard) su variabili chiave.
summary_city_year <- dati %>%
group_by(city, year) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
mean_volume = mean(volume),
sd_volume = sd(volume),
mean_price = mean(median_price),
sd_price = sd(median_price),
mean_inventory = mean(months_inventory),
sd_inventory = sd(months_inventory),
.groups = "drop"
)
summary_city_year
## # A tibble: 20 × 10
## city year mean_sales sd_sales mean_volume sd_volume mean_price sd_price
## <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Beaumont 2010 156. 36.9 22.7 4.95 133117. 13354.
## 2 Beaumont 2011 144 22.7 21.1 4.30 125642. 9603.
## 3 Beaumont 2012 172. 28.4 24.5 4.92 126533. 7973.
## 4 Beaumont 2013 201. 37.7 30.3 6.44 132400 7785.
## 5 Beaumont 2014 214. 36.5 32.1 7.05 132250 9835.
## 6 Bryan-Co… 2010 168. 70.8 28.7 10.8 153533. 5474.
## 7 Bryan-Co… 2011 167. 62.2 28.9 10.3 151417. 3709.
## 8 Bryan-Co… 2012 197. 74.3 35.4 13.5 153567. 7096.
## 9 Bryan-Co… 2013 238. 95.8 45.1 19.5 159392. 5429.
## 10 Bryan-Co… 2014 260. 86.7 52.8 18.0 169533. 7776.
## 11 Tyler 2010 228. 49.0 36.3 8.39 135175 4782.
## 12 Tyler 2011 239. 49.6 38.6 9.41 136217. 8505.
## 13 Tyler 2012 264. 46.4 44.0 10.2 139250 7983.
## 14 Tyler 2013 287. 53.0 50.3 10.3 146100 6726.
## 15 Tyler 2014 332. 56.9 59.6 12.8 150467. 8543.
## 16 Wichita … 2010 123. 26.6 15.0 4.07 98942. 10361.
## 17 Wichita … 2011 106. 19.8 12.1 2.52 98142. 10632.
## 18 Wichita … 2012 112. 14.2 13.2 2.66 100958. 12347.
## 19 Wichita … 2013 121. 26.0 14.9 3.11 105000 10383.
## 20 Wichita … 2014 117 21.1 14.5 3.13 105675 12444.
## # ℹ 2 more variables: mean_inventory <dbl>, sd_inventory <dbl>
summary_city_month <- dati %>%
group_by(city, month) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
.groups = "drop"
)
summary_city_month
## # A tibble: 48 × 4
## city month mean_sales sd_sales
## <chr> <int> <dbl> <dbl>
## 1 Beaumont 1 122. 31.2
## 2 Beaumont 2 135. 31.9
## 3 Beaumont 3 171 14.9
## 4 Beaumont 4 190. 17.7
## 5 Beaumont 5 207. 42.6
## 6 Beaumont 6 205 36.0
## 7 Beaumont 7 185. 22.9
## 8 Beaumont 8 217. 50.6
## 9 Beaumont 9 174 46.9
## 10 Beaumont 10 189. 44.0
## # ℹ 38 more rows
ggplot(summary_city_month, aes(x = factor(month), y = mean_sales, color = city, group = city)) +
geom_line() +
geom_point() +
theme_classic() +
labs(title = "Vendite medie per mese (media su tutti gli anni) per città",
x = "Mese", y = "Sales medio", color = "Città")
Questa tabella consente di confrontare i mercati (città) e i periodi (anni) evidenziando livelli medi e stabilità: deviazioni standard più alte indicano maggiore variabilità nel tempo.
summary_city_year_month <- dati %>%
group_by(city, year, month) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
mean_volume = mean(volume),
.groups = "drop"
)
summary_city_year_month
## # A tibble: 240 × 6
## city year month mean_sales sd_sales mean_volume
## <chr> <int> <int> <dbl> <dbl> <dbl>
## 1 Beaumont 2010 1 83 NA 14.2
## 2 Beaumont 2010 2 108 NA 17.7
## 3 Beaumont 2010 3 182 NA 28.7
## 4 Beaumont 2010 4 200 NA 26.8
## 5 Beaumont 2010 5 202 NA 28.8
## 6 Beaumont 2010 6 189 NA 27.2
## 7 Beaumont 2010 7 164 NA 22.7
## 8 Beaumont 2010 8 174 NA 25.2
## 9 Beaumont 2010 9 124 NA 17.2
## 10 Beaumont 2010 10 150 NA 23.9
## # ℹ 230 more rows
Per la combinazione (city, year, month) è presente una sola osservazione per gruppo; di conseguenza la deviazione standard non è calcolabile e risulta NA.
ggplot(dati, aes(x = city, y = median_price)) +
geom_boxplot() +
theme_classic() +
labs(title = "Distribuzione del prezzo mediano (median_price) per città",
x = "Città", y = "Prezzo mediano ($)") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
### 8.2 Boxplot: confronto del volume tra città e anni
ggplot(dati, aes(x = city, y = volume)) +
geom_boxplot() +
facet_wrap(~ year) +
theme_classic() +
labs(title = "Distribuzione del volume (milioni $) per città e anno",
x = "Città", y = "Volume (milioni $)") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
### 8.3 Barre stacked e normalizzate: totale vendite per mese e città
(con Year nello stesso blocco)
agg_sales_mese <- dati %>%
group_by(year, month, city) %>%
summarise(sales_tot = sum(sales), .groups = "drop")
ggplot(agg_sales_mese, aes(x = factor(month), y = sales_tot, fill = city)) +
geom_col() +
facet_wrap(~ year) +
theme_classic() +
labs(title = "Totale vendite (sales) per mese e città (stacked), separato per anno",
x = "Mese", y = "Vendite totali", fill = "Città")
### Stacked Normalizzato
ggplot(agg_sales_mese, aes(x = factor(month), y = sales_tot, fill = city)) +
geom_col(position = "fill") +
facet_wrap(~ year) +
theme_classic() +
labs(title = "Totale vendite per mese (normalizzato), separato per anno",
x = "Mese", y = "Proporzione", fill = "Città")
Viene usato geom_col() perché vengono rappresentati valori già aggregati (sales_tot). geom_bar() invece calcola conteggi automaticamente.
dati$date <- as.Date(paste(dati$year, dati$month, "01", sep = "-"))
agg_sales_time <- dati %>%
group_by(date, city) %>%
summarise(sales_tot = sum(sales), .groups = "drop") %>%
arrange(city, date)
ggplot(agg_sales_time, aes(x = date, y = sales_tot, color = city)) +
geom_line() +
theme_classic() +
labs(title = "Andamento delle vendite (sales) nel tempo per città",
x = "Tempo", y = "Vendite totali", color = "Città")
8.1 Boxplot – Prezzo mediano per città
Il boxplot evidenzia differenze strutturali tra i mercati locali. Bryan–College Station presenta una mediana più elevata rispetto alle altre città, mentre Wichita Falls mostra livelli sistematicamente inferiori. Tyler e Beaumont si collocano in posizione intermedia.
La diversa ampiezza dell’IQR indica una variabilità differente dei prezzi tra città. La presenza di alcuni outlier segnala mesi o anni caratterizzati da condizioni di mercato particolarmente favorevoli o atipiche.
8.2 Boxplot – Volume per città e anno
Il confronto per anno mostra un’evoluzione temporale del volume totale delle vendite. In diversi casi si osserva un aumento del livello centrale negli anni più recenti, in particolare per Tyler e Bryan–College Station.
L’ampiezza delle scatole e delle whiskers suggerisce una maggiore dispersione negli anni finali, coerente con il valore elevato del coefficiente di variazione del volume. Questo indica che l’intensità economica del mercato diventa progressivamente più variabile nel tempo.
8.3 Barre stacked – Totale vendite per mese e città
Il grafico stacked in valori assoluti evidenzia chiaramente la stagionalità delle vendite: i mesi primaverili ed estivi presentano livelli complessivi più elevati rispetto ai mesi autunnali e invernali.
Si osserva inoltre che Tyler e Bryan–College Station contribuiscono in misura maggiore al totale nei mesi di picco, confermando il loro ruolo più dinamico nel mercato complessivo.
8.3 Barre normalizzate (position = “fill”)
La versione normalizzata consente di confrontare le quote percentuali delle città, indipendentemente dal livello totale delle vendite.
La struttura percentuale appare nel complesso relativamente stabile nel tempo, pur con alcune variazioni nei singoli anni. Questo suggerisce che le differenze tra città sono in parte strutturali e non esclusivamente legate alla stagionalità.
8.4 Line chart – Andamento vendite nel tempo
Il grafico temporale evidenzia una chiara componente ciclica con picchi ricorrenti nei mesi centrali dell’anno.
Tyler mostra un trend complessivamente crescente nel periodo 2010–2014, con oscillazioni più ampie rispetto alle altre città. Bryan–College Station segue un andamento simile, mentre Wichita Falls presenta livelli più contenuti e una dinamica relativamente più stabile.
Le differenze persistenti tra le linee indicano mercati locali con intensità strutturalmente differenti.
L’analisi del dataset nel periodo 2010–2014 evidenzia un mercato immobiliare eterogeneo tra città e caratterizzato da una chiara componente stagionale.
Dal punto di vista descrittivo, la variabile volume risulta la più instabile in termini relativi (CV = 0.537) e anche la più asimmetrica (skewness = 0.885). Ciò indica che l’intensità economica del mercato oscilla proporzionalmente più del numero di transazioni e presenta periodi con valori particolarmente elevati, coerenti con i picchi osservati nei grafici temporali.
La distribuzione delle vendite in classi mostra una forte disuguaglianza tra frequenze (indice di Gini normalizzato = 0.913), con concentrazione nelle fasce medio-basse e una presenza meno frequente di livelli molto elevati. Questo suggerisce che i picchi di attività rappresentano eventi relativamente rari ma economicamente rilevanti.
L’analisi grafica evidenzia:
una stagionalità ricorrente, con livelli di vendita più elevati nei mesi primaverili ed estivi;
differenze strutturali tra città: Tyler e Bryan–College Station mostrano livelli medi più alti e maggiore dinamismo, mentre Wichita Falls presenta valori più contenuti e maggiore stabilità; Beaumont si colloca in posizione intermedia.
Gli indicatori costruiti (stima del prezzo medio per transazione e rapporto vendite/annunci) forniscono una lettura operativa del mercato, permettendo di valutare sia l’intensità economica sia la capacità di assorbimento dell’offerta.
Nel complesso, il mercato analizzato non risulta omogeneo, ma caratterizzato da dinamiche territoriali differenziate e da una componente ciclica significativa. Nei contesti più dinamici appare opportuno un monitoraggio frequente dell’andamento delle vendite; nei mercati più stabili possono essere adottate strategie più conservative e orientate al medio periodo.