Texas Realty Insights ha raccolto lo storico mensile delle compravendite residenziali in quattro città del Texas. L’obiettivo di questo report è descrivere il mercato con gli strumenti della statistica descrittiva: capire come si distribuiscono vendite, prezzi e annunci, come cambiano tra città, anni e mesi, e ricavarne delle indicazioni operative per le agenzie clienti.
library(ggplot2)
library(dplyr)
library(moments)
dati <- read.csv("realestate_texas.csv")
Prima di calcolare qualsiasi indice guardiamo com’è fatto il dataset.
dim(dati)
## [1] 240 8
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 ...
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
#valori assunti dalle variabili che identificano città e periodo
unique(dati$city)
## [1] "Beaumont" "Bryan-College Station" "Tyler"
## [4] "Wichita Falls"
unique(dati$year)
## [1] 2010 2011 2012 2013 2014
unique(dati$month)
## [1] 1 2 3 4 5 6 7 8 9 10 11 12
Il dataset ha 240 righe e 8 colonne, senza valori mancanti. Ogni riga
corrisponde a una città in un certo mese di un certo anno: ci sono 4
città (Beaumont, Bryan-College Station, Tyler e Wichita Falls), 5 anni
(dal 2010 al 2014) e 12 mesi, quindi 4 x 5 x 12 = 240 osservazioni.
Possiamo notare che R legge year e month come
numeri interi, ma in realtà identificano un periodo: di questo teniamo
conto nella classificazione.
| Variabile | Tipo | Analisi sensata |
|---|---|---|
| city | qualitativa nominale | distribuzione di frequenze, confronti tra città |
| year | temporale (qualitativa ordinale) | distribuzione di frequenze, raggruppamenti, serie storiche |
| month | temporale (qualitativa ordinale, ciclica) | distribuzione di frequenze, stagionalità |
| sales | quantitativa discreta | indici di posizione, variabilità e forma |
| volume | quantitativa continua (milioni di dollari) | indici di posizione, variabilità e forma |
| median_price | quantitativa continua (dollari) | indici di posizione, variabilità e forma |
| listings | quantitativa discreta | indici di posizione, variabilità e forma |
| months_inventory | quantitativa continua (mesi) | indici di posizione, variabilità e forma |
Le variabili year e month sono scritte come
numeri, ma calcolarne la media non avrebbe senso (il “mese medio” 6,5
non dice nulla sul mercato). Le trattiamo quindi come variabili
temporali: servono per raggruppare i dati (analisi per anno e per mese)
e, combinate tra loro, per costruire una data con cui disegnare le serie
storiche. Il mese ha anche una natura ciclica, utile per cercare la
stagionalità delle vendite.
#creiamo una variabile data (primo giorno del mese) per le serie storiche
dati$data <- as.Date(paste(dati$year, dati$month, "01", sep="-"))
N=dim(dati)[1]
#distribuzione di frequenze delle città
ni <- table(dati$city)
fi <- ni/N
cbind(ni, fi)
## ni fi
## Beaumont 60 0.25
## Bryan-College Station 60 0.25
## Tyler 60 0.25
## Wichita Falls 60 0.25
#distribuzione di frequenze degli anni
ni <- table(dati$year)
fi <- ni/N
cbind(ni, fi)
## ni fi
## 2010 48 0.2
## 2011 48 0.2
## 2012 48 0.2
## 2013 48 0.2
## 2014 48 0.2
#distribuzione di frequenze dei mesi
ni <- table(dati$month)
fi <- ni/N
cbind(ni, fi)
## ni fi
## 1 20 0.08333333
## 2 20 0.08333333
## 3 20 0.08333333
## 4 20 0.08333333
## 5 20 0.08333333
## 6 20 0.08333333
## 7 20 0.08333333
## 8 20 0.08333333
## 9 20 0.08333333
## 10 20 0.08333333
## 11 20 0.08333333
## 12 20 0.08333333
Le tre distribuzioni sono perfettamente uniformi: ogni città compare 60 volte (25%), ogni anno 48 volte (20%) e ogni mese 20 volte (8,3%). Il dataset è quindi bilanciato, e questo è importante perché nei confronti tra città o tra periodi nessun gruppo pesa più degli altri.
Per le cinque variabili quantitative calcoliamo gli indici di posizione (minimo, quartili, mediana, media, massimo), di variabilità (range, differenza interquartile, deviazione standard, coefficiente di variazione) e di forma (asimmetria e curtosi).
#coefficiente di variazione in percentuale
CV <- function(x){
return( sd(x)/mean(x) * 100 )
}
#funzione che calcola tutti gli indici per una variabile
indici <- function(x){
return( c(minimo = min(x),
Q1 = unname(quantile(x, 0.25)),
mediana = median(x),
media = mean(x),
Q3 = unname(quantile(x, 0.75)),
massimo = max(x),
range = max(x) - min(x),
IQR = IQR(x),
dev_std = sd(x),
CV = CV(x),
asimmetria = skewness(x),
curtosi = kurtosis(x) - 3) )
}
tabella_indici <- cbind(sales = indici(dati$sales),
volume = indici(dati$volume),
median_price = indici(dati$median_price),
listings = indici(dati$listings),
months_inventory = indici(dati$months_inventory))
round(tabella_indici, 2)
## sales volume median_price listings months_inventory
## minimo 79.00 8.17 73800.00 743.00 3.40
## Q1 127.00 17.66 117300.00 1026.50 7.80
## mediana 175.50 27.06 134500.00 1618.50 8.95
## media 192.29 31.01 132665.42 1738.02 9.19
## Q3 247.00 40.89 150050.00 2056.00 10.95
## massimo 423.00 83.55 180000.00 3296.00 14.90
## range 344.00 75.38 106200.00 2553.00 11.50
## IQR 120.00 23.23 32750.00 1029.50 3.15
## dev_std 79.65 16.65 22662.15 752.71 2.30
## CV 41.42 53.71 17.08 43.31 25.06
## asimmetria 0.72 0.88 -0.36 0.65 0.04
## curtosi -0.31 0.18 -0.62 -0.79 -0.17
#istogrammi delle variabili quantitative
par(mfrow = c(2, 3))
hist(dati$sales, main = "sales", xlab = "Numero di vendite", ylab = "Frequenze assolute", col = "lightblue")
hist(dati$volume, main = "volume", xlab = "Milioni di dollari", ylab = "Frequenze assolute", col = "lightblue")
hist(dati$median_price, main = "median_price", xlab = "Dollari", ylab = "Frequenze assolute", col = "lightblue")
hist(dati$listings, main = "listings", xlab = "Annunci attivi", ylab = "Frequenze assolute", col = "lightblue")
hist(dati$months_inventory, main = "months_inventory", xlab = "Mesi", ylab = "Frequenze assolute", col = "lightblue")
Commento
Tutte le curtosi sono vicine a zero o negative: nessuna variabile ha code particolarmente pesanti, cioè non ci sono valori estremi isolati ma piuttosto distribuzioni “larghe”, che mescolano città con dimensioni di mercato molto diverse.
Per capire quale variabile è più variabile non possiamo confrontare le deviazioni standard, perché dipendono dall’unità di misura: la deviazione standard del prezzo (22.662 dollari) è molto più grande di quella delle vendite (79,7) solo perché i prezzi sono espressi in dollari. Usiamo quindi il coefficiente di variazione, che rapporta la deviazione standard alla media ed è un numero puro, confrontabile tra variabili diverse. Per l’asimmetria usiamo l’indice di asimmetria di Fisher, che è già adimensionale.
round(tabella_indici[c("CV", "asimmetria"), ], 3)
## sales volume median_price listings months_inventory
## CV 41.422 53.705 17.082 43.308 25.060
## asimmetria 0.718 0.885 -0.365 0.649 0.041
La variabile con la maggiore variabilità è
volume, con un coefficiente di variazione del 53,7%: il
valore totale delle vendite cambia moltissimo tra una città e l’altra e
tra un periodo e l’altro, perché combina due fattori che variano
entrambi (numero di vendite e prezzo). Seguono listings
(43,3%) e sales (41,4%), mentre median_price è
la più stabile (17,1%).
La variabile con la distribuzione più asimmetrica è
ancora volume (asimmetria 0,885, in valore assoluto la più
alta), con una coda verso destra: la maggior parte dei mesi ha un volume
moderato, mentre pochi mesi di città grandi raggiungono valori molto
alti. months_inventory è invece praticamente simmetrica
(0,041).
Suddividiamo median_price in classi di ampiezza costante
pari a 20.000 dollari, da 70.000 a 190.000 dollari: in questo modo si
ottengono 6 classi che coprono tutti i valori osservati (minimo 73.800,
massimo 180.000) e corrispondono a fasce di prezzo facili da leggere per
chi lavora in agenzia.
#suddivisione in classi
prezzo_cl <- cut(dati$median_price,
breaks = seq(70000, 190000, 20000),
dig.lab = 6)
ni <- table(prezzo_cl)
fi <- ni/N
Ni <- cumsum(ni)
Fi <- Ni/N
distr_freq_prezzo <- as.data.frame(cbind(ni, fi, Ni, Fi))
distr_freq_prezzo
## ni fi Ni Fi
## (70000,90000] 11 0.04583333 11 0.04583333
## (90000,110000] 38 0.15833333 49 0.20416667
## (110000,130000] 46 0.19166667 95 0.39583333
## (130000,150000] 85 0.35416667 180 0.75000000
## (150000,170000] 54 0.22500000 234 0.97500000
## (170000,190000] 6 0.02500000 240 1.00000000
distr_freq_prezzo$classe <- factor(rownames(distr_freq_prezzo), levels = rownames(distr_freq_prezzo))
ggplot(data = distr_freq_prezzo)+
geom_col(aes(x = classe, y = ni), fill = "steelblue", col = "black")+
labs(x = "Classi di prezzo mediano ($)",
y = "Frequenze assolute",
title = "Distribuzione del prezzo mediano in classi")+
theme_bw()
Usiamo geom_col() perché la tabella contiene già le
frequenze calcolate: geom_bar() conterebbe di nuovo le
righe e darebbe un grafico sbagliato.
#indice di eterogeneità di Gini normalizzato
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)
}
gini.index(prezzo_cl)
## [1] 0.9112917
La classe più frequente è quella tra 130.000 e 150.000 dollari, che raccoglie il 35% dei mesi osservati; il 75% delle osservazioni ha un prezzo mediano fino a 150.000 dollari e solo il 2,5% supera i 170.000.
L’indice di Gini normalizzato vale 0,91, un valore vicino a 1: i prezzi mediani non sono concentrati in un’unica fascia ma sono distribuiti su quasi tutte le classi. Questo è coerente con la presenza di quattro mercati molto diversi tra loro: come vedremo, Wichita Falls si colloca nelle fasce più basse e Bryan-College Station in quelle più alte.
Le probabilità richieste sono frequentiste: si contano le righe che soddisfano la condizione e si dividono per il numero totale di righe (240).
#probabilità che una riga riporti la città Beaumont
p_beaumont <- sum(dati$city == "Beaumont") / N
#probabilità che una riga riporti il mese di luglio
p_luglio <- sum(dati$month == 7) / N
#probabilità che una riga riporti dicembre 2012 (condizione congiunta su anno e mese)
p_dicembre_2012 <- sum(dati$year == 2012 & dati$month == 12) / N
c(Beaumont = p_beaumont, Luglio = p_luglio, Dicembre_2012 = p_dicembre_2012)
## Beaumont Luglio Dicembre_2012
## 0.25000000 0.08333333 0.01666667
Prezzo medio degli immobili. Il volume è il valore totale delle vendite in milioni di dollari, quindi dividendolo per il numero di vendite si ottiene il prezzo medio di un immobile venduto in quel mese:
prezzo medio = volume x 1.000.000 / sales
Efficacia degli annunci. Per misurare quanto funzionano gli annunci rapportiamo le vendite del mese agli annunci attivi: è la percentuale di annunci che nel mese si sono trasformati in una vendita.
efficacia annunci (%) = sales / listings x 100
Un valore alto significa che una parte consistente degli immobili in
vendita trova un acquirente in poco tempo; un valore basso indica tanti
annunci fermi rispetto alle vendite. È un indicatore facile da leggere
in agenzia ed è legato a months_inventory, che misura la
stessa cosa al contrario (quanti mesi servirebbero per vendere
tutto).
dati$prezzo_medio <- dati$volume * 1000000 / dati$sales
dati$efficacia_annunci <- dati$sales / dati$listings * 100
summary(dati$prezzo_medio)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 97010 132939 156588 154320 173915 213234
summary(dati$efficacia_annunci)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.014 8.980 10.963 11.874 13.492 38.713
#confronto tra prezzo medio e prezzo mediano per città
dati %>%
group_by(city) %>%
summarise(prezzo_medio = mean(prezzo_medio),
prezzo_mediano = mean(median_price))
## # A tibble: 4 × 3
## city prezzo_medio prezzo_mediano
## <chr> <dbl> <dbl>
## 1 Beaumont 146640. 129988.
## 2 Bryan-College Station 183534. 157488.
## 3 Tyler 167677. 141442.
## 4 Wichita Falls 119430. 101743.
#mesi con l'efficacia più alta e più bassa
head(dati[order(-dati$efficacia_annunci), c("city", "year", "month", "sales", "listings", "efficacia_annunci")], 3)
## city year month sales listings efficacia_annunci
## 115 Bryan-College Station 2014 7 403 1041 38.71278
## 114 Bryan-College Station 2014 6 377 1152 32.72569
## 116 Bryan-College Station 2014 8 298 1016 29.33071
head(dati[order(dati$efficacia_annunci), c("city", "year", "month", "sales", "listings", "efficacia_annunci")], 3)
## city year month sales listings efficacia_annunci
## 133 Tyler 2011 1 143 2852 5.014025
## 131 Tyler 2010 11 155 3042 5.095332
## 1 Beaumont 2010 1 83 1533 5.414220
Il prezzo medio va da circa 97.000 a 213.000 dollari, con una media di 154.320. Possiamo notare che in tutte le città il prezzo medio è più alto del prezzo mediano (per esempio 183.534 contro 157.488 a Bryan-College Station): significa che, all’interno di ogni mese, la distribuzione dei prezzi di vendita ha una coda verso destra, cioè alcuni immobili molto costosi alzano la media. Per le agenzie il prezzo mediano è quindi il riferimento più affidabile del “prezzo tipico”.
L’efficacia degli annunci è in media dell’11,9%: in un mese tipico circa un annuncio su otto si trasforma in una vendita. I valori vanno dal 5% (Tyler a gennaio 2011) al 38,7% (Bryan-College Station a luglio 2014): i mesi più efficaci sono tutti estivi e tutti a Bryan-College Station negli ultimi anni.
per_citta <- dati %>%
group_by(city) %>%
summarise(media_vendite = round(mean(sales), 1),
devst_vendite = round(sd(sales), 1),
media_prezzo = round(mean(median_price)),
devst_prezzo = round(sd(median_price)),
media_volume = round(mean(volume), 1),
devst_volume = round(sd(volume), 1),
media_efficacia = round(mean(efficacia_annunci), 1),
devst_efficacia = round(sd(efficacia_annunci), 1))
as.data.frame(per_citta)
## city media_vendite devst_vendite media_prezzo devst_prezzo
## 1 Beaumont 177.4 41.5 129988 10105
## 2 Bryan-College Station 206.0 85.0 157488 8852
## 3 Tyler 269.8 62.0 141442 9337
## 4 Wichita Falls 116.1 22.2 101743 11320
## media_volume devst_volume media_efficacia devst_efficacia
## 1 26.1 7.0 10.6 2.7
## 2 38.2 17.2 14.7 7.3
## 3 45.8 13.1 9.3 2.3
## 4 13.9 3.2 12.8 2.5
ggplot(per_citta)+theme_bw()+
geom_col(aes(x = city, y = media_vendite), fill = "steelblue")+
geom_errorbar(aes(x = city,
ymin = media_vendite - devst_vendite,
ymax = media_vendite + devst_vendite),
width = 0.3, col = 2)+
labs(x = "Città",
y = "Vendite mensili (media ± dev. std)",
title = "Vendite medie mensili per città")
ggplot(per_citta)+theme_bw()+
geom_col(aes(x = city, y = media_efficacia), fill = "darkgreen")+
geom_errorbar(aes(x = city,
ymin = media_efficacia - devst_efficacia,
ymax = media_efficacia + devst_efficacia),
width = 0.3, col = 2)+
labs(x = "Città",
y = "Efficacia degli annunci, % (media ± dev. std)",
title = "Efficacia media degli annunci per città")
Le quattro città sono mercati molto diversi:
per_anno <- dati %>%
group_by(year) %>%
summarise(media_vendite = round(mean(sales), 1),
devst_vendite = round(sd(sales), 1),
media_prezzo = round(mean(median_price)),
devst_prezzo = round(sd(median_price)),
media_annunci = round(mean(listings), 1),
media_efficacia = round(mean(efficacia_annunci), 1),
devst_efficacia = round(sd(efficacia_annunci), 1))
as.data.frame(per_anno)
## year media_vendite devst_vendite media_prezzo devst_prezzo media_annunci
## 1 2010 168.7 60.5 130192 21822 1826.0
## 2 2011 164.1 63.9 127854 21318 1849.6
## 3 2012 186.1 70.9 130077 21432 1776.8
## 4 2013 211.9 84.0 135723 21708 1677.6
## 5 2014 230.6 95.5 139481 25625 1560.0
## media_efficacia devst_efficacia
## 1 10.0 3.4
## 2 9.3 2.3
## 3 11.0 2.8
## 4 13.5 4.5
## 5 15.7 6.2
ggplot(per_anno)+theme_bw()+
geom_line(aes(x = year, y = media_vendite), col = "steelblue", lwd = 1)+
geom_point(aes(x = year, y = media_vendite), col = "steelblue", size = 3)+
geom_errorbar(aes(x = year,
ymin = media_vendite - devst_vendite,
ymax = media_vendite + devst_vendite),
width = 0.2, col = 2)+
labs(x = "Anno",
y = "Vendite mensili (media ± dev. std)",
title = "Vendite medie mensili per anno")
Dal 2011 il mercato è in crescita costante: le vendite medie mensili passano da 164 nel 2011 a 231 nel 2014 (circa +40%), il prezzo mediano sale da circa 127.900 a 139.500 dollari e gli annunci attivi diminuiscono (da circa 1.850 a 1.560). Di conseguenza l’efficacia degli annunci migliora ogni anno, dal 9,3% del 2011 al 15,7% del 2014. Le barre di errore sono ampie perché all’interno di ogni anno ci sono città molto diverse tra loro.
per_mese <- dati %>%
group_by(month) %>%
summarise(media_vendite = round(mean(sales), 1),
devst_vendite = round(sd(sales), 1),
media_prezzo = round(mean(median_price)),
devst_prezzo = round(sd(median_price)),
media_efficacia = round(mean(efficacia_annunci), 1),
devst_efficacia = round(sd(efficacia_annunci), 1))
as.data.frame(per_mese)
## month media_vendite devst_vendite media_prezzo devst_prezzo media_efficacia
## 1 1 127.4 43.4 124250 25151 8.3
## 2 2 140.8 51.1 130075 22823 8.8
## 3 3 189.4 59.2 127415 23442 11.6
## 4 4 211.7 65.4 131490 21458 12.5
## 5 5 238.8 83.1 134485 18796 14.1
## 6 6 243.6 95.0 137620 19231 14.2
## 7 7 235.8 96.3 134750 21945 14.3
## 8 8 231.4 79.2 136675 22488 14.2
## 9 9 182.3 72.5 134040 24344 11.2
## 10 10 179.9 75.0 133480 26358 11.2
## 11 11 156.8 55.5 134305 24691 10.2
## 12 12 169.4 60.7 133400 22810 11.7
## devst_efficacia
## 1 2.3
## 2 2.2
## 3 3.5
## 4 3.8
## 5 5.0
## 6 5.8
## 7 7.4
## 8 5.3
## 9 3.5
## 10 3.6
## 11 2.9
## 12 3.8
ggplot(per_mese)+theme_bw()+
geom_col(aes(x = factor(month), y = media_vendite), fill = "steelblue")+
geom_errorbar(aes(x = factor(month),
ymin = media_vendite - devst_vendite,
ymax = media_vendite + devst_vendite),
width = 0.3, col = 2)+
labs(x = "Mese",
y = "Vendite mensili (media ± dev. std)",
title = "Vendite medie per mese")
Le vendite hanno una stagionalità molto chiara: sono basse a gennaio e febbraio (127 e 141 vendite in media), crescono in primavera e raggiungono il massimo tra maggio e agosto (oltre 230 vendite, con il picco di giugno a 244), per poi scendere in autunno. Anche l’efficacia degli annunci segue lo stesso andamento: supera il 14% da maggio ad agosto, contro l’8-9% di gennaio e febbraio. Il prezzo mediano invece varia poco durante l’anno.
ggplot(data = dati)+
geom_boxplot(aes(x = city, y = median_price), fill = "lightblue")+
labs(x = "Città",
y = "Prezzo mediano ($)",
title = "Distribuzione del prezzo mediano per città")+
theme_bw()
Il boxplot conferma che le città si differenziano soprattutto per il livello dei prezzi: Bryan-College Station ha la distribuzione più alta (mediana intorno a 155.000 dollari), Wichita Falls la più bassa (intorno a 102.000), con Tyler e Beaumont in mezzo. Le distribuzioni di Bryan-College Station e Wichita Falls non si sovrappongono per niente: si tratta di due mercati con fasce di prezzo completamente diverse. Wichita Falls ha anche la scatola più ampia, quindi i prezzi più variabili da un mese all’altro, mentre Beaumont ha un valore anomalo in alto (163.800 dollari a gennaio 2010).
ggplot(data = dati)+
geom_boxplot(aes(x = city, y = volume, fill = factor(year)))+
labs(x = "Città",
y = "Volume delle vendite (milioni di $)",
fill = "Anno",
title = "Distribuzione del volume delle vendite per città e anno")+
theme_bw()
Il volume cresce negli anni in tre città su quattro: a Tyler e a Bryan-College Station i box del 2014 sono nettamente più alti di quelli del 2010-2011, e lo stesso vale, in misura minore, per Beaumont. Wichita Falls invece rimane stabile intorno ai 14 milioni al mese. Bryan-College Station ha anche box molto allungati, segno di una forte differenza tra i mesi estivi e quelli invernali.
vendite_mese_citta <- dati %>%
group_by(month, city) %>%
summarise(vendite = sum(sales))
ggplot(data = vendite_mese_citta)+
geom_col(aes(x = factor(month), y = vendite, fill = city), position = "stack", col = "black")+
labs(x = "Mese",
y = "Totale vendite (2010-2014)",
fill = "Città",
title = "Totale vendite per mese e città")+
theme_bw()
ggplot(data = vendite_mese_citta)+
geom_col(aes(x = factor(month), y = vendite, fill = city), position = "fill", col = "black")+
labs(x = "Mese",
y = "Quota delle vendite (da 0 a 1)",
fill = "Città",
title = "Composizione delle vendite mensili per città (normalizzato)")+
theme_bw()
Il primo grafico mostra il totale delle vendite di ogni mese nei cinque anni: si vede bene il picco estivo, che riguarda tutte le città. Il grafico normalizzato mostra invece la quota di ogni città sul totale del mese: Tyler pesa sempre circa un terzo delle vendite, Wichita Falls circa il 15%. Le quote cambiano poco durante l’anno, con una sola eccezione: Bryan-College Station passa dal 22-23% delle vendite nei mesi invernali a quasi un terzo tra maggio e luglio, quindi è la città con la stagionalità più forte.
Per inserire l’informazione sull’anno nello stesso blocco grafico
usiamo un pannello per ogni anno (facet_wrap): ogni riga di
pannelli mostra le vendite mensili di un anno, divise per città.
ggplot(data = dati)+
geom_col(aes(x = factor(month), y = sales, fill = city), position = "stack")+
facet_wrap(~year, ncol = 1)+
labs(x = "Mese",
y = "Vendite",
fill = "Città",
title = "Vendite mensili per città, anno per anno")+
theme_bw()+
theme(legend.position = "bottom")
Con un pannello per anno si vede che la stagionalità si ripete ogni anno con la stessa forma, ma che le barre diventano più alte dal 2012 in poi: il picco estivo del 2014 supera di molto quello del 2010 e del 2011.
ggplot(data = dati)+
geom_line(aes(x = data, y = median_price, col = city), lwd = 0.8)+
labs(x = "Data",
y = "Prezzo mediano ($)",
col = "Città",
title = "Andamento del prezzo mediano nel tempo")+
theme_bw()
Per costruire il line chart usiamo la variabile data,
creata unendo anno e mese: se mettessimo sull’asse x solo il mese, R
collegherebbe i punti dei diversi anni in un’unica linea a zig-zag,
illeggibile. Il grafico mostra che Bryan-College Station è quasi sempre
la città più cara e Wichita Falls la più economica, con prezzi che
oscillano molto da un mese all’altro. Dal 2013 i prezzi salgono
sopratutto a Bryan-College Station e a Tyler.
efficacia_anno_citta <- dati %>%
group_by(city, year) %>%
summarise(efficacia = mean(efficacia_annunci))
ggplot(data = efficacia_anno_citta)+
geom_line(aes(x = year, y = efficacia, col = city), lwd = 1)+
geom_point(aes(x = year, y = efficacia, col = city), size = 2)+
labs(x = "Anno",
y = "Efficacia degli annunci (%)",
col = "Città",
title = "Efficacia media degli annunci per città e anno")+
theme_bw()
L’efficacia degli annunci migliora in tutte le città dal 2011 in poi, ma con velocità molto diverse. A Bryan-College Station passa dal 10,6% del 2010 al 23,6% del 2014: quasi un annuncio su quattro viene venduto ogni mese. Tyler e Beaumont migliorano in modo costante (fino al 12,4% e al 13,5%), mentre Wichita Falls oscilla tra l’11% e il 14% senza una vera tendenza.
L’analisi descrive un mercato immobiliare in crescita tra il 2010 e il 2014, con quattro città molto diverse per dimensione e livello dei prezzi e una forte stagionalità comune.
Tendenze principali
volume è la variabile più variabile e più asimmetrica,
perché somma le differenze di dimensione e di prezzo tra le città; il
prezzo mediano è invece la grandezza più stabile.Sulla base dell’analisi effettuata, proponiamo le seguenti raccomandazioni per le agenzie clienti: