Il dataset contiene le seguenti variabili:
Le variabili su cui ha senso calcolare gli indici numerici sono:
sales, volume, median_price,
listings e months_inventory. Per
city, year e month vengono create
distribuzioni di frequenza.
indici_stat = function(x, nome_var){
cat("Variabile:", nome_var, "\n")
cat("Minimo:", min(x, na.rm = T), "\n")
cat("Q1:", quantile(x, 0.25, na.rm = T), "\n")
cat("Mediana:", median(x, na.rm = T), "\n")
cat("Media:", mean(x, na.rm = T), "\n")
cat("Q3:", quantile(x, 0.75, na.rm = T), "\n")
cat("Massimo:", max(x, na.rm = T), "\n")
cat("Range:", max(x, na.rm = T)-min(x, na.rm = T), "\n")
cat("IQR:", IQR(x, na.rm = T), "\n")
cat("Dev. Standard:", sd(x, na.rm = T), "\n")
cat("Coeff. Variazione:", sd(x, na.rm = T)/mean(x, na.rm = T)*100, "\n")
cat("Assimmetria:", skewness(x, na.rm = T), "\n")
cat("Curtosi:", kurtosis(x, na.rm = T)-3, "\n")
}
indici_stat(sales, "Sales (Vendite)")
## Variabile: Sales (Vendite)
## Minimo: 79
## Q1: 127
## Mediana: 175.5
## Media: 192.2917
## Q3: 247
## Massimo: 423
## Range: 344
## IQR: 120
## Dev. Standard: 79.65111
## Coeff. Variazione: 41.42203
## Assimmetria: 0.718104
## Curtosi: -0.3131764
indici_stat(volume, "Volume (milioni $)")
## Variabile: Volume (milioni $)
## Minimo: 8.166
## Q1: 17.6595
## Mediana: 27.0625
## Media: 31.00519
## Q3: 40.893
## Massimo: 83.547
## Range: 75.381
## IQR: 23.2335
## Dev. Standard: 16.65145
## Coeff. Variazione: 53.70536
## Assimmetria: 0.884742
## Curtosi: 0.176987
indici_stat(median_price, "Median price ($)")
## Variabile: Median price ($)
## Minimo: 73800
## Q1: 117300
## Mediana: 134500
## Media: 132665.4
## Q3: 150050
## Massimo: 180000
## Range: 106200
## IQR: 32750
## Dev. Standard: 22662.15
## Coeff. Variazione: 17.08218
## Assimmetria: -0.3645529
## Curtosi: -0.6229618
indici_stat(listings, "Listings (Annunci)")
## Variabile: Listings (Annunci)
## Minimo: 743
## Q1: 1026.5
## Mediana: 1618.5
## Media: 1738.021
## Q3: 2056
## Massimo: 3296
## Range: 2553
## IQR: 1029.5
## Dev. Standard: 752.7078
## Coeff. Variazione: 43.30833
## Assimmetria: 0.6494982
## Curtosi: -0.79179
indici_stat(months_inventory,"Months inventory")
## Variabile: Months inventory
## Minimo: 3.4
## Q1: 7.8
## Mediana: 8.95
## Media: 9.1925
## Q3: 10.95
## Massimo: 14.9
## Range: 11.5
## IQR: 3.15
## Dev. Standard: 2.303669
## Coeff. Variazione: 25.06031
## Assimmetria: 0.04097527
## Curtosi: -0.1744475
freq_city = table(city); print(freq_city); prop.table(freq_city)
## city
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
## city
## Beaumont Bryan-College Station Tyler
## 0.25 0.25 0.25
## Wichita Falls
## 0.25
freq_year = table(year); print(freq_year)
## year
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
freq_month = table(month); print(freq_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
Commento: Il volume è la variabile con la variabilità più alta (CV ≈ 54%) e la distribuzione più asimmetrica (skewness ≈ 0.88), mentre il prezzo mediano è la variabile più stabile (CV ≈ 17%) e l’unica con asimmetria negativa (skewness ≈ -0.36). Il months inventory è la variabile più simmetrica in assoluto: skewness quasi zero e curtosi leggermente negativa indicano una distribuzione molto vicina alla normale.
Variabile con la più alta variabilità: Volume
Il confronto va fatto tramite il coefficiente di variazione (CV), poiché le variabili hanno unità di misura diverse. Il CV normalizza la dispersione sulla media, rendendola adimensionale e comparabile. Il volume presenta il CV più alto (≈ 53.7%), accumulando la variabilità sia del numero di vendite che dei prezzi.
Variabile con la distribuzione più asimmetrica: Volume
Confrontando i valori di skewness in valore assoluto, il volume risulta il più asimmetrico (skewness ≈ 0.885), con coda a destra: poche osservazioni con volumi eccezionalmente alti trascinano la media (31M\() al di sopra della mediana (27M\)). All’opposto, months_inventory è praticamente simmetrico (skewness ≈ 0.04), mentre median_price è l’unica variabile con asimmetria negativa (-0.365).
Viene classificata la variabile median_price in 5 classi
di ampiezza uguale.
data$price_class = cut(median_price, breaks = 5, include.lowest = T, right = T)
freq_price = table(data$price_class)
rel_freq = prop.table(freq_price)
print(freq_price)
##
## [7.37e+04,9.5e+04] (9.5e+04,1.16e+05] (1.16e+05,1.38e+05] (1.38e+05,1.59e+05]
## 18 40 73 84
## (1.59e+05,1.8e+05]
## 25
print(round(rel_freq, 4))
##
## [7.37e+04,9.5e+04] (9.5e+04,1.16e+05] (1.16e+05,1.38e+05] (1.38e+05,1.59e+05]
## 0.0750 0.1667 0.3042 0.3500
## (1.59e+05,1.8e+05]
## 0.1042
barplot(freq_price,
main = "Distribuzione del prezzo mediano per classi",
xlab = "Classi di prezzo ($)",
ylab = "Frequenza assoluta",
col = "lightblue",
las = 1,
cex.names = 0.60)
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(data$price_class)
## [1] 0.9259115
Commento: Un indice di Gini normalizzato vicino a 1 indica alta eterogeneità: le osservazioni sono distribuite in modo abbastanza uniforme tra le classi di prezzo, senza una concentrazione marcata in una singola fascia.
Le probabilità sono calcolate in senso frequentista: p = casi favorevoli / casi totali.
n_tot = nrow(data)
# Probabilità Beaumont
n_beaumont = sum(city == "Beaumont")
p_beaumont = (n_beaumont / n_tot) * 100
cat("P(Beaumont):", p_beaumont, "%\n")
## P(Beaumont): 25 %
# Probabilità Luglio
n_luglio = sum(month == 7)
p_luglio = (n_luglio / n_tot) * 100
cat("P(Luglio):", p_luglio, "%\n")
## P(Luglio): 8.333333 %
# Probabilità Dicembre 2012
n_dicembre2012 = sum(month == 12 & year == 2012)
p_dicembre2012 = (n_dicembre2012 / n_tot) * 100
cat("P(Dicembre 2012):", p_dicembre2012, "%\n")
## P(Dicembre 2012): 1.666667 %
Commento: La probabilità di estrarre una riga relativa a Beaumont è pari al 25%, coerente con un dataset bilanciato su 4 città. La probabilità per il mese di luglio è circa 8.3% (1/12), e quella per dicembre 2012 circa 1.7%, corrispondente a un singolo mese di un singolo anno su tutti quelli disponibili.
# Prezzo medio: volume totale (convertito in $) diviso numero di vendite
data$mean_price = (volume * 1000000) / sales
summary(data$mean_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 97010 132939 156588 154320 173915 213234
# Efficacia annunci: percentuale di annunci convertiti in vendita
data$efficacy = (sales / listings) * 100
summary(data$efficacy)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.014 8.980 10.963 11.874 13.492 38.713
Commento: Il prezzo medio (mean_price)
è influenzato dalle transazioni di lusso e risulta generalmente
superiore al prezzo mediano, confermando la distribuzione asimmetrica
dei prezzi. L’efficacia degli annunci (efficacy) misura la
capacità del mercato di convertire le inserzioni in vendite: valori più
alti indicano mercati più dinamici con domanda sostenuta.
summary_city = data %>%
group_by(city) %>%
summarise(
n_obs = n(),
media_sales = mean(sales, na.rm = T),
sd_sales = sd(sales, na.rm = T),
media_volume = mean(volume, na.rm = T),
sd_volume = sd(volume, na.rm = T),
media_prezzo = mean(median_price, na.rm = T),
sd_prezzo = sd(median_price, na.rm = T),
media_efficacy = mean(efficacy, na.rm = T)
) %>%
arrange(desc(media_sales))
print(summary_city)
## # A tibble: 4 × 9
## city n_obs media_sales sd_sales media_volume sd_volume media_prezzo sd_prezzo
## <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Tyler 60 270. 62.0 45.8 13.1 141442. 9337.
## 2 Brya… 60 206. 85.0 38.2 17.2 157488. 8852.
## 3 Beau… 60 177. 41.5 26.1 6.97 129988. 10105.
## 4 Wich… 60 116. 22.2 13.9 3.24 101743. 11320.
## # ℹ 1 more variable: media_efficacy <dbl>
ggplot(summary_city, aes(x = factor(city), y = media_prezzo)) +
geom_col(fill = "lightblue") +
geom_errorbar(aes(ymin = media_prezzo - sd_prezzo,
ymax = media_prezzo + sd_prezzo), width = 0.3, color = "red") +
labs(title = "Media del Prezzo per Città (con Dev. Standard)",
x = "Città", y = "Media Prezzo ($)")
summary_year = data %>%
group_by(year) %>%
summarise(
totale_sales = sum(sales, na.rm = T),
totale_volume = sum(volume, na.rm = T),
media_prezzo = mean(median_price, na.rm = T)
)
print(summary_year)
## # A tibble: 5 × 4
## year totale_sales totale_volume media_prezzo
## <int> <int> <dbl> <dbl>
## 1 2010 8096 1232. 130192.
## 2 2011 7878 1208. 127854.
## 3 2012 8935 1405. 130077.
## 4 2013 10172 1687. 135723.
## 5 2014 11069 1909. 139481.
summary_month = data %>%
group_by(month) %>%
summarise(
media_sales = mean(sales, na.rm = T),
sd_sales = sd(sales, na.rm = T),
media_volume = mean(volume, na.rm = T),
sd_volume = sd(volume, na.rm = T)
) %>%
arrange(month)
print(summary_month)
## # A tibble: 12 × 5
## month media_sales sd_sales media_volume sd_volume
## <int> <dbl> <dbl> <dbl> <dbl>
## 1 1 127. 43.4 19.0 8.37
## 2 2 141. 51.1 21.7 10.1
## 3 3 189. 59.2 29.4 12.0
## 4 4 212. 65.4 33.3 14.5
## 5 5 239. 83.1 39.7 19.0
## 6 6 244. 95.0 41.3 21.1
## 7 7 236. 96.3 39.1 21.4
## 8 8 231. 79.2 38.0 18.0
## 9 9 182. 72.5 29.6 15.2
## 10 10 180. 75.0 29.1 15.1
## 11 11 157. 55.5 24.8 11.2
## 12 12 169. 60.7 27.1 12.6
ggplot(summary_month, aes(x = factor(month), y = media_sales)) +
geom_col(fill = "blue") +
geom_errorbar(aes(ymin = media_sales - sd_sales,
ymax = media_sales + sd_sales), width = 0.3, color = "red") +
labs(title = "Media delle Vendite per Mese (con Dev. Standard)",
x = "Mese", y = "Media Vendite")
Commento: Le vendite mostrano una chiara stagionalità con picchi nei mesi primaverili ed estivi. Le città presentano prezzi medi e variabilità molto differenti tra loro, confermando l’eterogeneità del mercato texano.
ggplot(data, aes(x = reorder(city, median_price, median), y = median_price, fill = city)) +
geom_boxplot(outlier.colour = "red", outlier.shape = 1, alpha = 0.5) +
labs(title = "Distribuzione del Prezzo Mediano per Città",
x = "Città", y = "Prezzo Mediano ($)")
Commento: Il boxplot mostra mediana, IQR e outlier per ogni città. Le città con il box posizionato più in alto hanno prezzi mediani strutturalmente più elevati. L’ampiezza del box indica la variabilità interna: box ampi corrispondono a mercati più eterogenei. I punti rossi (outlier) verso l’alto segnalano transazioni occasionali di valore eccezionale.
ggplot(data, aes(x = reorder(city, volume, median), y = volume, fill = city)) +
geom_boxplot(alpha = 0.7) +
labs(title = "Distribuzione del Volume delle Vendite per Città",
x = "Città", y = "Volume (milioni $)")
ggplot(data, aes(x = volume, y = factor(year), fill = factor(year))) +
geom_boxplot(alpha = 0.5) +
labs(title = "Distribuzione del Volume delle Vendite per Anno",
x = "Volume (milioni $)", y = "Anno")
Commento: Il confronto per anno evidenzia l’evoluzione del mercato nel tempo. Anni con box spostati verso destra indicano volumi di vendita complessivamente più alti, segnale di un mercato in espansione. La variabilità all’interno di ogni anno (ampiezza del box) riflette le differenze stagionali e geografiche.
sales_month_city = data %>%
group_by(month, city) %>%
summarise(totale_sales = sum(sales), .groups = "drop")
nomi_mesi = c("Gen","Feb","Mar","Apr","Mag","Giu",
"Lug","Ago","Set","Ott","Nov","Dic")
ggplot(sales_month_city, aes(x = factor(month, labels = nomi_mesi),
y = totale_sales, fill = city)) +
geom_col() +
labs(title = "Totale Vendite per Mese e Città (Barre Sovrapposte)",
x = "Mese", y = "Totale Vendite", fill = "Città")
ggplot(sales_month_city, aes(x = factor(month, labels = nomi_mesi),
y = totale_sales, fill = city)) +
geom_col(position = "fill") +
scale_y_continuous(labels = percent_format()) +
labs(title = "Composizione % delle Vendite per Mese e Città",
x = "Mese", y = "Percentuale", fill = "Città")
Commento: Le barre sovrapposte mostrano sia il contributo di ogni città sia il totale mensile: si nota chiaramente il picco primaverile-estivo. Il grafico normalizzato rivela invece se il mix tra città cambia nel corso dell’anno: proporzioni stabili indicano che ogni città mantiene la propria quota di mercato indipendentemente dalla stagione.
data$date = as.Date(paste(year, month, "01", sep = "-"))
sales_trend = data %>%
group_by(city, date) %>%
summarise(totale_sales = sum(sales), .groups = "drop")
ggplot(sales_trend, aes(x = date, y = totale_sales, color = city)) +
geom_line(linewidth = 0.8) +
labs(title = "Andamento delle Vendite nel Tempo per Città",
x = "Data", y = "Vendite Totali", color = "Città") +
scale_x_date(date_labels = "%Y", date_breaks = "1 year")
Commento: Il line chart rivela la stagionalità ricorrente delle vendite (picchi nei mesi estivi) e le tendenze di lungo periodo per ogni città. Le città con linea in crescita nel tempo sono mercati in espansione strutturale. La sovrapposizione delle linee permette di confrontare direttamente il peso relativo di ogni città nel corso degli anni.
L’analisi descrittiva ha evidenziato come il mercato immobiliare texano sia caratterizzato da una variabilità significativa, concentrata soprattutto nel volume delle vendite — la variabile più dispersa (CV ≈ 54%) e più asimmetrica (skewness ≈ 0.88) — mentre il prezzo mediano risulta la variabile più stabile e affidabile per il riferimento di mercato. Le vendite mostrano una chiara stagionalità con picchi primaverili ed estivi, e le città presentano comportamenti eterogenei sia in termini di prezzi che di efficacia delle inserzioni, confermando che il mercato texano non può essere letto in modo uniforme ma richiede un approccio localizzato.
Raccomandazioni principali: