Partiamo caricando il nostro dataset estratto dal file “realestate_texas.csv” assegnato a un dataframe.
#importiamo il dataset in csv nello spazio di lavoro
realestate_stats = read.csv("realestate_texas.csv", sep=",")
Per avere un’idea degli oggetti e delle variabili nel dataset, stampiamo le prime righe del dataframe e facciamo un conteggio di osservazioni e variabili presenti:
#leggiamo le prime righe del dataset e visualizziamo la quantità di oggetti e variabili
head(realestate_stats)
#leggiamo le prime righe del dataset e visualizziamo la quantità di oggetti e variabili
dim(realestate_stats)
## [1] 240 8
Procediamo a identificare le tipologie di variabili nel dataset, e a commentarle preliminarmente.
#Identifichiamo le tipologie di variabili nel dataset
str(realestate_stats)
## '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 ...
Il dataset allegato al progetto di analisi esplorativa del mercato immobiliare texano prevede 8 variabili statistiche con 240 oggetti, esse sono:
Città: variabile qualitativa di tipo nominale. Utile alla contestualizzazione delle altre variabili per via della natura mutualmente esclusiva di questo tipo di variabile, nonchè necessaria al calcolo della moda per le n osservazioni.
Anno: Variabile quantitativa continua, in questo caso trattata come qualitativa ordinale. Particolarmente utile per un confronto sull’andamento del mercato immobiliare nelle 4 città considerate, con la costruzione di un grafico che paragoni le relative serie storiche con i dati a disposizione.
Mese: Variabile qualitativa nominale ciclica, codificata in numeri. Le serie storiche mensili non solo possono aumentare la risoluzione del grafico di confronto fra gli anni presenti nel dataset, ma permettono di identificare cicli annuali specifici delle stagioni e di comprendere i trend in termini di volumi di vendita mensili, in comparazione con gli stessi periodi di anni successivi o precedenti.
Vendite (Sales): Variabile quantitativa discreta su scala di rapporti. La quantità di vendite effettuate nel mese considerato. Costruendo una serie storica con questi dati possiamo identificare i trend annuali e cicli stagionali/mensili negli anni del dataset, inoltre possiamo identificare le differenze in termine di numero di vendite effettuate per gli stessi periodi dell’anno in città diverse, insieme ai volumi totali di vendita, per capire in quale città si effettuano più vendite e in quale periodo.
Volume totale di vendita: Variabile quantitativa continua su scala di rapporti. Il volume totale di vendita può darci un’idea del comportamento del mercato e delle performance aziendali sia confrontandolo su scala annuale che mensile, sia confrontandolo con altre variabili, come il numero di inserzioni attive, per ipotizzare sull’influenza che esse hanno sul volume totale di vendita stesso. Espresso in USD.
Prezzo mediano: Variabile quantitativa continua su scala di rapporti. Variazioni nel prezzo mediano di vendita su lungo termine possono permettere di identificare trend relativi al mercato immobiliare della città presa in considerazione, e fare paragoni di lungo periodo sulle tendenze di prezzo nelle varie città del dataset.
Inserzioni: Variabile quantitativa discreta. Il quantitativo di inserzioni attive per il mese considerato nel dataset può essere confrontato col quantitativo di vendite, e con i volumi, per individuare eventuali correlazioni fra le variabili e l’influenza effettiva che il numero di inserzioni immobiliari attive hanno su di esse.
Months per Inventory: Tempo richiesto allo smaltimento dell’inventario in inserzione, espresso in mesi. Variabile quantitativa continua su scala di rapporti. Un eventuale aumento eccessivo del tempo richiesto per lo smaltimento dell’inventario può essere spia di un mercato saturo o di una domanda inconsisente, mentre un tempo troppo breve può segnalare un calo dell’offerta da parte dei proprietari di immobili.
Identificata la natura delle variabili presenti nel dataset, procediamo ad effettuare un’analisi dei principali indici statistici di ognuna. Il percorso logico applicato è quello di ridurre il problema generale (“la massa di dati da analizzare”), in problemi più piccoli che possiamo esplorare singolarmente (“Le informazioni restituite dall’elaborazione di ogni singola variabile”).
R non prevede una funzione specifica per il calcolo della moda di una variabile, per cui decidiamo di costruire la nostra funzione personalizzata a questo scopo:
#La moda non è calcolabile su R tramite una funzione diretta
#quindi svilupperemo la funzione noi stessi
mode = function(x){
u = unique(x)
tab = tabulate(match(x, u))
u[tab == max(tab)]
}
Procediamo quindi ad utilizzare la nostra funzione mode() per calcolare la moda della variabile city del dataset:
city_mode = c(realestate_stats$city)
mode(city_mode)
## [1] "Beaumont" "Bryan-College Station" "Tyler"
## [4] "Wichita Falls"
La soluzione ci suggerisce che possiamo trovarci davanti ad una variabile quadrimodale, per effettuare tale verifica chiamiamo la funzione table sulla variabile $city e osserviamo il risultato:
#Usiamo la funzione table per verificare la natura modale di city
table(realestate_stats$city)
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
Il risultato parla chiaro. city è una variabile quadrimodale con lo stesso numero di osservazioni per ogni città del dataset.
Con city che svela la sua natura quadrimodale, possiamo ipotizzare che ciò dipenda da un periodo di osservazione uguale per ognuno degli agglomerati urbani di interesse. A questo punto verifichiamo che ciò sia vero trovando il min e il max della variabile year:
#min e max per la variabile year
min(realestate_stats$year)
## [1] 2010
max(realestate_stats$year)
## [1] 2014
Si tratta quindi di 5 anni di osservazioni, le quali potrebbero essere ulteriormente divise in mesi. Se così non fosse, non si spiegherebbero le 60 osservazioni per città sulla variabile city. La soluzione migliore è costruire una distribuzione di frequenze per avere un quadro chiaro.
#distribuzione di frequenze della variabile year
cytable = addmargins(table(realestate_stats$city, realestate_stats$year), 2)
print(cytable)
##
## 2010 2011 2012 2013 2014 Sum
## Beaumont 12 12 12 12 12 60
## Bryan-College Station 12 12 12 12 12 60
## Tyler 12 12 12 12 12 60
## Wichita Falls 12 12 12 12 12 60
Abbiamo quindi la conferma che, con 12 osservazioni per anno per ognuna delle città, il dataset deve essere diviso in mesi. Questo ci porta alla variabile successiva.
Calcolando il range della variabile month possiamo sapere se tutti e 12 i mesi sono presenti.
#range variabile month
range(realestate_stats$month)
## [1] 1 12
e possiamo stampare il risultato esteso per una conferma visiva.
#Un'ultima verifica sulla presenza di tutti e 12 i mesi per ogni anno
#si può effettuare prendendo le prime 12 righe della variabile month dal dataset
print(realestate_stats$month[1:12])
## [1] 1 2 3 4 5 6 7 8 9 10 11 12
Presa in considerazione la natura di questa variabile, non avrebbe senso procedere col calcolo di altri indici di posizione, forma o variabilità per month, ma come variabile temporale potrà tornare molto utile successivamente.
Per la quantità di vendite effettuate mensilmente in ognuna delle città nell’arco dei cinque anni possiamo variare la risoluzione dei nostri calcoli su più livelli.
Innanzitutto calcoliamo gli indici di posizione globali per l’intera variabile sales, cominciando dal min/max.
#Variabile sales. Calcoliamo e stampiamo il min/max
minsales = min(realestate_stats$sales)
maxsales = max(realestate_stats$sales)
sprintf("Il minimo della variabile sales è: %i", minsales)
## [1] "Il minimo della variabile sales è: 79"
sprintf("Il massimo della variabile sales è: %i", maxsales)
## [1] "Il massimo della variabile sales è: 423"
Calcoliamo la mediana per la quantità di vendite di tutte le città nei 5 anni considerati:
#Calcoliamo la mediana
mediansales = median(realestate_stats$sales)
sprintf("La mediana della variabile sales é: %.2f", mediansales)
## [1] "La mediana della variabile sales é: 175.50"
Otteniamo anche la media della variabile sales:
#calcoliamo la media della variabile sales
meansales = mean(realestate_stats$sales)
sprintf("La media delle quantità vendute in tutte le città e in tutti gli anni considerati è: %.2f", meansales)
## [1] "La media delle quantità vendute in tutte le città e in tutti gli anni considerati è: 192.29"
Avendo già min/max e media, estrapoliamo i restanti quartili con la funzione quantile() come segue:
#calcoliamo i quartili di sales
quantile_sales = quantile(realestate_stats$sales, probs= c(.25,.75))
print(quantile_sales)
## 25% 75%
## 127 247
Partiamo calcolando l’intervallo di viariazione.
#calcoliamo l'intervallo di variazione di sales:
varinterval = (maxsales-minsales)
sprintf("L'intervallo di variazione per sales é: %i", varinterval)
## [1] "L'intervallo di variazione per sales é: 344"
Otteniamo il range interquartile con la funzione apposita.
#procediamo calcolando il range interquartile di sales:
intersales = IQR(realestate_stats$sales)
sprintf("Il range interquartile della variabile sales è: %i", intersales)
## [1] "Il range interquartile della variabile sales è: 120"
Otteniamo la varianza di sales con la funzione apposita.
#calcoliamo la varianza della variabile sales:
salesvar = var(realestate_stats$sales)
sprintf("La variabile sales presenta una varianza di: %.1f", salesvar)
## [1] "La variabile sales presenta una varianza di: 6344.3"
Otteniamo anche la deviazione standard di sales con la funzione apposita.
#Passiamo poi a calcolare la deviazione standard con la funzione apposita:
stand_dev_sales = sd(realestate_stats$sales)
sprintf("La deviazione standard di sales è: %.3f", stand_dev_sales)
## [1] "La deviazione standard di sales è: 79.651"
Non essendoci osservazioni nulle o negative nella variabile sales, possiamo calcolare anche il coefficiente di variazione, dovendoci però costruire una funzione apposita perchè assente dal pacchetto base di R.
#Creiamo la funzione del coefficiente di variazione.
coeff_var = function(x){
return(sd(x)/mean(x)*100)
}
#Procediamo al calcolo per la variabile sales
salescv = coeff_var(realestate_stats$sales)
sprintf("Il coefficiente di variazione di sales è: %.3f", salescv)
## [1] "Il coefficiente di variazione di sales è: 41.422"
Non trattandosi di una variabile qualitativa, tralasceremo l’indice di eterogeneità di Gini perchè non avrebbe senso calcolarlo, passiamo agli indici di forma.
Il primo indice di forma che vogliamo calcolare è l’indice di asimmetria di Fisher. Per questa prima variabile costruiremo le formule a mano a dimostrazione del processo utilizzato.
#Procediamo a calcolare, per questa prima volta, l'indice di asimmetria a mano
salesn = length(realestate_stats$sales)
salesm3 = sum((realestate_stats$sales-meansales)^3)/salesn
asimmetry_sales_index = salesm3/stand_dev_sales^3
plot(density(realestate_stats$sales))
abline(v=meansales, col="red")
sprintf("L'indice di asimmetria di sales è: %.3f", asimmetry_sales_index)
## [1] "L'indice di asimmetria di sales è: 0.714"
Calcoliamo ora la Curtosi costruendo la formula apposita.
#Calcoliamo la curtosi manualmente
salesm4 = sum((realestate_stats$sales-meansales)^4)/salesn
kurtosis_sale_index = salesm4/stand_dev_sales^4 -3
sprintf("L'indice di curtosi di sales è: %.3f", kurtosis_sale_index)
## [1] "L'indice di curtosi di sales è: -0.336"
Notiamo come l’indice di asimmetria di Fisher restituisca un’asimmetria positiva. La distribuzione ha quindi una prevalenza di valori/modalità basse.
L’indice di curtosi ci comunica inoltre la tendenza della distribuzione ad essere platicurtica, cioè appiattita rispetto ad una distribuzione normale.
Variabile volume, indici di posizione.
#Passiamo alla variabile volume. Indici di posizione
minvolume = min(realestate_stats$volume)
maxvolume = max(realestate_stats$volume)
meanvolume = mean(realestate_stats$volume)
medianvolume = median(realestate_stats$volume)
quantile_volume = quantile(realestate_stats$volume, probs = c(.25, .75))
sprintf("La variabile volume ha un min/max di: %.3f %.3f", minvolume, maxvolume)
## [1] "La variabile volume ha un min/max di: 8.166 83.547"
sprintf("La variabile volume ha una media di: %.3f", meanvolume)
## [1] "La variabile volume ha una media di: 31.005"
sprintf("La variabile volume ha una mediana di: %.3f", medianvolume)
## [1] "La variabile volume ha una mediana di: 27.062"
print(quantile_volume)
## 25% 75%
## 17.6595 40.8930
Variabile volume, indici di variabilità.
#volume, indici di variabilità
volumevarinterval = (maxvolume-minvolume)
interquartile_volume = IQR(realestate_stats$volume)
volumevar = var(realestate_stats$volume)
volumesd = sd(realestate_stats$volume)
volume_coeff_var = coeff_var(realestate_stats$volume)
sprintf("L'intervallo di variazione di volume è: %.3f", volumevarinterval)
## [1] "L'intervallo di variazione di volume è: 75.381"
sprintf("Il range interquartile di volume è: %.3f", interquartile_volume)
## [1] "Il range interquartile di volume è: 23.233"
sprintf("La varianza di volume è: %.3f", volumevar)
## [1] "La varianza di volume è: 277.271"
sprintf("La deviazione standard di volume è: %.3f", volumesd)
## [1] "La deviazione standard di volume è: 16.651"
sprintf("Il coefficiente di variazione di volume è: %.3f", volume_coeff_var)
## [1] "Il coefficiente di variazione di volume è: 53.705"
Variabile volume, indici di forma.
Per velocizzare il calcolo degli indici di forma da questo momento userò le funzioni skewness e kurtosis del pacchetto moments.
#volume, indici di forma
library("moments")
asimmetry_volume_index = skewness(realestate_stats$volume)
kurtosis_volume_index = kurtosis(realestate_stats$volume)-3
plot(density(realestate_stats$volume))
abline(v=meanvolume, col="red")
sprintf("L'indice di asimmetria di volume è: %.3f", asimmetry_volume_index)
## [1] "L'indice di asimmetria di volume è: 0.885"
sprintf("L'indice di curtosi di volume è: %.3f", kurtosis_volume_index)
## [1] "L'indice di curtosi di volume è: 0.177"
Volume ha un’asimmetria positiva, quindi anche per questa variabile si osservano modalità prevalentemente basse, con una curtosi pertinente ad una distribuzione leptocurtica.
Variabile median_price, indici di posizione.
#median_price, indici di posizione
minmp = min(realestate_stats$median_price)
maxmp = max(realestate_stats$median_price)
meanmp = mean(realestate_stats$median_price)
medianmp = median(realestate_stats$median_price)
quantile_mp = quantile(realestate_stats$median_price, probs = c(.25, .75))
sprintf("La variabile median_price ha un min/max di: %i %i", minmp, maxmp)
## [1] "La variabile median_price ha un min/max di: 73800 180000"
sprintf("La variabile median_price ha una media di: %.3f", meanmp)
## [1] "La variabile median_price ha una media di: 132665.417"
sprintf("La variabile median_price ha una mediana di: %i", medianmp)
## [1] "La variabile median_price ha una mediana di: 134500"
print(quantile_mp)
## 25% 75%
## 117300 150050
median_price, indici di variabilità.
#median_price, indici di variabilità
mpvarinterval = (maxmp-minmp)
interquartile_mp = IQR(realestate_stats$median_price)
mpvar = var(realestate_stats$median_price)
mpsd = sd(realestate_stats$median_price)
mp_coeff_var = coeff_var(realestate_stats$median_price)
sprintf("L'intervallo di variazione di median_price è: %i", mpvarinterval)
## [1] "L'intervallo di variazione di median_price è: 106200"
sprintf("Il range interquartile di median_price è: %i", interquartile_mp)
## [1] "Il range interquartile di median_price è: 32750"
sprintf("La varianza di median_price è: %.3f", mpvar)
## [1] "La varianza di median_price è: 513572983.089"
sprintf("La deviazione standard di median_price è: %.3f", mpsd)
## [1] "La deviazione standard di median_price è: 22662.149"
sprintf("Il coefficiente di variazione di median_price è: %.3f", mp_coeff_var)
## [1] "Il coefficiente di variazione di median_price è: 17.082"
median_price, indici di forma.
Per variare la grafica e creare qualcosa di più carino, in questo passaggio ho provato ad usare il modulo ggplot2 di R.
#median_price, indici di forma.
library("ggplot2")
asimmetry_mp_index = skewness(realestate_stats$median_price)
kurtosis_mp_index = kurtosis(realestate_stats$median_price)-3
ggplot()+
geom_density(aes(x=realestate_stats$median_price), col="black", fill="palegreen")+
geom_vline(xintercept =meanmp, linewidth=1.5, color = "lightcoral")+
labs(x="Prezzo Mediano", y="Densità")+
geom_text(aes(x = meanmp + 20000, y = 1.8e-05, label = sprintf("Media\n %.3f", meanmp)), inherit.aes = FALSE) +
ylim(0, 2e-05)
sprintf("L'indice di asimmetria di median_price è: %.3f", asimmetry_mp_index)
## [1] "L'indice di asimmetria di median_price è: -0.365"
sprintf("L'indice di curtosi di median_price è: %.3f", kurtosis_mp_index)
## [1] "L'indice di curtosi di median_price è: -0.623"
La variabile median_price ha un’asimmetria negativa con una distribuzione platicurtica. La curva è appiattita e la maggior parte delle modalità osservate risultano alte.
#variabile listings, indici di posizione
minlist = min(realestate_stats$listings)
maxlist = max(realestate_stats$listings)
meanlist = mean(realestate_stats$listings)
medianlist = median(realestate_stats$listings)
quantile_list = quantile(realestate_stats$listings, probs = c(.25, .75))
sprintf("La variabile listings ha un min/max di: %i %i", minlist, maxlist)
## [1] "La variabile listings ha un min/max di: 743 3296"
sprintf("La variabile listings ha una media di: %.3f", meanlist)
## [1] "La variabile listings ha una media di: 1738.021"
sprintf("La variabile listings ha una mediana di: %.2f", medianlist)
## [1] "La variabile listings ha una mediana di: 1618.50"
print(quantile_list)
## 25% 75%
## 1026.5 2056.0
listings, indici di variabilità.
#variabile listings, indici di variabilità
listvarinterval = (maxlist-minlist)
interquartile_list = IQR(realestate_stats$listings)
listvar = var(realestate_stats$listings)
listsd = sd(realestate_stats$listings)
list_coeff_var = coeff_var(realestate_stats$listings)
sprintf("L'intervallo di variazione di listings è: %i", listvarinterval)
## [1] "L'intervallo di variazione di listings è: 2553"
sprintf("Il range interquartile di listings è: %.2f", interquartile_list)
## [1] "Il range interquartile di listings è: 1029.50"
sprintf("La varianza di listings è: %.3f", listvar)
## [1] "La varianza di listings è: 566568.966"
sprintf("La deviazione standard di listings è: %.3f", listsd)
## [1] "La deviazione standard di listings è: 752.708"
sprintf("Il coefficiente di variazione di listings è: %.3f", list_coeff_var)
## [1] "Il coefficiente di variazione di listings è: 43.308"
listings, indici di forma.
#per determinare in maniera più precisa la scala di y
#tramite cui posizionare la scritta "media", ho usato la funzione density
#eseguita sulla variabile listings. l'indice max della densità di listings su y è stato usato
#per posizionare correttamente la scritta "media" nel grafico
density_data = density(realestate_stats$listings)
max_listdensity = max(density_data$y)
#variabile listings, indici di forma
library("ggplot2")
asimmetry_lists_index = skewness(realestate_stats$listings)
kurtosis_lists_index = kurtosis(realestate_stats$listings)-3
ggplot()+
geom_density(aes(x=realestate_stats$listings), col="black", fill="palegreen")+
geom_vline(xintercept = meanlist, linewidth=1.5, color = "lightcoral")+
labs(x="Inserzioni attive", y="Densità")+
geom_text(aes(x = meanlist+500, y = max_listdensity, label = sprintf("Media\n %.3f", meanlist)), inherit.aes = FALSE) +
xlim(0, 5000)
sprintf("L'indice di asimmetria di listings è: %.3f", asimmetry_lists_index)
## [1] "L'indice di asimmetria di listings è: 0.649"
sprintf("L'indice di curtosi di listings è: %.3f", kurtosis_lists_index)
## [1] "L'indice di curtosi di listings è: -0.792"
L’indice di asimmetria di Fisher su listings è positivo. Si tratta di asimmetria positiva e la maggior parte delle modalità/valori sono bassi. La curtosi è negativa, quindi abbiamo una distribuzione platicurtica.
months inventory, indici di posizione.
#variabile months_inventory, indici di posizione
minmonths = min(realestate_stats$months_inventory)
maxmonths = max(realestate_stats$months_inventory)
meanmonths = mean(realestate_stats$months_inventory)
medianmonths = median(realestate_stats$months_inventory)
modemonths = mode(realestate_stats$months_inventory)
quantile_months = quantile(realestate_stats$months_inventory, probs = c(.25, .75))
sprintf("La variabile months_inventory ha un min/max di: %.2f %.2f", minmonths, maxmonths)
## [1] "La variabile months_inventory ha un min/max di: 3.40 14.90"
sprintf("La variabile months_inventory ha una media di: %.3f", meanmonths)
## [1] "La variabile months_inventory ha una media di: 9.193"
sprintf("La variabile months_inventory ha una mediana di: %.2f", medianmonths)
## [1] "La variabile months_inventory ha una mediana di: 8.95"
sprintf("La variabile months_inventory è unimodale: %.2f", modemonths)
## [1] "La variabile months_inventory è unimodale: 8.10"
print(quantile_months)
## 25% 75%
## 7.80 10.95
months inventory, indici di variabilità.
#variabile months_inventory, indici di variabilità
monthsvarinterval = (maxmonths-minmonths)
interquartile_months = IQR(realestate_stats$months_inventory)
monthsvar = var(realestate_stats$months_inventory)
monthssd = sd(realestate_stats$months_inventory)
months_coeff_var = coeff_var(realestate_stats$months_inventory)
sprintf("L'intervallo di variazione di months_inventory è: %.2f", monthsvarinterval)
## [1] "L'intervallo di variazione di months_inventory è: 11.50"
sprintf("Il range interquartile di months_inventory è: %.2f", interquartile_months)
## [1] "Il range interquartile di months_inventory è: 3.15"
sprintf("La varianza di months_inventory è: %.3f", monthsvar)
## [1] "La varianza di months_inventory è: 5.307"
sprintf("La deviazione standard di months_inventory è: %.3f", monthssd)
## [1] "La deviazione standard di months_inventory è: 2.304"
sprintf("Il coefficiente di variazione di months_inventory è: %.3f", months_coeff_var)
## [1] "Il coefficiente di variazione di months_inventory è: 25.060"
months_inventory, indici di forma.
#variabile months_inventory, indici di forma
library("ggplot2")
asimmetry_months_index = skewness(realestate_stats$months_inventory)
kurtosis_months_index = kurtosis(realestate_stats$months_inventory)-3
invendensity = density(realestate_stats$months_inventory)
invenmaxdensity = max(invendensity$y)
ggplot()+
geom_density(aes(x=realestate_stats$months_inventory), col="black", fill="palegreen")+
geom_vline(xintercept = meanmonths, linewidth=1.5, color = "lightcoral")+
labs(x="Tempo restante per smaltire\n le inserizioni attive", y="Densità")+
geom_text(aes(x = meanmonths+2, y = invenmaxdensity, label = sprintf("Media\n %.3f", meanmonths)), inherit.aes = FALSE)+
xlim(0,20)
sprintf("L'indice di asimmetria di months_inventory è: %.3f", asimmetry_months_index)
## [1] "L'indice di asimmetria di months_inventory è: 0.041"
sprintf("L'indice di curtosi di months_inventory è: %.3f", kurtosis_months_index)
## [1] "L'indice di curtosi di months_inventory è: -0.174"
months_inventory ha un’asimmetria positiva. Sono quindi più frequenti modalità basse. La curtosi è negativa per cui ci troviamo davanti a una distribuzione platicurtica.
Utilizzerò un lollipop chart creato con ggplot2 per comparare i coefficienti di variazione delle variabili per i quali è stato calcolato.
#Effettuiamo i primi confronti su varianza e asimmetria per i dati a disposizione
#utilizziamo ggplot2 e un lollipop chart per evidenziare le differenze
#Confronto di variabilità
library("ggplot2")
cvarcomparison = data.frame(
x = c(salescv, volume_coeff_var, mp_coeff_var, list_coeff_var, months_coeff_var),
y = factor(c("Vendite", "Volume di Vendita", "Prezzo Mediano", "Inserzioni", "Mesi allo Smaltimento"),
levels = c("Vendite", "Volume di Vendita", "Prezzo Mediano", "Inserzioni", "Mesi allo Smaltimento"))
)
# Creazione del lollipop chart con ggplot2
ggplot(cvarcomparison, aes(x = x, y = y)) +
geom_segment(aes(x = 0, xend = x, y = y, yend = y), color = "grey") +
geom_point(aes(x = x), color = "red", fill=alpha("lightcoral", 0.3), alpha=0.7, shape=21, stroke=1.5, size = 5) +
geom_text(aes(label=round(x, 3)), hjust = -0.3, color= "black")+
theme_light() +
theme(
panel.grid.major.x = element_blank(),
panel.border = element_blank(),
axis.ticks.x = element_blank(),
plot.title.position = "plot"
) +
xlab("Coefficienti di Variazione") +
ylab("")+
labs(title = "Comparazione dei coefficienti di variazione.",
subtitle = "Utilizzo del dataset realestate_texas.csv opportunamente elaborato")+
coord_flip()
Dal grafico emerge chiaramente che la variable volume (“Volume di vendita”) è quella col coefficiente di variazione più elevato. Procediamo a valutarne anche l’asimmetria tramite l’indice di asimmetria di fisher.
#Confronto di asimmetria
asimmetrycomparison = data.frame(
x = c(asimmetry_sales_index, asimmetry_volume_index, asimmetry_mp_index, asimmetry_lists_index, asimmetry_months_index),
y = factor(c("Vendite", "Volume di Vendita", "Prezzo Mediano", "Inserzioni", "Mesi allo Smaltimento"),
levels = c("Vendite", "Volume di Vendita", "Prezzo Mediano", "Inserzioni", "Mesi allo Smaltimento"))
)
# Creazione del lollipop chart con ggplot2
ggplot(asimmetrycomparison, aes(x = x, y = y)) +
geom_segment(aes(x = 0, xend = x, y = y, yend = y), color = "grey") +
geom_point(aes(x = x), color = "blue", fill=alpha("lightblue", 0.3), alpha=0.7, shape=21, stroke=1.5, size = 5) +
geom_text(aes(label=round(x, 3)), hjust = -0.3, color= "black")+
theme_light() +
theme(
panel.grid.major.x = element_blank(),
panel.border = element_blank(),
axis.ticks.x = element_blank(),
plot.title.position = "plot"
) +
xlab("Indice di asimmetria di Fisher") +
ylab("")+
labs(title = "Comparazione degli indici di asimmetria di Fisher",
subtitle = "Utilizzo del dataset realestate_texas.csv opportunamente elaborato")+
coord_flip()
Come si evince dal grafico, soltanto una delle variabili ha indice di asimmetria negativo, mentre Volume di Vendita (volume) dimostra, ancora una volta, essere la variabile con l’indice di asimmetria più elevato.
Scelgo la variabile sales per effettuare una divisione in classi delle modalità, costruire la distribuzione di frequenze, procedere poi a dimostrarle graficamente e calcolare l’indice di gini.
Divisione in classi e distribuzione di frequenza.
#Selezioniamo la variabile sales per effettuare una divisione in classe
#ne sviluppiamo la distribuzione di frequenza e la esplicitiamo in un grafico a barre.
#Procederemo poi al calcolo dell'indice di Gini della variabile scelta
#sales, divisione in classe.
salesclass = cut(realestate_stats$sales, breaks = seq(50,450, by=50), right = FALSE)
#calcoliamo le frequenze ed organizziamo la distribuzione
sales_ndistribution = table(salesclass)
sales_frtable = sales_ndistribution/sum(sales_ndistribution)
sales_cumsum = cumsum(sales_ndistribution)
sales_cumrel = sales_cumsum/sum(sales_ndistribution)
finaltable = cbind(ni=sales_ndistribution, fi=sales_frtable, Ni=sales_cumsum, Fi=sales_cumrel)
colnames(finaltable) = c("Fr. Assolute", "Fr. Relative", "Fr. Assolute cumulate", "Fr. relative cumulate")
print(finaltable)
## Fr. Assolute Fr. Relative Fr. Assolute cumulate Fr. relative cumulate
## [50,100) 20 0.08333333 20 0.08333333
## [100,150) 69 0.28750000 89 0.37083333
## [150,200) 58 0.24166667 147 0.61250000
## [200,250) 33 0.13750000 180 0.75000000
## [250,300) 34 0.14166667 214 0.89166667
## [300,350) 14 0.05833333 228 0.95000000
## [350,400) 9 0.03750000 237 0.98750000
## [400,450) 3 0.01250000 240 1.00000000
Inseriamo la distribuzione di frequenze in un grafico creato con ggplot2 che prenda in considerazione le n osservazioni e le classi della variabile.
#Inseriamo la distribuzione in un grafico con ggplot2
#creiamo il dataframe da passare al grafico
saled_distribution_data = data.frame(
salesclass = as.factor(names(sales_ndistribution)),
n = as.vector(sales_ndistribution)
)
ggplot(saled_distribution_data, aes(x=salesclass, y = n, fill = salesclass))+
geom_bar(stat = "identity", fill="grey")+
scale_x_discrete(limits = levels(salesclass))+
labs(x = "Classi della variabile", y = "Numero di osservazioni")+
theme(legend.position = "none",
plot.title.position = "plot")+
labs(title = "Distribuzione di frequenze variabile sales",
subtitle = "Per le n osservazioni divise in classi")
Ora calcoliamo l’indice di eterogeneità di Gini della distribuzione di frequenza per sales appena costruita.
#calcoliamo l'indice di gini di sales
#creiamo la funzione apposita
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)
}
#procediamo al calcolo
salesgini = gini.index(salesclass)
sprintf("La variabile sales ha un indice di eterogeneità di Gini pari a: %.3f", salesgini)
## [1] "La variabile sales ha un indice di eterogeneità di Gini pari a: 0.923"
Eseguiamo il calcolo dell’indice di eterogeneità di Gini sulla distribuzione in classi della variabile sales. Il risultato è 0.923, per cui notiamo di essere vicini a una condizione di massima eterogeneità prevista (gini=1)
#Calcolo delle probabilità
#Prendiamo in considerazione la probabilità che, con un numero sufficiente di prove, la città di Beaumont venga estratta dal dataset.
#costruiamo il relativo grafico
library("ggplot2")
library("gganimate")
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("gifski")
library("knitr")
frames = lapply(1:10, function(i){
data.frame(city = sample(realestate_stats$city, 1000000, replace = TRUE),
frame = paste("Frame", i))
})
framedata = do.call(rbind, frames)
framedata_summary = framedata %>%
group_by(city, frame) %>%
summarise(count = n(), .groups = "drop")
animated_plot = ggplot(framedata_summary, aes(x = city, y = count, fill = city)) +
geom_bar(stat = 'identity') +
theme_minimal() +
labs(x = "Città", y = "Numero di estrazioni") +
transition_states(
frame,
transition_length = 2,
state_length = 1
) +
ease_aes('linear')+
labs(title = "Probabilità di estrazione casuale per una delle modalità di city",
subtitle = "Frame: {closest_state}")+
theme(legend.position = "none")
cityanimation = animate(animated_plot, fps = 15, duration = 5, nframes = 30, renderer = gifski_renderer())
anim_save("city_probability_animation.gif", animation = cityanimation)
knitr::include_graphics("city_probability_animation.gif")
#Otteniamo la probabilità classica per la variabile city
city_classic_prob = (60/240)
city_relative_prob = (city_classic_prob*100)
sprintf("Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice della variabile city. Con un numero sufficiente di tentativi di estrazione, la variabile city restituirà un probabilità del %.1f%% di ottenere La città di Beaumont", city_relative_prob)
## [1] "Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice della variabile city. Con un numero sufficiente di tentativi di estrazione, la variabile city restituirà un probabilità del 25.0% di ottenere La città di Beaumont"
Dimostriamo, attraverso il grafico e l’uso della probabilità classica, che l’estrazione casuale della città di Beaumont fra le righe della variabile city ha un 25% di probabilità di estrazione con un numero sufficiente di tentativi.
#Prendiamo ora in considerazione la variabile month per il mese di Luglio
#Costruiamo anche il relativo grafico
library("ggplot2")
library("gganimate")
library("dplyr")
library("gifski")
library("knitr")
frames_month = lapply(1:10, function(i){
data.frame(months = sample(realestate_stats$month, 1000000, replace = TRUE),
frame = paste("Frame", i))
})
frame_month_data = do.call(rbind, frames_month)
framedatamonth_summary = frame_month_data %>%
group_by(months, frame) %>%
summarise(count = n(), .groups = "drop")
animated_plot_months = ggplot(framedatamonth_summary, aes(x = months, y = count, fill = months)) +
geom_bar(stat = 'identity') +
theme_minimal() +
labs(x = "Mesi", y = "Numero di estrazioni") +
transition_states(
frame,
transition_length = 2,
state_length = 1
) +
ease_aes('linear')+
labs(title = "Probabilità di estrazione casuale per una delle modalità di month",
subtitle = "Frame: {closest_state}")+
theme(legend.position = "none")
monthsanimation = animate(animated_plot_months, fps = 15, duration = 5, nframes = 30, renderer = gifski_renderer())
anim_save("months_probability_animation.gif", animation = monthsanimation)
knitr::include_graphics("months_probability_animation.gif")
#Otteniamo la probabilità classica per la variabile month
month_classic_prob = (20/240)
month_relative_prob = (month_classic_prob*100)
sprintf("Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice della variabile month. Con un numero sufficiente di tentativi di estrazione, la variabile month restituirà un probabilità del %.1f%% di ottenere il mese di Luglio", month_relative_prob)
## [1] "Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice della variabile month. Con un numero sufficiente di tentativi di estrazione, la variabile month restituirà un probabilità del 8.3% di ottenere il mese di Luglio"
Dimostriamo, attraverso il grafico e l’uso della probabilità classica, che l’estrazione casuale del mese di Luglio fra le righe della variabile month ha un 8.3% di probabilità di estrazione con un numero sufficiente di tentativi.
#Valutiamo la probabilità che dal dataset si estragga il mese di dicembre 2012
#costruiamo il grafico
library("ggplot2")
library("gganimate")
library("dplyr")
library("gifski")
library("knitr")
#calcolo della probabilità
twentyt_classic_prob = (4/240)
twentyt_relative_prob = (twentyt_classic_prob*100)
sprintf("Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice. Con un numero sufficiente di tentativi di estrazione, la modalità Dicembre 2012 restituirà una probabilità del %.1f%% di essere estratta", twentyt_relative_prob)
## [1] "Il grafico rappresenta visivamente ciò che il calcolo della probabilità classica ci dice. Con un numero sufficiente di tentativi di estrazione, la modalità Dicembre 2012 restituirà una probabilità del 1.7% di essere estratta"
set.seed(42)
months_full_dataset = c(rep(1:59, each = 4), rep(60, times = 4))
frames_twentyt = lapply(1:10, function(i) {
data.frame(
month_category = sample(months_full_dataset, 1000000, replace = TRUE),
frame = paste("Frame", i)
)
})
frame_twentyt_data = do.call(rbind, frames_twentyt)
framedatatwentyt_summary = frame_twentyt_data %>%
group_by(month_category, frame) %>%
summarise(count = n(), .groups = "drop") %>%
mutate(color_group = ifelse(month_category == 60, "Dicembre", "Altri mesi"))
animated_plot_twentyt = ggplot(framedatatwentyt_summary, aes(x = as.factor(month_category), y = count, fill = color_group)) +
geom_bar(stat = 'identity', position = "dodge", width = 0.8) +
theme_minimal() +
labs(x = "Categorie di Mesi", y = "Numero di estrazioni") +
transition_states(
frame,
transition_length = 2,
state_length = 1
) +
ease_aes('linear')+
labs(title = "Probabilità di estrazione casuale per Dicembre 2012",
subtitle = "Frame: {closest_state}")+
scale_fill_manual(values = c("Dicembre" = "lightcoral", "Altri mesi" = "grey"))+
theme(legend.position = "none",
axis.text.x = element_text(angle = 90, hjust = 1),
plot.margin = margin(1, 1, 1, 1, "cm"))
twentytanimation = animate(animated_plot_twentyt,
fps = 15,
duration = 5,
nframes = 30,
renderer = gifski_renderer()
)
anim_save("twentyt_probability_animation.gif", animation = twentytanimation)
knitr::include_graphics("twentyt_probability_animation.gif")
Come notiamo dal calcolo della probabilità e dal grafico, otteniamo uguale probabilità dell’1,7% di estrarre Dicembre 2012 dal dataset con un numero sufficiente di estrazioni.
Approfittiamo dei dati a disposizione per aggiungere la colonna del prezzo medio mensile per ogni riga del dataset, essendoci attualmente soltanto il prezzo mediano.
#Aggiungiamo al dataset una colonna con il prezzo medio degli immobili
realestate_stats$mean_price = (realestate_stats$volume/realestate_stats$sales)*1000000
Procediamo ora a rapportare numero di vendite a inserzioni attive per verificare l’efficacia di conversione delle inserzioni in vendite, rappresentando tutto in un lollipop chart.
#Per valutare l'efficacia degli annunci di vendita, rapportiamo le vendite mensili alle inserzioni attive dello stesso mese
realestate_stats$listings_efficiency = realestate_stats$sales/realestate_stats$listings
#prima di poter procedere a costruire il grafico, necessitiamo delle medie della variabile listings_efficiency per poter meglio rappresentare l'efficacia per città
realestate_listingse_summary = realestate_stats %>%
group_by(city) %>%
summarise(listings_efficiency = mean(listings_efficiency))
#costruiamo il grafico
ggplot(realestate_listingse_summary, aes(x=listings_efficiency, y=city)) +
geom_segment(aes(x=0, xend=listings_efficiency, y=city, yend=city), color="grey", size = 1) +
geom_point(aes(x= listings_efficiency, y = city), color="lightcoral", size=5) +
theme_light() +
theme(
panel.grid.major.x = element_blank(),
panel.border = element_blank(),
axis.ticks.x = element_blank(),
plot.title.position = "plot"
) +
labs(x="Efficacia delle inserzioni", y="Città",
title = "Grafico di efficacia delle inserzioni",
subtitle = "Rappresentazione della media del rapporto fra vendite effettuate e inserzioni totali per ogni mese")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Come si evince dal grafico. Bryan-College Station ha la maggior efficienza di conversione delle inserzioni attive in vendite per ogni mese.
Di seguito mostriamo anche un print dei dati utilizzati.
print(realestate_listingse_summary)
## # A tibble: 4 × 2
## city listings_efficiency
## <chr> <dbl>
## 1 Beaumont 0.106
## 2 Bryan-College Station 0.147
## 3 Tyler 0.0935
## 4 Wichita Falls 0.128
Convertendo il rapporto in percentuale, ci rendiamo conto che:
realestate_listingse_summary$percent = realestate_listingse_summary$listings_efficiency*100
print(realestate_listingse_summary)
## # A tibble: 4 × 3
## city listings_efficiency percent
## <chr> <dbl> <dbl>
## 1 Beaumont 0.106 10.6
## 2 Bryan-College Station 0.147 14.7
## 3 Tyler 0.0935 9.35
## 4 Wichita Falls 0.128 12.8
Bryan-College Station in media converte il 14.7% di inserzioni attive su scala mensile.
#Ulteriori considerazioni sul dataset
#Creiamo una serie storica delle vendite delle 4 città del dataset comparandole in un unico grafico
#Innanzitutto creiamo un gruppo con le città del dataset
sales_group_data = realestate_stats %>%
group_by(city, year, month) %>%
summarise(total_sales = sum(sales, na.rm = TRUE)) %>%
ungroup() %>%
mutate(date = as.Date(paste(year, month, "01", sep = "-")))
## `summarise()` has grouped output by 'city', 'year'. You can override using the
## `.groups` argument.
#Costruiamo il grafico
ggplot(sales_group_data, aes(x = date, y = total_sales, group = city, color = city))+
geom_line(size = 1.2)+
theme_minimal()+
labs(title = "Serie storica comparativa delle vendite per città",
x = "Anno",
y = "Numero di vendite",
color = "Città")+
theme(
legend.position = "bottom",
plot.title = element_text(hjust = 0.5))+
facet_wrap(~ city, scales="free_y")
Le prime considerazioni sul grafico mostrano una certa stagionalità del numero di vendite, che tendono a scendere considerevolmente nel periodo invernale in tutte le città per poi risalire nei mesi centrali con un comportamento a “onda”.
Notiamo anche come le vendite sembrino in trend di salita in tutte le città tranne che a Wichita Falls, in cui non si registrano tendenza in salita significative nei 5 anni.
#Confrontiamo la distribuzione del prezzo mediano delle case per le varie città
#utilizzando 4 boxplot differenti
#costruiamo il grafico
ggplot(realestate_stats, aes(x = city, y = median_price))+
geom_boxplot(
color = "indianred4",
fill = "indianred3",
alpha = 0.2,
outlier.colour = "mediumvioletred",
outlier.fill = "mediumvioletred",
outlier.size = 3,
)+
theme_minimal()+
labs(title = "Distribuzione del prezzo mediano per le varie città",
x = "Città",
y = "Prezzo Mediano")+
theme(plot.title = element_text(hjust = 0.5))
Come visibile dalla comparazione dei boxplot, Bryan-College Station è la città che mostra una distribuzione del prezzo mediano dalle modalità più alte rispetto a tutte le altre città, mentre Wichita Falls quella con le modalità più basse. Tyler è l’unica città a non presentare valori outliers nella distribuzione.
#Prendiamo in considerazione ora il valore totale delle vendite diviso per città e anni
#Usiamo la library hrbrthemes e poi aggreghiamo i dati.
library("hrbrthemes")
volume_group = realestate_stats %>%
group_by(year, city) %>%
summarise(total_volume_data = sum(volume, na.rm = TRUE)) %>%
ungroup()
#costruiamo il grafico
ggplot(volume_group, aes(x = city, y = total_volume_data, fill = factor(year)))+
geom_bar(stat="Identity", color="#e9ecef", position=position_dodge(), alpha=0.6)+
scale_fill_manual(values = c("#69b3a2", "#404080", "#FF6347", "#4682B4", "#FFA500"))+
theme_ipsum()+
labs(fill = "Anni", title = "Distribuzione del volume delle vendite",
subtitle = "Dati divisi per anno e città",
x= "Città", y ="Volume totale in mil$")+
theme(axis.text.x = element_text(angle=45, hjust=1),
plot.title.position = "plot")
Il grafico evidenzia chiaramente come Bryan-College Station e Tyler abbiano aumentato i volumi di vendita nel 2013 e 2014, effetto che si osserva moderatamente anche in Beaumont. Wichita Falls invece ha volumi di vendita (in mil$) più bassi rispetto a tutte le altre città del dataset.
#grafico a barre sovrapposte con totale delle vendite
sales_grouping = realestate_stats %>%
group_by(city, month) %>%
summarise(total_sales = sum(sales, na.rm = TRUE)) %>%
ungroup()
ggplot(sales_grouping, aes(x = as.factor(month), y = total_sales, fill = city)) +
geom_bar(stat = "identity", position = "Stack") +
scale_fill_hue(c = 40)+
theme_minimal()+
labs(title = "Totale delle vendite mensili per ogni città",
x = "Mese",
y = "Totale vendite",
fill = "Città")+
theme(
legend.position = "bottom",
plot.title = element_text(hjust = 0.5)
)
Consideriamo anche la versione normalizzata del grafico.
ggplot(sales_grouping, aes(x = as.factor(month), y = total_sales, fill = city)) +
geom_bar(stat = "identity", position = "fill") +
scale_fill_hue(c = 40)+
theme_minimal()+
labs(title = "Distribuzione normalizzata delle vendite mensili",
x = "Mese",
y = "Totale vendite",
fill = "Città")+
theme(
legend.position = "bottom",
plot.title = element_text(hjust = 0.5)
)+
scale_y_continuous(labels = scales::percent)
Come ipotizzato da precedenti considerazioni sulla serie storica e sulla distribuzione del volume delle vendite, confermiamo che Tyler e Bryan-College Station sono le città che mostrano il maggior numero di vendite, con Wichita che presenta dati marginali rispetto alle altre quattro. I dati di Tyler e Bryan-College sembrano occupare in percentuale la maggior parte della distribuzione.
Procediamo a divedere il grafico non normalizzato per anni, inserendo quindi una divisione per mesi, anni e città.
#Proviamo a includere anche la divisione in anni creando grafici a barre sovrapposte divisi.
sales_grouping = realestate_stats %>%
group_by(city, year, month) %>%
summarise(total_sales = sum(sales, na.rm = TRUE)) %>%
ungroup()
ggplot(sales_grouping, aes(x = as.factor(month), y = total_sales, fill = city)) +
geom_bar(stat = "identity", position = "stack") +
scale_fill_hue(c = 40) +
theme_minimal() +
labs(title = "Totale delle vendite mensili per ogni città",
x = "Mese",
y = "Totale vendite",
fill = "Città") +
theme(
legend.position = "bottom",
plot.title = element_text(hjust = 0.5)
) +
facet_wrap(~ year, ncol = 1)
Come esercizio grafico, possiamo rappresentare la medesima situazione con una heatmap.
#usiamo gli stessi dati per una heatmap
library(ggplot2)
library(dplyr)
monthly_sales_grouping = realestate_stats %>%
group_by(city, year, month) %>%
summarise(total_sales = sum(sales, na.rm = TRUE)) %>%
ungroup()
heatmap_plot = ggplot(monthly_sales_grouping, aes(x = factor(month, levels = 1:12), y = city, fill = total_sales)) +
geom_tile(color = "white") +
facet_wrap(~ year, ncol = 1) +
scale_fill_gradient(low = "white", high = "lightcoral") +
labs(title = "Heatmap delle Vendite Mensili per Città e Anno",
x = "Mese",
y = "Città",
fill = "Vendite Totali") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 0, hjust = 1))
print(heatmap_plot)
Avendo aggiunto la variabile al dataset, vale inoltre la pena esplorare l’evoluzione del prezzo medio su una serie storica divisa per città, utilizzando uno stacked area chart.
#Approfittiamo per costruire una serie storia sul prezzo medio
mean_group_data = realestate_stats %>%
group_by(city, year, month) %>%
summarise(total_mean_price = sum(mean_price, na.rm = TRUE)) %>%
ungroup() %>%
mutate(date = as.Date(paste(year, month, "01", sep = "-")))
#Costruiamo il grafico
ggplot(mean_group_data, aes(x = date, y = total_mean_price, group = city, fill = city))+
geom_area(alpha = 0.6, color = "black", size = 0.5)+
theme_minimal()+
labs(title = "Serie storica del prezzo medio per città",
x = "Anno",
y = "Prezzo medio",
fill = "Città")+
theme(
legend.position = "bottom",
plot.title = element_text(hjust = 0.5))+
facet_wrap(~ city, scales = "free_y")+
scale_y_continuous(labels = scales::comma)
Analizzando quanto emerso dai dati elaborati in questo dataset, possiamo partire dal grafico di efficacia delle inserzioni per notare come Wichita Falls, seconda per media del rapporto fra vendite effettuate e inserzioni totali, in realtà sia anche quella che mostra un andamento più piatto delle vendite in termini di valori assoluti in mil$ e per numero assoluto di vendite negli anni considerati. Questi dati e la distribuzione del prezzo mediano di Wichita Falls rappresentata nel box plot ci fanno ipotizzare un momento di crisi del mercato immobiliare di quell’area del Texas, con una domanda generalmente bassa.
Anche il prezzo medio degli immobili di Wichita Falls non presenta significativi trend o evoluzioni nell’arco dei cinque anni considerati. Al contrario, Bryan-College Station subisce un chiaro trend di salita del prezzo medio negli ultimi due anni del dataset, in parte visibile anche in Tyler.
Per quanto riguarda la città di Tyler osserviamo come i dati in volume e numero di vendite, confrontati con l’efficacia relativamente inferiore di conversione delle inserzioni, ci suggeriscano che si possa ottimizzare il dato sull’efficacia di conversione per portare il mercato di quell’area ad ottenere performance potenzialmente superiori.