data <- read.csv("realestate_texas.csv")
str(data)
## '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 ...
dim(data)
## [1] 240 8
La variabile month è una variabile categorica ordinale espressa in numeri da 1 a 12. La rendo categorica ordinale per maggiore comprensione
data$month<-factor(data$month, labels = month.name)
il dataframe ha 240 osservazioni e 8 variabili. city - var categorica nominale year - var quant discr month - var categorica ordinale - dopo aver sostituito la var numerica sales - var quant discreta volume - var quant cont median_price - var quant cont listings - var quant discr month_inventory - var quant cont
ANALISI VARIABILI TEMPORALI: La variabile “month” si può usare per trend stagionali - effetti mensili - boxplot per confrontare distribuzione delle vendite per mese oppure si puo effettuare un confronto dell’ammontare medio delle vendite per ogni mese (ind dall’anno). La variabile “year” si puo utilizzare per analizzare trend storici longitudinali come per esempio per osservare come vendite, prezzi ed inventari mutino nel tempo - line chart
Calcolo indici di posizione, variabilità e forma per le variabili continue e creo distribuzione di frequenza per variabili categoriche
attach(data)
library(moments)
seleziono solo le variabili continue e creo un data frame con gli indici
var_cont<-data[, c("sales", "volume", "median_price", "listings", "months_inventory")]
statistiche <- data.frame(
#Var = colnames(var_cont),
Media = sapply(var_cont, mean),
Mediana = sapply(var_cont, median),
Dev_Std = sapply(var_cont, sd),
Range = sapply(var_cont, function(x) max(x) - min(x)),
IQR = sapply(var_cont, IQR),
Skewness = sapply(var_cont, skewness),
Kurtosis = sapply(var_cont, kurtosis)-3 #centro la curtosi sullo 0
)
statistiche
## Media Mediana Dev_Std Range IQR
## sales 192.29167 175.5000 79.651111 344.000 120.0000
## volume 31.00519 27.0625 16.651447 75.381 23.2335
## median_price 132665.41667 134500.0000 22662.148687 106200.000 32750.0000
## listings 1738.02083 1618.5000 752.707756 2553.000 1029.5000
## months_inventory 9.19250 8.9500 2.303669 11.500 3.1500
## Skewness Kurtosis
## sales 0.71810402 -0.3131764
## volume 0.88474203 0.1769870
## median_price -0.36455288 -0.6229618
## listings 0.64949823 -0.7917900
## months_inventory 0.04097527 -0.1744475
Nei 5 anni che vanno dal 2010 al 2014 compresi sono stati vendute in media 192.3 immobili al mese. Con un minimo di 79 vendite a Gennaio 2013 e Febbraio 2011 ed un massimo di 423 a Giugno 201a (Range = 344). La deviazione standard di 79,6 indica una varianza significiativa tra i mesi, evidenziata anche da un IQR di 120. L’indice di Fischer pari a 0.7 significa che la maggior parte dei mesi ha vendite relativamente basse (la coda della distribuzione si allunga verso destra) mentre alcuni mesi hanno vendite molto piu alte rispetto alla media. La forma platicurtica della curva (indice di curtosi negativo) conferma la dispersione dei valori rispetto alla media. L’alta varianza della variabile riflette l’eterogeneità delle vendite tra mesi e città, suggerendo che non c’è una chiara stabilità nel numero di transazioni immobiliari
Il valore medio delle vendite ammonta a circa 31 milioni di dollari e il 50% delle osservazioni si trova tra i 17.6 e i 40.9 milioni. Anche per questa variabile osserviamo un’assimmetria positiva. Tuttavia, rispetto alle vendite, in termini di unità immobiliari, il volume delle vendite mostra una maggiore concentrazione dei valori attorno alla media, come indicato da una curtosi positiva pari a 0.18
Il prezzo mediano degli immobili è 132.665, range e deviazione standard molto elevati, rispettivamente di 106200 e 22662$, indicando un’alta variabilità tra le osservazioni. Sebbene la distribuzione sia quasi simmetrica (skewness = -0.364, vicino a 0), i prezzi mediani variano significativamente tra le città e i periodi, mostrando un mercato immobiliare con forte eterogeneità dei prezzi.
Il numero totale degli annunci attivi (listings) è estremamente variabile, con un range di 2553 e un IQR di 1029, suggerendo una forte eterogeneità nel mercato immobiliare. La distribuzione presenta una leggera asimmetria positiva (skewness = 0.649), indicando che la maggior parte delle città ha un numero di annunci inferiore alla media. Inoltre, la bassa curtosi (-0.791) suggerisce che i valori sono dispersi su un ampio intervallo senza una forte concentrazione centrale, confermando un’alta variabilità nel numero di annunci attivi tra le città.
La quantità di tempo necessaria media per vendere tutte le inserzioni correnti è di 9.19 mesi. La variabile ha una distribuzione quasi simmetrica (skewness ≈ 0) e una concentrazione delle osservazioni vicino alla media.
#distr freq per var categoriche
N<-nrow(data)
calcola.freq<-function(x){
ni<-table(x)
fi<-ni/N
Ni<-cumsum(ni)
Fi<-cumsum(fi)
tab_freq <- data.frame(
Classi=names(ni),
Freq_Ass=as.numeric(ni),
Freq_Rel=as.numeric(fi),
Freq_Ass_Cum=as.numeric(Ni),
Freq_Rel_cum=as.numeric(Fi)
)
return(tab_freq)
}
distr_freq_city<-calcola.freq(city)
distr_freq_month<-calcola.freq(month)
distr_freq_year<-calcola.freq(year)
Le tre variabili categoriche sono equamente distribuite, il dataset è stato costruito con una distribuzione uniforme tra le categorie.
La variabile con la maggiore variabilità è “median_price” con una deviazione standard di 22662 e un IQR di 32750, segnalando una forte disomogeneità nei prezzi degli immobili e una distribuzione molto dispersa rispetto alla media. La variabile,invece, che presenta maggiore asimmetria è “volume” con un indice di Fisher pari a 0.88474203. Questo suggerisce che alcuni mesi hanno volumi di vendita eccezionalmente alti rispetto agli altri.
Divido median_price in 3 classi di ampiezza 35400 perchè è la variabile con il range più alto e la maggiore variabilità.
ampiezza<-(max(median_price)-min(median_price))/3
ampiezza
## [1] 35400
breaks <- seq(min(median_price), max(median_price), ampiezza)
labels <- paste0("[", round(head(breaks, -1), 0), " - ", round(tail(breaks, -1), 0), "]")
median_price_cl<- cut(median_price, breaks = breaks,
include.lowest = TRUE, labels=labels)
median_price_cl
## [1] [144600 - 180000] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [5] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [9] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [13] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [17] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [21] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [25] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [29] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [33] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [37] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [41] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [45] [144600 - 180000] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [49] [73800 - 109200] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [53] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [57] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [61] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [65] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [69] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [73] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [77] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [81] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [85] [109200 - 144600] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [89] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [93] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [97] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [101] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [105] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [109] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [113] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [117] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [121] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [125] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [129] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [133] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [137] [109200 - 144600] [144600 - 180000] [109200 - 144600] [144600 - 180000]
## [141] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [145] [109200 - 144600] [109200 - 144600] [109200 - 144600] [109200 - 144600]
## [149] [109200 - 144600] [144600 - 180000] [144600 - 180000] [109200 - 144600]
## [153] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [157] [109200 - 144600] [109200 - 144600] [144600 - 180000] [109200 - 144600]
## [161] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [165] [144600 - 180000] [144600 - 180000] [109200 - 144600] [109200 - 144600]
## [169] [109200 - 144600] [144600 - 180000] [109200 - 144600] [144600 - 180000]
## [173] [144600 - 180000] [144600 - 180000] [144600 - 180000] [144600 - 180000]
## [177] [144600 - 180000] [109200 - 144600] [144600 - 180000] [144600 - 180000]
## [181] [73800 - 109200] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [185] [73800 - 109200] [109200 - 144600] [73800 - 109200] [73800 - 109200]
## [189] [73800 - 109200] [73800 - 109200] [73800 - 109200] [109200 - 144600]
## [193] [73800 - 109200] [73800 - 109200] [73800 - 109200] [109200 - 144600]
## [197] [109200 - 144600] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [201] [73800 - 109200] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [205] [73800 - 109200] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [209] [73800 - 109200] [109200 - 144600] [109200 - 144600] [73800 - 109200]
## [213] [73800 - 109200] [73800 - 109200] [109200 - 144600] [73800 - 109200]
## [217] [73800 - 109200] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [221] [109200 - 144600] [73800 - 109200] [73800 - 109200] [73800 - 109200]
## [225] [109200 - 144600] [109200 - 144600] [73800 - 109200] [109200 - 144600]
## [229] [73800 - 109200] [109200 - 144600] [73800 - 109200] [73800 - 109200]
## [233] [109200 - 144600] [109200 - 144600] [73800 - 109200] [73800 - 109200]
## [237] [73800 - 109200] [109200 - 144600] [73800 - 109200] [73800 - 109200]
## Levels: [73800 - 109200] [109200 - 144600] [144600 - 180000]
distr_freq_median_price_cl<-calcola.freq(median_price_cl)
Per vedere quanta informazione perdo raggruppando il prezzo mediano in sole tre classi faccio il confronto suddividendo anche in 11 classi.
?nclass.FD
## avvio in corso del server httpd per la guida ... fatto
num_classi <- nclass.FD(median_price)
breaks <- seq(min(median_price), max(median_price), length.out = num_classi + 1)
labels_cl <- paste0("[", round(head(breaks, -1)), " - ", round(tail(breaks, -1)), "]")
median_price_cl2 <- cut(median_price, breaks = breaks, include.lowest = TRUE, labels = labels_cl)
distr_freq_median_price_cl2<-calcola.freq(median_price_cl2)
Creo grafico a barre per la distribuzione di frequenza:
library(ggplot2)
ggplot()+
geom_bar(aes(x=median_price_cl2),
fill="steelblue", col="black")+
labs(title = "Prezzo Mediano mensile di Vendita degli immobili in Texas (2010-2014)",
subtitle = "Distribuzione di Frequenza delle Classi",
x="Prezzo Mediano ($)",
y="Frequenza")+
scale_y_continuous(breaks=seq(0, 50, 5)) +
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Il valore della y rappresenta il numero di mesi (sulle 240 osservazioni
totali) in cui il prezzo mediano è ricaduto in quell’intervallo; le
classi con più alta frequenza indicano gli intervalli di prezzo più
comuni: il prezzo mediano di vendita piu frequente è compreso tra i
131727 e 141382$.
#misurare la disuguaglianza tra le classi di prezzo
gini.index<-function(x){
ni=table(x)
fi=ni/length(x)
fi2=fi^2
J=length(table(x))
gini = 1-sum(fi2)
gini.normalizzato = gini/((J-1)/J)
return(gini.normalizzato)
}
gini.index(median_price_cl2)
## [1] 0.9668542
L’indice di Gini calcolato per la distribuzione delle classi di prezzo mediano è 0.96 (la massima eterogeneità si avrebbe per gini.index=1), indicando un’elevata eterogeneità nella distribuzione dei prezzi tra le fasce di prezzo. Questo valore suggerisce che le osservazioni sono distribuite in modo abbastanza uniforme tra le classi, senza una forte concentrazione in una sola categoria.
Questo risultato è coerente col grafico delle distribuzioni di frequenza: le classi centrali (tra 131.727 e 160.691 dollari ) presentano le frequenze più elevate, indicando che la maggior parte dei mesi ha avuto un prezzo mediano compreso in questa fascia. Tuttavia, esistono anche classi con frequenze molto basse segnalando che alcuni mesi hanno registrato prezzi significativamente diversi rispetto alla media.
p_Beaumont<-sum(city=="Beaumont")/nrow(data)
p_Beaumont
## [1] 0.25
library(dplyr)
## Warning: il pacchetto 'dplyr' è stato creato con R versione 4.2.3
##
## 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
p_July<-sum(month=="July")/nrow(data)
subset_July<-data%>% filter(month=="July")
p_July
## [1] 0.08333333
subset_dec_2012 <- data %>% filter(month == "December", year == 2012)
subset_dec_2012
## city year month sales volume median_price listings
## 1 Beaumont 2012 December 160 25.714 134700 1570
## 2 Bryan-College Station 2012 December 134 22.887 148400 1442
## 3 Tyler 2012 December 234 36.965 140000 2633
## 4 Wichita Falls 2012 December 115 11.820 87500 801
## months_inventory
## 1 9.1
## 2 7.3
## 3 10.0
## 4 7.1
p_Dec_2012<-sum((month=="December")& (year==2012))/nrow(data)
p_Dec_2012
## [1] 0.01666667
La probabilità che presa a caso una riga dal dataset questa riporti Beaumont è del 25%, quella che riporti il mese di luglio è dell’8% mentre quella che esce una riga di dicembre 2012 è dell’1,6 %.
Creo la variabile per osservare il prezzo medio, espressa in centinaia di migliaia di dollari.
options(scipen = 999)
data$avg_price<-(volume*1e6)/sales
str(data)
## 'data.frame': 240 obs. of 9 variables:
## $ city : chr "Beaumont" "Beaumont" "Beaumont" "Beaumont" ...
## $ year : int 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
## $ month : Factor w/ 12 levels "January","February",..: 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 ...
## $ avg_price : num 170627 163796 157698 134095 142738 ...
head(data$avg_price)
## [1] 170626.5 163796.3 157697.8 134095.0 142737.6 144015.9
Creo una misura per l’efficacia degli annunci di vendita (scala 0-1)
data$efficacy<-(sales/listings)
head(data$efficacy)
## [1] 0.05414220 0.06809584 0.10775607 0.11709602 0.11405985 0.10482529
#confronto variabili
summary(data$avg_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 97010 132939 156588 154320 173915 213234
summary(data$efficacy)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.05014 0.08980 0.10963 0.11874 0.13492 0.38713
summary(data$median_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 73800 117300 134500 132665 150050 180000
L’efficacia delle vendite (efficacy) ha una media del 11.87% e una mediana del 10.96%, quindi nella maggior parte dei casi meno del 12% degli annunci porta effettivamente a una vendita. Il massimo (38.71%) suggerisce che in alcune aree o periodi le vendite sono molto più rapide ed efficaci, mentre in altri casi (minimo 5%) il mercato è più stagnante.
Il prezzo medio è sempre superiore a al prezzo mediano, il che è atteso perché la media può essere influenzata da vendite molto alte (outliers).
Provo un grafico di confronto per vedere il prezzo medio e quello mediano nelle quattro città.
ggplot(data, aes(x = city)) +
geom_boxplot(aes(y = median_price, fill = "Median Price"), alpha = 0.5) +
geom_boxplot(aes(y = avg_price, fill = "Avg Price"), alpha = 0.5) +
labs(title = "Confronto tra Prezzo Mediano e Prezzo Medio per Città",
x = "Città", y = "Prezzo ($)") +
scale_fill_manual(values = c("Median Price" = "steelblue", "Avg Price" = "yellow2")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))+
theme_minimal()+
guides(fill = guide_legend(title = NULL))
Bryan-College Station mostra la maggiore varianza nei prezzi.
Creo un grafico anche per il confronto tra le vendite e l’efficacia degli annunci.
#ridefinisco e inserisco nel dataset la var che avevo creato divisa in 3 classi
data$median_price_cl <- cut(data$median_price,
breaks = c(73800, 109200, 144600, 180000),
include.lowest = TRUE,
labels = c("Basso", "Medio", "Alto"))
#verificare le differenze tra città
ggplot(data, aes(x = median_price_cl, y = efficacy * 100, fill = city)) +
geom_boxplot(alpha = 0.7) +
scale_fill_manual(values = c("Beaumont" = "indianred",
"Bryan-College Station" = "darkseagreen",
"Tyler" = "thistle",
"Wichita Falls" = "slategrey")) +
labs(title = "Efficacia degli Annunci Pubblicitari per Fasce di Prezzo Mediano e Città",
x = "Fasce di Prezzo (Prezzo Mediano)",
y = "Efficacia (%)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
La variazione dell’efficacia tra città suggerisce che in alcuni mercati,
come Bryan-College Station, le case più costose possono avere
un’efficacia di vendita molto variabile, mentre in altre città
l’efficacia è più stabile tra le fasce di prezzo.
Creo un box plot per confrontare la distribuzione delle vendite negli anni per le quattro città.
ggplot(data, aes(x = factor(year), y = sales, fill = city)) +
geom_boxplot() +
scale_fill_manual(values = c("Beaumont" = "indianred",
"Bryan-College Station" = "darkseagreen",
"Tyler" = "thistle", # Steelblue
"Wichita Falls" = "slategrey")) + # Slategray
labs(title = "Distribuzione delle Vendite per Anno e Città",
x = "Anno", y = "Numero di Vendite") +
theme_minimal()
Il grafico evidenzia variazioni significative tra le città e una
tendenza all’aumento delle vendite nel tempo, con un incremento
particolarmente marcato dal 2012 al 2014. Bryan-College Station e Tyler
hanno una maggiore variabilità e un numero di vendite più elevato
rispetto alle altre città. Confrontando il risultato con il grafico
precedente sull’efficacia si può ipotizzare che gli anni con vendite più
alte (es. 2013-2014) abbiano risentito dellàimpatto dellàefficacia degli
annunci, specialmente per le case più costose. Nella città di Wichita
Falls, la bassa efficacia potrebbe spiegare le vendite più contenute nel
tempo.
library(dplyr)
library(reshape2)
## Warning: il pacchetto 'reshape2' è stato creato con R versione 4.2.3
summary_city <- data %>%
group_by(city) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
mean_price = mean(median_price),
sd_price = sd(median_price),
mean_volume = mean(volume),
sd_volume = sd(volume))
summary_city
## # A tibble: 4 × 7
## city mean_sales sd_sales mean_price sd_price mean_volume sd_volume
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Beaumont 177. 41.5 129988. 10105. 26.1 6.97
## 2 Bryan-College S… 206. 85.0 157488. 8852. 38.2 17.2
## 3 Tyler 270. 62.0 141442. 9337. 45.8 13.1
## 4 Wichita Falls 116. 22.2 101743. 11320. 13.9 3.24
standardize <- function(x) {
return((x - mean(x)) / sd(x))
}
summary_city$mean_sales_st<-standardize(summary_city$mean_sales)
summary_city$mean_price_st<-standardize(summary_city$mean_price)
summary_city$mean_volume_st<-standardize(summary_city$mean_volume)
summary_year <- data %>%
group_by(year) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
mean_price = mean(median_price),
sd_price = sd(median_price),
mean_volume = mean(volume),
sd_volume = sd(volume)
)
summary_month <- data %>%
group_by(month) %>%
summarise(
mean_sales = mean(sales),
sd_sales = sd(sales),
mean_price = mean(median_price),
sd_price = sd(median_price),
mean_volume = mean(volume),
sd_volume = sd(volume)
)
summary_year$mean_sales_st<-standardize(summary_year$mean_sales)
summary_year$mean_price_st<-standardize(summary_year$mean_price)
summary_year$mean_volume_st<-standardize(summary_year$mean_volume)
ggplot(summary_year, aes(x = year)) +
geom_line(aes(y = mean_sales_st, color = "Vendite"), lwd = 1) +
geom_line(aes(y = mean_price_st, color = "Prezzo Mediano"), lwd = 1) +
#geom_line(aes(y = mean_volume_st, color = "Volume"), lwd = 1) +
geom_point(aes(y = mean_sales_st), color = "red", size = 3) +
geom_point(aes(y = mean_price_st), color = "steelblue", size = 3) +
#geom_point(aes(y = mean_volume_st), color = "green4", size = 3) +
labs(
title = "Andamento Standardizzato di Vendite e Prezzo nel Tempo",
x = "Anno",
y = "Valore Standardizzato",
color = NULL
) +
scale_color_manual(
values = c("Vendite" = "red", "Prezzo Mediano" = "steelblue")#, "Volume" = "green4")
) +
guides(color = guide_legend(title = NULL)) +
theme_minimal() +
scale_x_continuous(breaks = unique(summary_year$year))+
scale_y_continuous(limits = c(-2, 3), breaks = seq(-2, 3, by = 1)) #+
#geom_text(aes(y = mean_sales_st -0.5, label = round(mean_sales_st, 2)), color = "red4", size = 3) +
#geom_text(aes(y = mean_price_st +0.5, label = round(mean_price_st, 2)), color = "blue4", size = 3) #+
#geom_text(aes(y = mean_volume_st + 1.5, label = round(mean_volume_st, 2)), color = "green4", size = 3)
Dopo aver standardizzato le variabili per renderle confrontabili, ho deciso di escludere dal grafico il volume delle vendite, poiché esso risulta strettamente correlato al numero di vendite e non aggiunge informazioni significative. Tra il 2010 e il 2011, sia il prezzo mediano che il numero di vendite mostrano un andamento negativo, con un calo più marcato del prezzo che dal 2012 ha invece un aumento più significativo, mentre l’incremento delle vendite rimane costante dal 2011. Nel 2010, 2011, 2012 si osservano valori di prezzo e vendite inferiori alla media.
Creo un dataset aggregato per città mese e anno e visualizzo il totale delle vendite Ogni segmento rappresenta un anno in ordine temporale.
summary_month_city_year <- data %>%
group_by(year, month, city) %>%
summarise(
mean_sales = mean(sales, na.rm = TRUE),
.groups = "drop"
)
#summary_month_city_year$mean_sales_st <- standardize(summary_month_city_year$mean_sales)
ggplot(data=summary_month_city_year, aes(x = month, y = mean_sales,
fill = city)) +
geom_col(position = "stack", color="black") +
scale_fill_manual(values = c("Beaumont" = "indianred",
"Bryan-College Station" = "darkseagreen",
"Tyler" = "thistle",
"Wichita Falls" = "slategrey")) +
labs(
title = "Totale delle Vendite per Mese e Città",
x = "Mese",
y = "Vendite Totali",
fill = "Città"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Per rendere più chiaro il grafico creo un grafico a barre
normalizzato.
summary_month_city_year <- summary_month_city_year %>%
group_by(month) %>%
mutate(percent_sales = mean_sales / sum(mean_sales))
ggplot(data = summary_month_city_year, aes(x = month, y = percent_sales, fill = city)) +
geom_col(position = "fill", color = "black") + # "fill" normalizza le altezze a 1 (100%)
scale_fill_manual(values = c("Beaumont" = "indianred",
"Bryan-College Station" = "darkseagreen",
"Tyler" = "thistle",
"Wichita Falls" = "slategrey")) +
labs(
title = "Distribuzione Percentuale delle Vendite per Mese e Città",
x = "Mese",
y = "Quota di Vendite (%)",
fill = "Città"
) +
scale_y_continuous(labels = scales::percent_format()) + # Mostra asse Y in percentuale
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Come già evidenziato dai grafici precedenti Wichita Falls mantiene una
quota di mercato inferiore rispetto alle altre città. Si evidenzia
stagionalità nelle vendite.
Infine, provo a visualizzare una serie storica del numero totale di vendite negli anni.
library(lubridate)
## Warning: il pacchetto 'lubridate' è stato creato con R versione 4.2.3
##
## Caricamento pacchetto: 'lubridate'
## I seguenti oggetti sono mascherati da 'package:base':
##
## date, intersect, setdiff, union
data$date <- as.Date(paste(data$year, match(data$month, month.name), "1", sep = "-"))
ggplot(data, aes(x = date, y = sales, col = city)) +
geom_line(linewidth = 0.5) +
geom_point(size = 1) +
scale_color_manual(values = c("Beaumont" = "indianred",
"Bryan-College Station" = "darkseagreen",
"Tyler" = "thistle",
"Wichita Falls" = "slategrey")) +
labs(
title = "Andamento delle Vendite Immobiliari (2010-2014)",
x = "Anno",
y = "Numero di Vendite",
color = "Città"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
# scale_x_date(date_labels = "%b %Y", date_breaks = "6 months")
scale_x_date(date_labels = "%Y", date_breaks = "1 year")
max(data$sales)
## [1] 423
min(data$sales)
## [1] 79
data[data$sales == min(data$sales), ]
## city year month sales volume median_price listings
## 194 Wichita Falls 2011 February 79 8.747 90800 950
## 217 Wichita Falls 2013 January 79 9.666 99300 854
## months_inventory avg_price efficacy median_price_cl date
## 194 7.8 110721.5 0.08315789 Basso 2011-02-01
## 217 7.7 122354.4 0.09250585 Basso 2013-01-01
data[data$sales == max(data$sales), ]
## city year month sales volume median_price listings months_inventory
## 174 Tyler 2014 June 423 80.814 155700 2855 9.3
## avg_price efficacy median_price_cl date
## 174 191049.6 0.1481611 Alto 2014-06-01
La città di Tyler ha raggiunto il numero maggiore di vendite, con un totale di 423 immobili venduti a Giugno 2014. La città di Wichita Falls ha, invece, registrato il minor numero di vendite (79) sia a Gennaio 2013 che a Febbraio 2011.
CONCLUSIONI L’andamento mensile mostra una chiara stagionalità, con picchi di vendite nei mesi estivi e una riduzione nei mesi invernali.
Il trend di crescita del prezzo mediano è più marcato rispetto a quello del numero di vendite. Questo potrebbe suggerire una crescente domanda che ha fatto aumentare i prezzi, oppure una riduzione dell’offerta, portando a un incremento dei valori immobiliari.
L’analisi dell’efficacia degli annunci di vendita ha evidenziato significative differenze tra città e fasce di prezzo. Alcuni mercati si distinguono per un’attività più dinamica, sia in termini di volume di vendite che di prezzo mediano mentre, in particolare Wichita Falls si distingue per la minore efficacia degli annunci e una domanda immobiliare meno sostenuta. Bryan-College Station mostra la maggiore variabilità e i valori più alti di efficacia, indicando una forte domanda e una gestione più efficiente delle vendite. Beaumont si posiziona in una situazione intermedia, con un mercato più stabile e meno soggetto a variazioni estreme.