library(ggplot2)
library(dplyr)
library(moments)
library(gghalves)
# Tipologia variabili
# city: categorica nominale → confronti tra mercati (boxplot, distribuzioni)
# year + month: variabili temporali discrete → trend e stagionalità
# sales, listings: quantitative discrete → intensità domanda/offerta
# volume, median_price, months_inventory: quantitative continue → valore economico, prezzi e equilibrio domanda/offerta
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
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
boxplot(dati$median_price, main="Boxplot prezzo mediano")
abline(h=quantile(dati$median_price), col="red")
abline(h=quantile(dati$median_price,0.75)+1.5*IQR(dati$median_price), col="red")
abline(h=quantile(dati$median_price,0.25)-1.5*IQR(dati$median_price), col="red")
boxplot(median_price~city, data=dati, main="Prezzo mediano per città")
ggplot(dati, aes(x=city, y=median_price))+
geom_boxplot()+
facet_wrap(~ year)+
theme_classic()+
labs(title="Distribuzione median_price per città e anno", x="Città", y="Prezzo mediano")
ggplot(dati, aes(x = factor(month), y = median_price)) +
geom_boxplot() +
facet_grid(city ~ year) +
theme_classic() +
labs(title="Prezzo mediano per mese (city ~ year)", x = "Mese", y="Prezzo mediano")
ggplot(dati, aes(x = year, y = median_price, color = city, group = city)) +
geom_line() +
geom_point() +
theme_classic() +
labs(title="Andamento annuale del prezzo mediano per città",
x="Anno", y="Prezzo mediano", color="Città")
ggplot(dati, aes(x = city, y = median_price)) +
geom_boxplot(fill = "green") +
stat_summary(fun = median, geom = "text",
aes(label = paste("Median=", round(after_stat(y),1))),
vjust = -0.7, color="red", size=4) +
stat_summary(fun = function(x) quantile(x,0.25), geom="text",
aes(label=paste("Q1=", round(after_stat(y),1))), vjust=1.5, size=3.5) +
stat_summary(fun = function(x) quantile(x,0.75), geom="text",
aes(label=paste("Q3=", round(after_stat(y),1))), vjust=-1, size=3.5) +
theme_classic() +
labs(title="Distribuzione del prezzo mediano per città", x="Città", y="Prezzo mediano")
ggplot(dati, aes(x = city, y = median_price, fill = factor(year))) +
geom_bar(stat = "summary", fun = "median", position = "dodge") +
theme_classic() +
labs(title="Prezzo mediano (mediana) per città e anno", x="Città", y="Prezzo mediano", fill="Anno")
ggplot(dati, aes(x = city, y = volume, fill = factor(year))) +
geom_boxplot() +
theme_classic() +
labs(title="Distribuzione volume per città e anno", x="Città", y="Volume", fill="Anno")
agg_mese_city_year <- dati %>%
group_by(year, month, city) %>%
summarise(volume_tot = sum(volume), .groups = "drop")
ggplot(agg_mese_city_year, aes(x = factor(month), y = volume_tot, fill = city)) +
geom_col() +
facet_wrap(~ year) +
theme_classic() +
labs(title="Totale volume vendite per mese (stacked)", x="Mese", y="Volume totale", fill="Città")
ggplot(agg_mese_city_year, aes(x = factor(month), y = volume_tot, fill = city)) +
geom_col(position = "fill") +
facet_wrap(~ year) +
theme_classic() +
labs(title="Totale volume vendite per mese (normalizzato)", x="Mese", y="Proporzione", fill="Città")
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, città e anno", x="Mese", y="Vendite totali")
dati$trimestre <- cut(dati$month, breaks=c(0,3,6,9,12),
labels=c("Trim1","Trim2","Trim3","Trim4"))
table(dati$trimestre)
##
## Trim1 Trim2 Trim3 Trim4
## 60 60 60 60
ggplot(dati, aes(x = trimestre, y = volume, fill = trimestre)) +
geom_boxplot() +
facet_wrap(~ city) +
theme_classic() +
labs(title="Volume per trimestre e città", x="Trimestre", y="Volume")
ggplot(dati, aes(x = trimestre, y = median_price)) +
geom_boxplot(fill="orange") +
facet_grid(city ~ year) +
theme_classic() +
labs(title="Prezzo mediano per trimestre (city ~ year)", x="Trimestre", y="Prezzo mediano")
agg_year <- aggregate(median_price ~ year, data = dati, FUN = median)
ggplot(agg_year, aes(x = year, y = median_price)) +
geom_line() +
geom_point() +
theme_classic() +
labs(title="Andamento complessivo del prezzo mediano", x="Anno", y="Prezzo mediano")
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
dati$classi <- cut(dati$sales, breaks=5)
frequenze_sales <- table(dati$classi)
barplot(frequenze_sales, main="Distribuzione sales in classi", xlab="Classi sales", ylab="Frequenza", las=1)
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.index(dati$classi)
## [1] 0.9132812
prob_beaumont <- mean(dati$city == "Beaumont")
prob_luglio <- mean(dati$month == 7)
prob_dic2012 <- mean(dati$month == 12 & dati$year == 2012)
prob_beaumont
## [1] 0.25
prob_luglio
## [1] 0.08333333
prob_dic2012
## [1] 0.01666667
prob_and <- mean(dati$city == "Beaumont" & dati$month == 7 & dati$year == 2012)
prob_and
## [1] 0.004166667
dati$efficacia_annunci <- dati$sales / dati$listings
summary(dati$efficacia_annunci)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.05014 0.08980 0.10963 0.11874 0.13492 0.38713
ggplot(dati, aes(x = city, y = efficacia_annunci)) +
geom_boxplot(fill="green") +
theme_classic() +
labs(title="Efficacia annunci per città", x="Città", y="Vendite / Annunci")
efficacia_city_year <- dati %>%
group_by(year, city) %>%
summarise(efficacia_media = mean(efficacia_annunci), .groups="drop")
ggplot(efficacia_city_year, aes(x=year, y=efficacia_media, color=city, group=city)) +
geom_line() + geom_point() +
theme_classic() +
labs(title="Evoluzione efficacia annunci", x="Anno", y="Vendite/Annunci")
ggplot(dati, aes(x = city, y = efficacia_annunci, fill = city)) +
geom_half_violin(side = "r", alpha = 0.6, color = NA) +
geom_half_boxplot(side = "l", width = 0.2, outlier.shape = NA) +
facet_wrap(~ year) +
theme_classic() +
theme(legend.position = "none") +
labs(title="Distribuzione efficacia annunci per città e anno", x="Città", y="Vendite/Annunci")
L’analisi del dataset evidenzia come il mercato presenti dinamiche eterogenee sia dal punto di vista territoriale sia temporale. Le differenze tra le città analizzate non si limitano ai livelli di prezzo, ma riguardano anche la stabilità del mercato, la variabilità dei volumi di vendita e l’efficienza del sistema di offerta.
In particolare, analizzando Bryan–College Station emerge come un mercato caratterizzato da prezzi medi più elevati e da una dispersione relativamente contenuta, segnale di una struttura più stabile e prevedibile. Questo profilo suggerisce un contesto adatto a strategie orientate alla continuità e alla valorizzazione nel medio-lungo periodo. Wichita Falls, al contrario, presenta valori medi inferiori e una maggiore variabilità, indicando un mercato più volatile, potenzialmente interessante in ottica di opportunità tattiche ma con un livello di rischio più elevato.
L’analisi degli indici di variabilità e forma mostra come il volume delle vendite sia la variabile più instabile e asimmetrica. La presenza di una marcata asimmetria positiva indica che i risultati economici del mercato sono trainati da pochi periodi di forte crescita, mentre la maggior parte delle osservazioni si concentra su valori più contenuti. Questo comportamento suggerisce che le performance complessive dipendono in modo significativo da fasi cicliche favorevoli, piuttosto che da una crescita costante nel tempo.
L’introduzione dell’indicatore di efficacia degli annunci di vendita, definito come rapporto tra vendite concluse e annunci attivi, consente una lettura più operativa del mercato. Città come Tyler e Beaumont mostrano valori medi più elevati di questo indicatore, mostrando una maggiore capacità di assorbimento dell’offerta e una migliore efficienza delle inserzioni. Al contrario, contesti con un numero elevato di annunci rispetto alle vendite suggeriscono una maggiore competizione tra operatori e tempi di vendita potenzialmente più lunghi.
Dal punto di vista manageriale, i risultati ottenuti forniscono indicazioni utili per una gestione differenziata delle strategie commerciali. In mercati più stabili è possibile puntare su politiche di prezzo e investimento più conservative, mentre nei contesti più variabili risulta strategico intervenire sulla qualità e sul posizionamento degli annunci, oltre che sulla tempistica di ingresso sul mercato.