#librerie
library(ggplot2)
library(dplyr)
##
## 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
library(scales)
## Warning: il pacchetto 'scales' è stato creato con R versione 4.4.3
#dataset
data_ret <- read.csv("realestate_texas.csv")
#cose utili
n <- nrow(data_ret)
months <- c("Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic")
#funzioni
#indice di gini
gini.index <- function(x){
ni = table(x)
fi = ni/length(x)
fi2 = fi^2
J = length(table(x))
gini = 1-sum(fi2)
gini.norm = gini/((J-1)/J)
return(gini.norm)
}
#calcolo indici
calculate_indices <- function(x) {
indici <- list(
min = min(x),
Q1 = quantile(x, 0.25),
mediana = median(x),
media = mean(x),
Q3 = quantile(x, 0.75),
max = max(x),
range = max(x) - min(x),
IQR = IQR(x),
varianza = var(x),
ds = sd(x),
CV = sd(x) / mean(x) * 100,
skewness = skewness(x),
kurtosis = kurtosis(x)
)
return(indici)
}
Nel dataset sono presenti 240 osservazioni per 8 variabili.
La seguente tabella illustra i tipi di variabili statistiche presenti nel dataset.
| Variabile | Tipo varia | Descrizione |
|---|---|---|
city |
qualitativa su scala nominale | città di riferimento per i dati |
year |
qualitativa su scala nominale | anno di riferimento per i dati |
month |
qualitativa su scala nominale | mese di riferimento per i dati |
sales |
quantitativa discreta | numero totale delle vendite |
volume |
quantitativa continua | valore totale delle vendite espresso in milioni di dollari |
median_price |
quantitativa continua | valore mediano del prezzo di vendita, espresso in dollari |
listings |
quantitativa discreta | numero totale di annunci attivi |
month_inventory |
quantitativa continua | quantità di tempo necessaria per vendere tutte le inserzioni correnti al ritmo attuale di vendita, espresso in mesi |
Ho deciso di trattare le variabili che esprimono una dimensione tempo come variabili qualitative.
Ho creato una variabile date_var in formato
date combinando i dati delle variabili temporali
month e year. Ho convenzionalmente impostato
il valore day con il primo giorno del mese.
data_ret$date_var <- as.Date(
paste(data_ret$year, data_ret$month, "01", sep = "-"),
format = "%Y-%m-%d"
)
Per le variabili qualitative calcolerò la distribuzione di frequenza, per le variabili quantitative calcolerò gli indici di posizione, variabilità e forma.
Ho analizzato distribuzione di frequenza per le variabili
city, year e month calcolando
l’indice di Gini.
city: 1year: 1month: 1L’indice di Gini esprime massima eterogeneità per tutte le variabili analizzate. Pertanto, essendo i valori equamente distribuiti, si può dedurre che dal 2010 al 2014, per ogni mese e per ogni città di riferimento sono state rilevate le variabili quantitative descritte nella tabella precedente.
Questa deduzione è confermata dalla verifica delle categorie per ciascuna variabile, che risultano perfettamente equidistribuite.
table(data_ret$city)
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
table(data_ret$year)
##
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
table(data_ret$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
Procedo con il calcolo delle probabilità richieste nel punto 5.
Probabilità che una riga riporti la città di Beaumont: 25%
Probabilità che una riga riporti il mese di luglio: 8.34%
Probabilità che una riga riporti il mese di dicembre 2012: 1.67%
sum((data_ret$city=="Beaumont")/n)*100
## [1] 25
sum((data_ret$month==07)/n)*100
## [1] 8.333333
sum((data_ret$date=="2012-12-01")/n)*100
## [1] 1.666667
Ho deciso di anticipare questo anche il punto 6 per poter poi confrontare il prezzo medio al prezzo mediano.
Ho calcolato il prezzo medio degli immobili utilizzando la seguente formula:
\[ mean\_price = \frac{volume}{sales} \]
Nel dataset, il totale delle vendite è espresso in milioni di
dollari. Per poter poi confrontare avg_price e
median_price ho convertito anche mean_price in
dollari.
data_ret$mean_price <- (data_ret$volume/data_ret$sales)*1000000
Ho calcolato l’efficacia degli annunci utilizzando la seguente formula:
\[
listing\_eff = \frac{sales}{listings} \times{100}
\] Il rapporto tra il numero di vendite (sales) e il
numero di annunci attivi (listings) indica quante vendite
sono generate per ogni annuncio attivo; listing_eff è
espresso in termini percentuali. Valori alti Indicano molte vendite per
annuncio, quindi che gli annunci sono molto efficaci. Valori bassi
indicano poche vendite per annuncio, quindi che gli annunci sono poco
efficaci.
data_ret$listing_eff <- (data_ret$sales/data_ret$listings)*100
Per considerare anche il valore economico delle vendite, ho calcolato una variabile che esprime in dollari il valore generato per ciascun annuncio.
\[ listing\_value = \frac{{mean\_price}\times{sales}}{listings} \]
data_ret$listing_value <- ((data_ret$sales)*(data_ret$mean_price))/data_ret$listings
Procedo con il calcolo degli indici di posizione, variabilità e forma
per le variabili listings, sales,
volume, median_price, mean_price
che riepilogo nella seguente tabella.
| listings | sales | volume | median_price | mean_price | |
|---|---|---|---|---|---|
| min | 743.00 | 79.00 | 8.17 | 73800.00 | 97010.20 |
| Q1 | 1026.50 | 127.00 | 17.66 | 117300.00 | 132938.94 |
| mediana | 1618.50 | 175.50 | 27.06 | 134500.00 | 156588.48 |
| media | 1738.02 | 192.29 | 31.01 | 132665.42 | 154320.37 |
| Q3 | 2056.00 | 247.00 | 40.89 | 150050.00 | 173915.15 |
| max | 3296.00 | 423.00 | 83.55 | 180000.00 | 213233.94 |
| range | 2553.00 | 344.00 | 75.38 | 106200.00 | 116223.74 |
| IQR | 1029.50 | 120.00 | 23.23 | 32750.00 | 40976.22 |
| varianza | 566568.97 | 6344.30 | 277.27 | 513572983.09 | 736984385.27 |
| ds | 752.71 | 79.65 | 16.65 | 22662.15 | 27147.46 |
| CV | 43.31 | 41.42 | 53.71 | 17.08 | 17.59 |
| skewness | 0.65 | 0.72 | 0.88 | -0.36 | -0.07 |
| kurtosis | 2.21 | 2.69 | 3.18 | 2.38 | 2.22 |
ggplot(data_ret, aes(x = volume)) +
geom_histogram(
bins = 21,
fill = "lightgrey",
color = "black"
) +
geom_density(
aes(y = after_stat(count)*((max(data_ret$volume)-min(data_ret$volume))/21)),
color = "red",
size = 1
) +
labs(
x = NULL,
y = "Frequenza assoluta",
title = "Distribuzione del volume totale delle vendite") +
scale_x_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M"),
breaks = seq(10, 90, by = 10)
)+
theme_light()
Il volume totale delle vendite esprime la più alta variabilità (CV = 53.71%) tra le variabili analizzate, i valori sono quindi molto dispersi intorno alla media. Ciò potrebbe essere dovuto a importanti fluttuazioni nel valore totale delle vendite nel corso del tempo, o a significative differenze tra una città e l’altra. Un alto CV potrebbe quindi indicare un mercato immobiliare piuttosto volatile.
Il volume totale delle vendite esprime anche la variabile con la distribuzione più asimmetrica, con una coda lunga a destra (skewness = 0.88), la maggior parte dei volumi di vendita registrati si concentra sui valori più bassi. Questo aspetto potrebbe essere causato da diversi fattori, come, ad esempio, minor rendimento di alcune città o un basso volume di vendite per periodi prolungati.
Come si può vedere dal grafico, la curva di densità (linea rossa) mostra che la maggior parte dei volumi di vendita registrati si concentra tra i 10 e i 35 milioni di dollari. L’istogramma, che rappresenza le frequenze assolute suddivise in 21 classi, mostra una distribuzione dei valori piuttosto varia con più picchi significativi.
ggplot(data_ret, aes(x = median_price)) +
geom_histogram(
bins = 21,
fill = "lightgrey",
color = "black"
) +
geom_density(
aes(y = after_stat(count)*((max(data_ret$median_price)-min(data_ret$median_price))/21)),
color = "red",
size = 1
) +
labs(
x = "Prezzo mediano",
y = "Frequenza assoluta",
title = "Distribuzione del prezzo mediano"
) +
scale_x_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "),
breaks = seq(70000, 180000, by = 20000)
)+
theme_light()
ggplot(data_ret, aes(x = mean_price)) +
geom_histogram(
bins = 21,
fill = "lightgrey",
color = "black"
) +
geom_density(
aes(y = after_stat(count)*((max(data_ret$mean_price)-min(data_ret$mean_price))/21)),
color = "red",
size = 1
) +
labs(
x = "Prezzo medio",
y = "Frequenza assoluta",
title = "Distribuzione del prezzo medio"
) +
scale_x_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "),
breaks = seq(90000, 220000, by = 20000)
)+
theme_light()
Il prezzo medio ha un range più ampio rispetto al prezzo mediano (116224$ cfr. 106200$), indicando la presenza di alcuni valori estremi che influenzano la media. Potrebbe trattarsi di alcuni immobili di alto valore, essendo il prezzo medio generalmente più alto del prezzo mediano. Inoltre, il prezzo medio minimo è più alto del prezzo mediano minimo, ciò suggerisce che non ci sono molti immobili a prezzi molto bassi.
La varianza e la deviazione standard del prezzo medio sono leggermente più elevate rispetto a quelle del prezzo mediano, confermando una maggiore dispersione dei prezzi medi.
Sia nel prezzo medio sia nel prezzo mediano si può osservare una leggera asimmetria negativa e la curtosi leggermente elevata. Questi dati suggeriscono che la distribuzione dei prezzi ha una coda sinistra più lunga e alcuni valori estremi, anche se non particolarmente influenti.
Ho suddiviso la variabile quantitativa sales in 3
classi.
sales_cl_3 <- cut(data_ret$sales, breaks = 3)
distr_freq_sales_3 <- as.data.frame(
cbind(
ni=table(sales_cl_3),
fi=round(table(sales_cl_3)/n, 3),
Ni=cumsum(table(sales_cl_3)),
Fi=round(cumsum(table(sales_cl_3))/n, 3)
)
)
| ni | fi | Ni | Fi | |
|---|---|---|---|---|
| (78.7,194] | 141 | 0.5875 | 141 | 0.5875 |
| (194,308] | 76 | 0.3167 | 217 | 0.9042 |
| (308,423] | 23 | 0.0958 | 240 | 1.0000 |
ggplot(as.data.frame(sales_cl_3))+
geom_bar(aes(x = sales_cl_3),
fill = "lightgrey",
color = "black"
)+
labs(
x = "Classi",
y = "Frequenza assoluta",
title = "Distribuzione in 3 classi del totale delle vendite"
)+
theme_light()
La maggior parte dei valori (58.6%) è concentrata nella prima classe, che rappresenta un numero di vendite basso compreso tra 79 e 194. Pochi valori (9.6%) sono registrati nella terza classe, che rappresenta un numero alto di vendite alto compreso tra 308 e 423. L’indice di Gini è di 0.82, e presenta una modesta eterogeneità.
Ho voluto analizzare più nel dettaglio la distribuzione del numero di vendite, con una suddivisione in 9 classi.
sales_cl_9 <- cut(data_ret$sales, breaks = 9)
distr_freq_sales_9 <- as.data.frame(
cbind(
ni=table(sales_cl_9),
fi=round(table(sales_cl_9)/n, 3),
Ni=cumsum(table(sales_cl_9)),
Fi=round(cumsum(table(sales_cl_9))/n, 3)
)
)
| ni | fi | Ni | Fi | |
|---|---|---|---|---|
| (78.7,117] | 46 | 0.1916667 | 46 | 0.1916667 |
| (117,155] | 51 | 0.2125000 | 97 | 0.4041667 |
| (155,194] | 44 | 0.1833333 | 141 | 0.5875000 |
| (194,232] | 27 | 0.1125000 | 168 | 0.7000000 |
| (232,270] | 23 | 0.0958333 | 191 | 0.7958333 |
| (270,308] | 26 | 0.1083333 | 217 | 0.9041667 |
| (308,347] | 10 | 0.0416667 | 227 | 0.9458333 |
| (347,385] | 9 | 0.0375000 | 236 | 0.9833333 |
| (385,423] | 4 | 0.0166667 | 240 | 1.0000000 |
ggplot(as.data.frame(sales_cl_9))+
geom_bar(aes(x = sales_cl_9),
fill = "lightgray",
color = "black"
)+
labs(
x = "Classi",
y = "Frequenza assoluta",
title = "Distribuzione in 3 classi del totale delle vendite"
)+
theme_light()
ggplot(data_ret, aes(x = sales)) +
geom_histogram(
bins = 21,
fill = "lightgrey",
color = "black"
) +
geom_density(
aes(y = after_stat(count)*((max(data_ret$sales)-min(data_ret$sales))/21)),
color = "red",
size = 1
) +
labs(
x = "Vendite",
y = "Frequenza assoluta",
title = "Distribuzione del numero di vendite"
) +
theme_light()
La doppia analisi (9 classi e 21 bin) conferma un mercato polarizzato, dove la maggior parte dei periodi/città registra vendite modeste, mentre pochi casi eccezionali contribuiscono in modo sproporzionato al volume totale. Inoltre, la similitudine tra le distribuzioni di sales e volume conferma che il valore totale delle vendite è trainato principalmente dal numero di transazioni.
Ho deciso di condurre l’analisi condizionata sulla variabili che
esprimono il prezzo medio (avg_price) e il numero di
vendite (sales), al fine di analizzare più nel dettaglio la
composizione del volume totale delle vendite.
Prezzo medio
summary_year_mean_price <- data_ret %>%
group_by(year) %>%
summarise(
mean_mean_price = round(mean(mean_price),0),
sd_mean_price = round(sd(mean_price),0)
)
| anno | media prezzo medio | sd prezzo medio |
|---|---|---|
| 2010 | 150189 | 23280 |
| 2011 | 148251 | 24938 |
| 2012 | 150899 | 26438 |
| 2013 | 158705 | 26524 |
| 2014 | 163559 | 31741 |
Vendite
summary_year_sales <- data_ret %>%
group_by(year) %>%
summarise(
mean_sales = round(mean(sales),0),
sd_sales = round(sd(sales),0)
)
| anno | media vendite | sd vendite |
|---|---|---|
| 2010 | 169 | 61 |
| 2011 | 164 | 64 |
| 2012 | 186 | 71 |
| 2013 | 212 | 84 |
| 2014 | 231 | 96 |
Prezzo medio
summary_month_mean_price <- data_ret %>%
group_by(month) %>%
summarise(
mean_mean_price = round(mean(mean_price),0),
sd_mean_price = round(sd(mean_price),0)
)
| mese | media prezzo medio | sd prezzo medio |
|---|---|---|
| 1 | 145640 | 29819 |
| 2 | 148840 | 25120 |
| 3 | 151137 | 23238 |
| 4 | 151461 | 26174 |
| 5 | 158235 | 25787 |
| 6 | 161546 | 23470 |
| 7 | 156881 | 27220 |
| 8 | 156456 | 28253 |
| 9 | 156522 | 29669 |
| 10 | 155897 | 32527 |
| 11 | 154233 | 29685 |
| 12 | 154996 | 27009 |
Vendite
summary_month_sales <- data_ret %>%
group_by(month) %>%
summarise(
mean_sales = round(mean(sales),0),
sd_sales = round(sd(sales),0)
)
| mese | media vendite | sd prezzo medio |
|---|---|---|
| 1 | 127 | 43 |
| 2 | 141 | 51 |
| 3 | 189 | 59 |
| 4 | 212 | 65 |
| 5 | 239 | 83 |
| 6 | 244 | 95 |
| 7 | 236 | 96 |
| 8 | 231 | 79 |
| 9 | 182 | 73 |
| 10 | 180 | 75 |
| 11 | 157 | 55 |
| 12 | 169 | 61 |
Prezzo medio
summary_city_mean_price <- data_ret %>%
group_by(city) %>%
summarise(
mean_mean_price = round(mean(mean_price),0),
sd_mean_price = round(sd(mean_price),0)
)
| città | media prezzo medio | sd prezzo medio |
|---|---|---|
| Beaumont | 146640 | 11232 |
| Bryan-College Station | 183534 | 15149 |
| Tyler | 167677 | 12351 |
| Wichita Falls | 119430 | 11398 |
Vendite
summary_city_sales <- data_ret %>%
group_by(city) %>%
summarise(
mean_sales = round(mean(sales),0),
sd_sales = round(sd(sales),0)
)
| città | media vendite | sd vendite |
|---|---|---|
| Beaumont | 177 | 41 |
| Bryan-College Station | 206 | 85 |
| Tyler | 270 | 62 |
| Wichita Falls | 116 | 22 |
ggplot(summary_year_mean_price, aes(x = as.integer(year), y = mean_mean_price)) +
geom_line(color = "darkblue", size = 1) +
geom_point(color = "darkblue", size = 3) +
labs(
x = NULL,
y = "Prezzo medio",
title = "Andamento della media del prezzo medio per anno"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light()
ggplot(summary_year_sales, aes(x = as.integer(year), y = mean_sales)) +
geom_line(color = "darkorange", size = 1) +
geom_point(color = "darkorange", size = 3) +
labs(
x = NULL,
y = "Vendite",
title = "Andamento della media del numero vendite per anno"
) +
theme_light()
ggplot(summary_month_mean_price,
aes(x = month, y = mean_mean_price)) +
geom_bar(
aes(fill = mean_mean_price),
stat = "identity",
color = "black",
show.legend = FALSE
) +
scale_fill_gradient(
low = "lightgray",
high = "darkblue"
) +
labs(
x = NULL,
y = "Prezzo medio",
title = "Valore medio del prezzo medio per mese"
) +
scale_x_continuous(
breaks = seq(1, 12, by = 1),
labels = months) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light()
ggplot(summary_month_sales,
aes(x = month, y = mean_sales)) +
geom_bar(
aes(fill = mean_sales),
stat = "identity",
color = "black",
show.legend = FALSE
) +
scale_fill_gradient(
low = "lightgray",
high = "darkorange"
) +
labs(
x = NULL,
y = "Vendite",
title = "Valore medio del numero di vendite per mese"
) +
scale_x_continuous(
breaks = seq(1, 12, by = 1),
labels = months) +
theme_light()
ggplot(summary_city_mean_price,
aes(x = city, y = mean_mean_price)) +
geom_bar(
aes(fill=mean_mean_price),
stat = "identity",
color = "black",
show.legend = FALSE
) +
scale_fill_gradient(
low = "lightgray",
high = "darkblue"
) +
labs(
x = NULL,
y = "Prezzo medio",
title = "Media del prezzo medio per città"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light()
L’analisi condizionata per anno, mese e città rivela marcate differenze geografiche e temporali.
Negli anni (2010-2014), si osserva una crescita sia del numero medio di vendite (+36.7%), sia del prezzo di vendita medio (+8.9%). La crescita è costante ad eccezione del 2011 che registra il valore medio più basso sia di prezzo medio (148251$) sia di numero di vendite (164). Negli anni cresce anche la variabilità, soprattutto nel numero medio di vendite (2010 ±61, 2014 ±96).
A livello stagionale, prezzi e vendite raggiungono il picco nel mese di giugno, con una media di 161546$ e 244 vendite. I mesi da ottobre a gennaio sono caratterizzati da una progressiva contrazione e da una maggiore variabilità dei prezzi medi. Gennaio è il mese con il prezzo medio più basso (145640$) e con in media meno vendite (127).
La città di Bryan-College Station ha il prezzo medio più alto, con una media 183534$. Questo primato potrebbe essere viziato dalla presenza alcuni immobili o quartieri di lusso. Inoltre, Bryan-College Station mostra la maggiore variabilità sia nel prezzo medio (±15149$) sia nel numero di vendite (±85). La città di Tyler domina in numero di vendite medio (270). Wichita Falls è la città con il prezzo medio più basso (119430$) e con in media meno vendite (116).
Ho voluto indagare un possibile trade-off tra prezzo medio e numero di vendite, elaborando un grafico a punti. Bryan-College Station (prezzi alti, vendite medie) e Tyler (prezzi medi, vendite alte) mostrano infatti una relazione inversa, mentre Wichita Falls (prezzi bassi, vendite basse) e Beaumont (prezzi medi, vendite medie) sfuggono a questo schema.
ggplot(data_ret, aes(x = mean_price, y = sales, label = city)) +
geom_point(aes(color=city),
size = 2) +
labs(x = "Prezzo medio",
y = "Vendite",
title = "Vendite/prezzo medio per città",
color = "Città")+
scale_color_brewer(palette = "Set2")+
scale_x_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light()
Per proseguire l’analisi ho preferito considerare in parallelo anche la distribuzione del prezzo medio.
| città | Beaumont | Bryan-College Station | Tyler | Wichita Falls |
|---|---|---|---|---|
| min | 106700 | 140700 | 120600 | 73800 |
| q1 | 123025 | 150800 | 133975 | 92800 |
| median | 130750 | 155400 | 142200 | 102300 |
| mean | 129988 | 157488 | 141442 | 101743 |
| q3 | 134550 | 161975 | 147675 | 109175 |
| max | 163800 | 180000 | 161600 | 135300 |
| range | 57100 | 39300 | 41000 | 61500 |
| IQR | 11525 | 11175 | 13700 | 16375 |
| city | Beaumont | Bryan-College Station | Tyler | Wichita Falls |
|---|---|---|---|---|
| min | 120713 | 151816 | 143464 | 97010 |
| q1 | 141631 | 170685 | 158750 | 111597 |
| median | 145809 | 183185 | 167224 | 119785 |
| mean | 146640 | 183534 | 167677 | 119430 |
| q3 | 153598 | 194513 | 175050 | 125446 |
| max | 174724 | 213234 | 193787 | 148775 |
| range | 54011 | 61418 | 50323 | 51765 |
| IQR | 11967 | 23828 | 16300 | 13849 |
Il confronto tra prezzo mediano e medio nelle quattro città rivela un mercato immobiliare stratificato, in cui è presente una differenza sistematica tra media e mediana in tutte le città (in media +22088$).
Bryan-College Station si conferma come località più prestigiosa, con il prezzo mediano (mediana 155400$) e medio (mediana 183185$) nettamente superiori alle altre città; la marcata differenza tra le due metriche (+27785$) può essere considerata un segno dell’influenza di immobili di lusso.
Wichita Falls resta la città più economica, con il prezzo mediano (mediana 102300$) e medio (mediana 119430$) significativamente inferiori. La modesta differenza media-mediana (+17130$) suggerisce una distribuzione più equilibrata.
Come confermato anche dal seguente grafico a dispersione non sono presenti significativi outliers, ad eccezione di un valore per Beaumont. Viene mostrata una evidente correlazione positiva, quasi lineare, tra prezzo medio e mediano.
ggplot(data_ret, aes(x = mean_price, y = median_price, label = city)) +
geom_point(aes(color=city),
size = 1.5) +
labs(x = "Prezzo medio",
y = "Prezzo mediano",
title = "Prezzo mediano/prezzo medio per città",
color = "Città")+
scale_x_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "),
limits = c(73000, 220000),
breaks = seq(75000, 250000, by = 50000)) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "),
limits = c(73000, 220000),
breaks = seq(75000, 250000, by = 50000)) +
coord_equal() +
scale_color_brewer(palette = "Set2")+
theme_light()
data_perc_moth_city_sales <- data_ret %>%
group_by(month, city) %>%
summarise(total_sales = sum(sales), .groups = 'drop') %>%
group_by(month) %>%
mutate(percent = total_sales/sum(total_sales)) %>%
ungroup()
ggplot(data_perc_moth_city_sales, aes(x = as.integer(month), y = percent, fill = city)) +
geom_col(position = "fill") +
geom_text(aes(label = percent(percent, accuracy = 1)),
position = position_fill(vjust = 0.5),
size = 4, color = "white",
fontface = "bold") +
scale_x_continuous(
breaks = 1:12,
labels = months
) +
scale_y_continuous(labels = percent_format()) +
scale_fill_brewer(palette = "Set2") +
labs(
x = NULL,
y = NULL,
title = "Distribuzione aggregata delle vendite (2010-2014)",
fill = "Città"
) +
theme_light()+
theme(legend.position = "top")
L’analisi integrata dei tre grafici conferma un mercato immobiliare caratterizzato da forti disparità geografiche e una marcata stagionalità, evidenziando un picco estivo generalizzato, sostenuto soprattutto dalle città di Tyler e Bryan-College Station.
Tyler emerge come il motore principale, con una quota di mercato costantemente superiore al 34%. Segue Bryan-College Station, dai prezzi più elevati, che mantiene livelli meno costanti con un’escursione del 12% (21-33%). Beaumont (20-26%) e Wichita Falls (13-16%) mostrano un mercato piuttosto stabile, con un leggero aumento percentuale in autunno e inverno.
data_ret_aggr_volume <- data_ret %>%
group_by(date_var) %>%
summarise(total_volume = sum(volume, na.rm = TRUE), .groups = 'drop')
ggplot(data = data_ret_aggr_volume) +
geom_line(aes(
x=date_var,
y=total_volume)
) +
scale_x_date(
breaks = "1 year",
labels = scales::date_format("%b %Y"),
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M", big.mark = ".", decimal.mark = ","),
n.breaks = 8
) +
geom_smooth(aes(
x = date_var,
y = total_volume),
method = "lm",
color = "red",
se = FALSE) +
labs(
y = NULL,
x = NULL,
title = "Andamento del volume delle vendite")+
theme_light()
data_aggr_volume_year <- data_ret %>%
group_by(year, month) %>%
summarise(total_volume = sum(volume), .groups = 'drop')
ggplot(data_aggr_volume_year) +
geom_line(aes(
x = month,
y = total_volume,
color = as.character(year)),
linewidth = 1
) +
geom_point(aes(
x = month,
y = total_volume,
color = as.character(year)),
size = 2
) +
scale_x_continuous(
breaks = 1:12,
labels = months
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M", big.mark = ".", decimal.mark = ","),
n.breaks = 8
) +
labs(
x = NULL,
y = NULL,
title = "Confronto tra annate del volume delle vendite"
) +
scale_color_manual(
values = colorRampPalette(c("lightgreen", "darkgreen"))(5),
name = "Anno"
)+
theme_light() +
theme(
legend.position = "top",
)
ggplot(data = data_ret) +
geom_line(aes(x = date_var, y = volume, color = city)) +
geom_smooth(aes(x = date_var, y = volume, color = city), method = "lm", se = FALSE) +
labs(
x = NULL,
y = NULL,
color = "Città",
title = "Andamento del volume delle vendite per città (2010-2014)"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M", big.mark = ".", decimal.mark = ",")
) +
scale_x_date(
breaks = "1 year",
labels = scales::date_format("%b\n%Y"),
) +
scale_color_brewer(palette = "Set2")+
theme_light()+
theme(legend.position = "top")
ggplot(data = data_ret) +
geom_line(aes(x = date_var, y = volume, color = city)) +
geom_smooth(aes(x = date_var, y = volume, color = city), method = "lm", se = FALSE) +
facet_wrap(~ city,
labeller = labeller(city = NULL)) +
labs(
x = NULL,
y = NULL,
color = "Città",
title = "Andamento del volume delle vendite nel tempo per città (2010-2014)"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M", big.mark = ".", decimal.mark = ",")
) +
scale_x_date(
breaks = "1 year",
labels = scales::date_format("%b\n%Y"),
)+
scale_color_brewer(palette = "Set2")+
theme_light()+
theme(legend.position = "top",
strip.text = element_blank())
I grafici rivelano una crescita complessiva del volume delle vendite, e le città di Tyler e di Bryan-College Station si confermano come traino principale del mercato. Bryan-College Station mostra picchi elevati, ma anche una maggiore volatilità stagionale. Tyler, invece, mantiene volumi medi più consistenti e una tendenza stabile, indicando un mercato solido e meno sensibile alle fluttuazioni. Beaumont registra una crescita costante ma moderata, con minore variabilità rispetto alle città leader, riflettendo probabilmente un’espansione più graduale. Wichita Falls contribuisce in misura significativamente inferiore al totale, con una trascurabile crescita che riflette il suo ruolo marginale nel panorama analizzato.
Ho deciso di confrontare questi valori con il valore generato dal singolo annuncio, per comprendere in modo più approfondito il rendimento di ciascuna città e valutare eventuali strategie.
ggplot(data_ret, aes(x = city, y = volume, fill = city)) +
geom_boxplot(
alpha = 0.8,
outlier.color = "#E41A1C",
outlier.shape = 19
) +
stat_summary(
fun = mean,
geom = "point",
shape = 18,
size = 3,
color = "black"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M")) +
scale_fill_brewer(palette = "Set2") +
labs(
x = NULL,
y = NULL,
title = "Distribuzione per città del volume delle vendite",
subtitle = "Punto nero: media, punti rossi: outlier"
) +
theme_light() +
theme(
legend.position = "none",
plot.subtitle = element_text(size = 8))
ggplot(data_ret, aes(x = city, y = listing_value, fill = city)) +
geom_boxplot(
alpha = 0.8,
outlier.color = "#E41A1C",
outlier.shape = 19
) +
stat_summary(
fun = mean,
geom = "point",
shape = 18,
size = 3,
color = "black"
) +
scale_fill_brewer(palette = "Set2") +
labs(
x = NULL,
y = NULL,
title = "Distribuzione per città del valore generato da ogni annuncio attivo",
subtitle = "Punto nero: media, Punti rossi: outlier"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light() +
theme(
legend.position = "none",
plot.subtitle = element_text(size = 8))
ggplot(data_ret, aes(x = as.factor(year), y = volume, fill = year)) +
geom_boxplot(
alpha = 0.7,
outlier.color = "#E41A1C",
outlier.shape = 19,
show.legend = FALSE
) +
scale_fill_gradient(
low = "lightgreen",
high = "darkgreen",
guide = "none"
) +
stat_summary(
fun = mean,
geom = "point",
shape = 18,
size = 3,
color = "black"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", suffix = "M")) +
labs(
x = NULL,
y = NULL,
title = "Evoluzione annuale della distribuzione del volume delle vendite",
subtitle = "Punto nero: media, punti rossi: outlier"
) +
theme_light() +
theme(
plot.subtitle = element_text(size = 8))
ggplot(data_ret, aes(x = as.factor(year), y = listing_value, fill = year)) +
geom_boxplot(
alpha = 0.7,
outlier.color = "#E41A1C",
outlier.shape = 19,
show.legend = FALSE
) +
scale_fill_gradient(
low = "lightgreen",
high = "darkgreen",
guide = "none"
) +
stat_summary(
fun = mean,
geom = "point",
shape = 18,
size = 3,
color = "black"
) +
labs(
x = NULL,
y = NULL,
title = "Evoluzione annuale della distribuzione del valore generato da ogni annuncio attivo",
subtitle = "Punto nero: media, punti rossi: outlier"
) +
scale_y_continuous(
labels = scales::dollar_format(prefix = "$", big.mark = " "))+
theme_light() +
theme(
plot.title = element_text(size = 12),
plot.subtitle = element_text(size = 8))
I boxplot evidenziano un andamento parallelo tra il volume complessivo delle vendite e il valore generato per annuncio attivo, sebbene con dinamiche differenziate a livello territoriale.
L’incremento progressivo degli outlier nel valore generato per annuncio attivo segnala una disuguaglianza crescente nella performance degli annunci alimentata da transazioni eccezionali che superano di molto i valori medi.
Questo fenomeno sottolinea una marcata polarizzazione del mercato, ed è riconducibile a due fattori principali: la stagionalità delle transazioni e la presenza di un segmento premium, particolarmente pronunciato a Bryan-College Station, dove si concentrano immobili di lusso con valutazioni elevate.
Un aspetto interessante riguarda Wichita Falls: nonostante volumi di vendita sensibilmente inferiori rispetto alle altre città, il valore per annuncio non presenta scostamenti significativi da Tyler e Beaumont. Questo suggerisce che, pur in un contesto di minore liquidità, il mercato locale mantiene una discreta capacità di generare valore per singola transazione, seppur senza picchi particolarmente rilevanti. Il dato è confermato da un buona media del tasso di conversione tra annunci attivi e vendite.
| Città | % di conversione annunci / vendite | commento |
|---|---|---|
| Beaumont | 10.61 | Andamento medio senza picchi |
| Bryan-College Station | 14.73 | Performance migliore, domanda alta per immobili premium |
| Tyler | 9.35 | Più vendite, ma minore efficacia per annuncio (volume compensa) |
| Wichita Falls | 12.80 | Buona efficienza, mercato piccolo ma reattivo |
Per concludere vorrei fare qualche commento all’efficacia degli annunci, al fine di suggerire delle strategie per migliorare il mercato.
data_agg_listing_eff_city_month <- data_ret %>%
group_by(city, month) %>%
summarise(total_listing_eff = round(mean(listing_eff), 2), .groups = 'drop')
ggplot(data_agg_listing_eff_city_month, aes(x=city, y=month, fill=total_listing_eff)) +
geom_tile(color="white") +
geom_text(aes(label=paste0(round(total_listing_eff,1),"%")), color="black") +
labs(
title = "Efficacia degli annunci immobiliari per città e mese",
x = NULL,
y = NULL,
) +
scale_fill_gradient(low="lightgrey", high="purple")+
scale_y_continuous(
breaks = 1:12,
labels = months
) +
theme_light()+
theme(legend.position = "null")
L’analisi evidenzia come l’efficacia degli annunci vari significativamente tra città e stagioni. Bryan-College Station domina nei mesi estivi (picchi del 22% a luglio), confermando l’attrattiva del suo segmento premium, mentre Wichita Falls mantiene performance costanti (10-15% tutto l’anno) grazie a un mercato stabile. Tyler, nonostante l’alto volume di vendite, mostra un’efficacia inferiore (9.4%), suggerendo margini di miglioramento nel potenziale degli annunci.
Per ottimizzare i risultati si potrebbero realizzare campagne stagionali mirate e un pricing dinamico per capitalizzare i periodi di alta domanda.
Alcuni esempi:
Monitorare e adattare i prezzi in tempo reale basandosi sullo storico dei dati.
Diversificare la pubblicazione degli annunci: A Bryan-College Station, con un buon marketing, si potrebbe anticipare la domanda estiva per vendere immobili di fascia alta già nel mese di maggio.
Promozioni invernali, come sconti sulle commissioni.
Approfondire il caso della città di Tyler per migliorare la qualità dei suoi annunci.