library(knitr)
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
#Load the data into R (CSV file)
data<-read.csv("Real Estate Texas.csv")
#Exploring the Dataset: structure and variable types
#First rows of the Dataset
kable(head(data), caption = "First rows of the Dataset")
city | year | month | sales | volume | median_price | listings | months_inventory |
---|---|---|---|---|---|---|---|
Beaumont | 2010 | 1 | 83 | 14.162 | 163800 | 1533 | 9.5 |
Beaumont | 2010 | 2 | 108 | 17.690 | 138200 | 1586 | 10.0 |
Beaumont | 2010 | 3 | 182 | 28.701 | 122400 | 1689 | 10.6 |
Beaumont | 2010 | 4 | 200 | 26.819 | 123200 | 1708 | 10.6 |
Beaumont | 2010 | 5 | 202 | 28.833 | 123100 | 1771 | 10.9 |
Beaumont | 2010 | 6 | 189 | 27.219 | 122800 | 1803 | 11.1 |
#Variables Names
kable(data.frame(Variables=names(data)), caption = "Variables Names")
Variables |
---|
city |
year |
month |
sales |
volume |
median_price |
listings |
months_inventory |
#Dataset structure in tabular form
str_df <- data.frame(
Variable = names(data),
Class = sapply(data, class)
)
kable(str_df, caption = "Dataset Structure")
Variable | Class | |
---|---|---|
city | city | character |
year | year | integer |
month | month | integer |
sales | sales | integer |
volume | volume | numeric |
median_price | median_price | numeric |
listings | listings | integer |
months_inventory | months_inventory | numeric |
#Descriptive statistics
kable(summary(data), caption = "Descriptive statistics")
city | year | month | sales | volume | median_price | listings | months_inventory | |
---|---|---|---|---|---|---|---|---|
Length:240 | Min. :2010 | Min. : 1.00 | Min. : 79.0 | Min. : 8.166 | Min. : 73800 | Min. : 743 | Min. : 3.400 | |
Class :character | 1st Qu.:2011 | 1st Qu.: 3.75 | 1st Qu.:127.0 | 1st Qu.:17.660 | 1st Qu.:117300 | 1st Qu.:1026 | 1st Qu.: 7.800 | |
Mode :character | Median :2012 | Median : 6.50 | Median :175.5 | Median :27.062 | Median :134500 | Median :1618 | Median : 8.950 | |
NA | Mean :2012 | Mean : 6.50 | Mean :192.3 | Mean :31.005 | Mean :132665 | Mean :1738 | Mean : 9.193 | |
NA | 3rd Qu.:2013 | 3rd Qu.: 9.25 | 3rd Qu.:247.0 | 3rd Qu.:40.893 | 3rd Qu.:150050 | 3rd Qu.:2056 | 3rd Qu.:10.950 | |
NA | Max. :2014 | Max. :12.00 | Max. :423.0 | Max. :83.547 | Max. :180000 | Max. :3296 | Max. :14.900 |
Analisi Variabili del Dataset
(Tipo Variabile | Descrizione | Tipo Analisi )
City : Qualitativa Nominale | indica le città a cui si riferiscono i dati | confronto vendite/volume tra città o aree geografiche.
Year : Quantitativa Continua (in questo contesto trattata come qualitativa ordinale) | Anno di osservazione | analisi di trend.
Month : Qualitativa nominale (ciclica) | indica Mese di osservazione | analisi di stagionalità.
Sales : Quantitativa Discreta | numero totale di case vendute. | Analisi Descrittiva della domanda immobiliare (media, dispersione, distribuzione)
Volume : Quantitativa continua | Valore totale delle vendite (in milioni di dollari). | Analisi descrittiva del giro d’affari del mercato (media, dispersione, distribuzione)
Median Price : Quantitativa Continua | prezzo mediano di vendita (in dollari) | Analisi Descrittiva sul livello dei prezzi delle case
Listings : Quantitativa Discreta | numero totale di annunci attivi | Analisi dell’offerta immobiliare (media, dispersione, distribuzione).
months_inventory : Quantitativa Continua | Tempo (in mesi) stimato per vendere tutte le inserzioni correnti. | Indicatore dell’equilibrio domanda/offerta.
Tipo Analisi Possibili :
City -> Confronto tra gruppi
Year / Month -> Trend e Stagionalità
Variabili Quantitative -> Distribuzioni, Variabilità e Correlazione
Per Variabili Quantitative (
sales
, volume
,
median_price
, listings
,
month_inventory
)
-> Calcolo indici di :
Posizione : Media, Mediana, Minimo , Massimo , Quartili
Variabilità : Varianza , Deviazione Standard , Range
Forma : Asimmetria , Curtosi
Per variabili quantitative/temporali
(city
, year
, month
)
-> Calcolo Distribuzione di frequenza
library(knitr)
library(moments)
#Define the quantitative variables
var_quant <- c("sales","volume","median_price","listings","months_inventory")
#Function to calculate the requested indices
calc_stas<- function(x){
c(
Media = mean(x, na.rm = TRUE),
Mediana = median(x, na.rm = TRUE),
Minimo = min(x, na.rm = TRUE),
Massimo = max(x, na.rm = TRUE),
Quartile_1 = quantile(x, 0.25, na.rm = TRUE),
Quartile_3 = quantile(x, 0.75, na.rm = TRUE),
Varianza = var(x, na.rm = TRUE),
Dev_Std = sd(x, na.rm = TRUE),
Range = diff(range(x, na.rm = TRUE)),
IQR = IQR(x, na.rm = TRUE),
Asimmetria = skewness(x, na.rm = TRUE),
Curtosi = kurtosis(x, na.rm = TRUE)
)
}
#Apply the function to the qualitative variables
stats_df <- sapply(data[var_quant], calc_stas)%>%
round(2) %>%
as.data.frame()
stats_df<- tibble::rownames_to_column(stats_df,var= "Measure")
#Final table
kable(stats_df, caption = "Indices by size (rows) and variable (columns)")
Measure | sales | volume | median_price | listings | months_inventory |
---|---|---|---|---|---|
Media | 192.29 | 31.01 | 132665.42 | 1738.02 | 9.19 |
Mediana | 175.50 | 27.06 | 134500.00 | 1618.50 | 8.95 |
Minimo | 79.00 | 8.17 | 73800.00 | 743.00 | 3.40 |
Massimo | 423.00 | 83.55 | 180000.00 | 3296.00 | 14.90 |
Quartile_1.25% | 127.00 | 17.66 | 117300.00 | 1026.50 | 7.80 |
Quartile_3.75% | 247.00 | 40.89 | 150050.00 | 2056.00 | 10.95 |
Varianza | 6344.30 | 277.27 | 513572983.09 | 566568.97 | 5.31 |
Dev_Std | 79.65 | 16.65 | 22662.15 | 752.71 | 2.30 |
Range | 344.00 | 75.38 | 106200.00 | 2553.00 | 11.50 |
IQR | 120.00 | 23.23 | 32750.00 | 1029.50 | 3.15 |
Asimmetria | 0.72 | 0.88 | -0.36 | 0.65 | 0.04 |
Curtosi | 2.69 | 3.18 | 2.38 | 2.21 | 2.83 |
Sales :
Distribuzione Asimmetrica : Media (192.3) e Mediana (175.3) non coincidono. Asimmetria Positiva (Asim_Index: 0.72) con pochi picchi molto alti e infatti sono più frequenti i valori bassi (quindi con una coda verso Dx). La curtosi è sotto 3 (Kurtosis : 2.69) , sottolineando che la distribuzione è più piatta di una distribuzione normale. La variabilità è leggermente alta (sd: 79.7) e Range e IQR sono molto diversi tra loro e quindi potrebbe suggerire presenza di outlier.
Volume :
Distribuzione Asimmetrica : Media (31.01) e Mediana (27.062) non coincidono. Asimmetria Positiva (Asim_Index: 0.84,) con pochi picchi molto alti e infatti sono più frequenti i valori bassi (quindi con una coda verso Dx). La curtosi è sopra 3 (Kurtosis : 3.17) , indicando che le code sono un pò più pesanti e quindi leggermente leptocurtiche. La variabilità è moderata (sd: 16.7) ma la differenza marcata tra Range e IQR potrebbe suggerire anche in questo caso presenza di outlier.
Median Price :
Distribuzione quasi simmetrica : Media e Mediana quasi coincidono, AVG: 132 665,42, Mediana: 134 500 ), con lieve asimmetria negativa (Asim_Index: -0.36) . La curtosi è sotto 3 , sottolineando che la distribuzione è più piatta di una distribuzione normale (Kurtosis : 2.38). Tuttavia La variabilità è molto alta (sd : 22662.15) rispetto alla media, suggerendo un alta eterogeneità dei prezzi.
Listings :
Distribuzione leggermente asimmetrica : Media e Mediana quasi coincidono (AVG: 1738.02, Mediana: 1618.5). Asimmetria Positiva (Asim_Index: 0.65). La curtosi è molto sotto 3 (Kurtosis : 2.21), sottolineando che la distribuzione è più piatta di una distribuzione normale (distribuzione platicurtica) . La dispersione è elevata come mostrato dalla deviazione standard molto ampia (sd: 752.7). Inoltre l’asimmetria e la curtosi indicano che la distribuzione è leggermente spostata verso valori alti.
Month Inventory :
Distribuzione sostanzialmente simmetrica : Media e Mediana quasi coincidono , con bassa variabilità (sd : 2.3) e una bassa asimmetria (Asim_Index: 0.04, Kurtosis : 2.82). La sua distribuzione si avvicina a quella di una distribuzione normale.
Coefficienti da impiegare per confrontare “Variabilità” & “Asimmetria” :
Variabilità : utilizzo il coefficiente di variazione ( CV = sd / mean ), che essendo un valore percentuale permette il confronto tra scale diverse.
Asimmetria : utilizzo la funzione “skewness” e verifico la variabile con valore più alto (in questo caso distribuzione più asimmetrica).
library(moments)
var<- c("sales","volume", "median_price", "listings", "months_inventory")
#function
ds<- function(x){
return(sd(x))
}
cv <- function(x){
return(sd(x, na.rm = TRUE)/mean(x, na.rm= TRUE)*100)
}
sk <- function(x){
return(skewness(x))
}
#apply to the variables
DV<-sapply(data[var],ds)
CV<- sapply(data[var], cv)
SK<- sapply(data[var], sk)
#combine into table
results <- data.frame(
Variable = var,
Deviazione_Std = round(DV, 2),
Coeff_Var = round(CV, 2),
Skewness = round(SK, 2)
)
#sorting
return_CV<- results[order(-results$Coeff_Var),]
return_SK<- results[order(-results$Skewness),]
# Tabellar Output
kable(results, caption ="Standard deviation, Coefficient of variation, Skewness")
Variable | Deviazione_Std | Coeff_Var | Skewness | |
---|---|---|---|---|
sales | sales | 79.65 | 41.42 | 0.72 |
volume | volume | 16.65 | 53.71 | 0.88 |
median_price | median_price | 22662.15 | 17.08 | -0.36 |
listings | listings | 752.71 | 43.31 | 0.65 |
months_inventory | months_inventory | 2.30 | 25.06 | 0.04 |
kable(return_CV, caption = "Variables sorted by coefficient of variation (in descending order)")
Variable | Deviazione_Std | Coeff_Var | Skewness | |
---|---|---|---|---|
volume | volume | 16.65 | 53.71 | 0.88 |
listings | listings | 752.71 | 43.31 | 0.65 |
sales | sales | 79.65 | 41.42 | 0.72 |
months_inventory | months_inventory | 2.30 | 25.06 | 0.04 |
median_price | median_price | 22662.15 | 17.08 | -0.36 |
kable(return_SK, caption = "Variables sorted by skewness (in descending order)")
Variable | Deviazione_Std | Coeff_Var | Skewness | |
---|---|---|---|---|
volume | volume | 16.65 | 53.71 | 0.88 |
sales | sales | 79.65 | 41.42 | 0.72 |
listings | listings | 752.71 | 43.31 | 0.65 |
months_inventory | months_inventory | 2.30 | 25.06 | 0.04 |
median_price | median_price | 22662.15 | 17.08 | -0.36 |
Variabilità ( Deviazione Standard & Coefficiente di Variazione CV )
La Variabile con la maggiore deviazione standard è “median_price” (22662) , ma ha diversa unità di misura rispetto alle altre variabili e questo influisce sulla sua scala di grandezza.
Per un confronto più equo , utilizzo il CV (coefficiente di variazione): la variabile con una maggiore variabilità relativa risulta ” volume ” (CV = 53,7%). Questo indica che nel caso della variabile “volume” i dati si disperdono del 53,7% rispetto alla media.
Asimmetria ( Skewness )
La variabile che risulta più asimmetrica è ” volume ” , con indice di skewness pari a 0,88 (Asimmetria Positiva e quindi coda verso destra).
Un’asimmetria positiva significa che la distribuzione è caratterizzata da molti valori bassi e pochi alti che trascinano la coda a destra.
Per svolgere questa analisi ho usato come variabile ” sales ” (variabile quantitativa discreta).
Costruzione delle Classi
Ho calcolato l’ampiezza di ogni classe alla larghezza della variabile per determinare il range e i n seguito ho suddiviso il range in 10 intervalli di uguale ampiezza.
Calcolo Frequenza assoluta, relativa e cumulata.
Creazione del Grafico della distribuzione :
Ho rappresentato le frequenze assolute con un grafico a barre, ruotando le etichette per migliorarne la leggibilità.
library(dplyr)
library(knitr)
#Choosen Variable
var<- data$sales
#Classe Number (es. 10) and width
n_classi<-10
ampiezza <- ceiling((max(var) - min(var)) / n_classi)
#Create intervals
breaks<- seq(from = floor(min(var)),
to = ceiling(max(var)+ampiezza),
by= ampiezza
)
#Classes Labels
etichette<- paste(head(breaks,-1), breaks[-1], sep = " - ")
#frequency Table
freq_table<- data.frame(
class= cut(var, breaks = breaks, labels = etichette, right = FALSE),
stringsAsFactors = FALSE
) %>%
group_by(class) %>%
summarise(
Absolute_frequency = n(),
.groups = 'drop'
) %>%
mutate(
Relative_frequency = Absolute_frequency / sum(Absolute_frequency),
Cumulative_frequency = cumsum(Relative_frequency)
) %>%
mutate(across(c(Relative_frequency, Cumulative_frequency), ~ round(.x, 2)))
#Tabular output
kable(freq_table, caption= "Frequency distribution for the variable sales")
class | Absolute_frequency | Relative_frequency | Cumulative_frequency |
---|---|---|---|
79 - 114 | 40 | 0.17 | 0.17 |
114 - 149 | 46 | 0.19 | 0.36 |
149 - 184 | 45 | 0.19 | 0.55 |
184 - 219 | 32 | 0.13 | 0.68 |
219 - 254 | 21 | 0.09 | 0.77 |
254 - 289 | 20 | 0.08 | 0.85 |
289 - 324 | 18 | 0.07 | 0.92 |
324 - 359 | 9 | 0.04 | 0.96 |
359 - 394 | 6 | 0.03 | 0.99 |
394 - 429 | 3 | 0.01 | 1.00 |
library(ggplot2)
ggplot(freq_table, aes(x = class, y = Absolute_frequency)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(title = "Frequency Distribution - Sales",
x = "Sales Classes",
y = "Absolute Frequency") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Formula :
\(G = 1-Σ fi^2\)
dove \(fi\) sono le frequenze relative per classe.
G = 0 -> Distribuzione concentrata in poche classi (Bassa Eterogeneità)
G = 1 -> Distribuzione più uniforme (alta eterogeneità)
#Absolute Frequency
ni<- freq_table$Absolute_frequency
#Relative Frequency
fi<- ni/length(data$sales)
fi2<- fi^2
j<- length(ni)
# Gini Index
gini <- 1 - sum(fi2)
# Normalized Gini Index
gini_norm <- gini / ((j - 1) / j)
# Tabular Output
gini_df <- data.frame(
Indice_Gini = round(gini, 3),
Indice_Gini_Normalizzato = round(gini_norm, 3)
)
kable(gini_df, caption = "Gini Index per variable 'sales'")
Indice_Gini | Indice_Gini_Normalizzato |
---|---|
0.86 | 0.956 |
Dato che G = 0,86 , la distribuzione del sales è abbastanza eterogenea , quindi non tutte le vendite sono concentrate nella stessa classe.
G = 0,86 ( Gini normalizzata = 0,956) , la distribuzione del sales è abbastanza eterogenea , quindi non tutte le vendite sono concentrate nella stessa fascia e si distribuiscono in modo diversificato.
Dal grafico a barre si può osservare che la maggioranza delle sales cadono tra 114 e 184 unità, ma sono presenti anche classi con frequenze minori , che contribuiscono all’elevato valore di eterogeneità.
Richiesta : “Qual è la probabilità che, presa una riga a caso di questo dataset, essa riporti la città “Beaumont”? E la probabilità che riporti il mese di Luglio? E la probabilità che riporti il mese di dicembre 2012?“
Per risolvere tutte e 3 le richieste utilizzo il metodo di calcolo della Probabilità Classica :
\(P(evento) = n° Casi favorevoli/ n° Tot casi Possibili\)
dove :
casi favorevoli = osservazioni che soddisfano la condizione dell’evento
casi possibili = numero totale di osservazioni nel dataset
library(knitr)
n_tot <- nrow(data)
#Probability city = Beaumont
n_beaumont <- sum(data$city == "Beaumont")
p_beaumont <- n_beaumont / n_tot
p_beaumont
## [1] 0.25
#Probability July month
n_july <- sum(data$month == 7)
p_july <- n_july / n_tot
p_july
## [1] 0.08333333
#Probability December 2012
n_dec_2012 <- sum(data$month == 12 & data$year == 2012)
p_dec_2012 <- n_dec_2012 / n_tot
p_dec_2012
## [1] 0.01666667
➽ RESUME
# Resume Table
prob_df <- data.frame(
Event = c("City = Beaumont", "Month = July", "Data = December 2012"),
Favorable_cases = c(n_beaumont, n_july, n_dec_2012),
Possible_cases = n_tot,
Probability = round(c(p_beaumont, p_july, p_dec_2012), 4)
)
kable(prob_df, caption = "Probabilities calculated using the classical definition")
Event | Favorable_cases | Possible_cases | Probability |
---|---|---|---|
City = Beaumont | 60 | 240 | 0.2500 |
Month = July | 20 | 240 | 0.0833 |
Data = December 2012 | 4 | 240 | 0.0167 |
P(City = Beaumont) = 25% → indica la probabilità che un’osservazione scelta a caso appartenga alla città di Beaumont.
P(Month = July) = 8,3% → indica la probabilità che un’osservazione sia relativa al mese di luglio.
P(December 2012)= 1,67% → indica la probabilità che un’osservazione sia relativa a dicembre 2012.
Per calcolare il prezzo medio degli immobili ho effettutato il
rapporto tra ” volume
” ( valore totale delle vendite ,
espressa in milioni ) e ” sales
” (numero di immobili
venduti)
library(knitr)
#Average Real Estate Price
data$avg_price<- data$volume *10^6/data$sales
#Extracted var AVG Real Estate Price
kable(
head(data[, c("city", "year", "month", "sales", "volume", "listings", "avg_price")]),
caption = "AVG Price - extract dataset"
)
city | year | month | sales | volume | listings | avg_price |
---|---|---|---|---|---|---|
Beaumont | 2010 | 1 | 83 | 14.162 | 1533 | 170626.5 |
Beaumont | 2010 | 2 | 108 | 17.690 | 1586 | 163796.3 |
Beaumont | 2010 | 3 | 182 | 28.701 | 1689 | 157697.8 |
Beaumont | 2010 | 4 | 200 | 26.819 | 1708 | 134095.0 |
Beaumont | 2010 | 5 | 202 | 28.833 | 1771 | 142737.6 |
Beaumont | 2010 | 6 | 189 | 27.219 | 1803 | 144015.9 |
Per calcolare l’efficacia degli annunci di vendita , ho effettuato il
rapporto tra ” sales
” ( vendite effettive ) e ”
listings
” ( numero di annunci ). Questo nuovo indice
permette di misurare l’efficacia degli annunci di vendita.
#Ads Efficency
data$efficency<- data$sales/data$listings
data$efficency<-round(data$efficency,2)
#Extracted var Ads Efficency
kable(
head(data[, c("city", "year", "month", "sales", "volume", "listings","avg_price", "efficency")]),
caption = "AVG Price + Ads Efficency - extract dataset"
)
city | year | month | sales | volume | listings | avg_price | efficency |
---|---|---|---|---|---|---|---|
Beaumont | 2010 | 1 | 83 | 14.162 | 1533 | 170626.5 | 0.05 |
Beaumont | 2010 | 2 | 108 | 17.690 | 1586 | 163796.3 | 0.07 |
Beaumont | 2010 | 3 | 182 | 28.701 | 1689 | 157697.8 | 0.11 |
Beaumont | 2010 | 4 | 200 | 26.819 | 1708 | 134095.0 | 0.12 |
Beaumont | 2010 | 5 | 202 | 28.833 | 1771 | 142737.6 | 0.11 |
Beaumont | 2010 | 6 | 189 | 27.219 | 1803 | 144015.9 | 0.10 |
Il risultato sarà compreso tra 0 & 1 :
valori vicini a 1 -> alta Efficacia : Quasi tutti gli annunci hanno generato una vendita
valori vicini a 0 -> Bassa Efficacia : Molti annunci non si trasformano in vendita
Analizzo nel dettaglio come le 2 variabili si distribuiscono e concentrano la maggior parte degli immobili per AVG Price & Ads efficiency.
#Summary Table "AVG Price"
tabella_summary <- data.frame(
Statistic = names(summary(data$avg_price)),
Value = as.numeric(summary(data$avg_price))
)
kable(tabella_summary, caption = "Descriptive statistics of avg_price")
Statistic | Value |
---|---|
Min. | 97010.2 |
1st Qu. | 132938.9 |
Median | 156588.5 |
Mean | 154320.4 |
3rd Qu. | 173915.2 |
Max. | 213233.9 |
#Histogram x AVG_Price
library(ggplot2)
ggplot(data)+
geom_histogram(aes(x= avg_price),binwidth = 10000 ,fill= "lightblue",color= "black")+
geom_vline(xintercept = 132939, color= "red",lty="dashed", lwd=2)+
geom_vline(xintercept = 173915, color= "red",lty= "dashed", lwd=2)+
labs(title = "Distribution of Real Estate's AVG price", x="AVG Price [$]", y="Frequency")+
theme_classic()
#Line Chart x Avg-Price
data$period <- as.Date(paste(data$year, data$month, "01", sep = "-"))
data$period <- as.Date(paste(data$year, data$month, "01", sep = "-"))
ggplot(data)+geom_line(aes(x = period, y = avg_price, color = city, group = city)) +
geom_point(aes(x = period, y = avg_price, color = city, group = city),size = 1) +
labs(title = "AVG Price for city in time",
x = "Period",
y = "AVG Price ($)") +
scale_x_date(date_labels = "%Y-%m")+theme_minimal()+
theme(legend.position = "bottom")
Range : I prezzi medi oscillano tra 97.000 $ e i 213.000 $.
Quartili : il 1° Quartile ( 132.939 $) e il 3° quartile (173.915 $) racchiudono il 50% centrale delle osservazioni.
Mediana : Pari a 156.588 $ ) è molto vicina alla Media ( 154.320 $ ) , suggerendo una distribuzione abbastanza simmetrica.
Concentrazione : La maggior parte degli immobili ha un prezzo medio di vendita tra 130.000 $ - 175.000 $ , con alcuni valori estremi ( 97.000$ - 21000 $ ).
Trend Temporale : dal 2010 al 2011, Il prezzo medio mantiene un andamento costante per tutte le città , mentre dal 2012 si denota una tendenza alla crescita, sopratutto per città come Bryan-Collage Station.
data_efficiency_sort<- data[order(data$efficency),]
kable(
head(data_efficiency_sort[, c("city", "year", "month", "sales", "volume", "listings", "avg_price", "efficency")]),
caption = "Ads efficency sorted - dataset Extract"
)
city | year | month | sales | volume | listings | avg_price | efficency | |
---|---|---|---|---|---|---|---|---|
1 | Beaumont | 2010 | 1 | 83 | 14.162 | 1533 | 170626.5 | 0.05 |
131 | Tyler | 2010 | 11 | 155 | 24.411 | 3042 | 157490.3 | 0.05 |
133 | Tyler | 2011 | 1 | 143 | 21.050 | 2852 | 147202.8 | 0.05 |
13 | Beaumont | 2011 | 1 | 108 | 16.200 | 1677 | 150000.0 | 0.06 |
14 | Beaumont | 2011 | 2 | 108 | 16.187 | 1691 | 149879.6 | 0.06 |
73 | Bryan-College Station | 2011 | 1 | 94 | 15.242 | 1480 | 162148.9 | 0.06 |
#Summary Table "AVG Price"
tabella_summary <- data.frame(
Statistic = names(summary(data$efficency)),
Value = as.numeric(summary(data$efficency))
)
kable(tabella_summary, caption = "Descriptive statistics of ADS efficency")
Statistic | Value |
---|---|
Min. | 0.0500000 |
1st Qu. | 0.0900000 |
Median | 0.1100000 |
Mean | 0.1184167 |
3rd Qu. | 0.1325000 |
Max. | 0.3900000 |
#Line Chart x Avg-Price
ggplot(data)+geom_line(aes(x = period, y = efficency, color = city, group = city))+
geom_point(aes(x = period, y = efficency, color = city, group = city),size = 1) +
labs(title = "Ads efficency for city in time",
x = "Period",
y = "Ads efficency") +
scale_x_date(date_labels = "%Y-%m")+theme_minimal()+
theme(legend.position = "bottom")
Range : Il tasso di conversione tra annuncio pubblicitario e vendita immobile varia tra 5% e 39% -> range non elevato , con qualche outlier verso l’alto che si stacca dalla maggior parte della distribuzione.
Quartili : il 1° Quartile ( 8,9 %) e il 3° quartile (13,49% ) racchiudono il 50% centrale delle efficienze.
Mediana : Pari a 10,96 % è leggermente superiore alla Media ( 11,87 % ) e questo suggerisce una leggera asimmetria verso destra dovuto a pochi annunci molto efficienti (+ valori bassi nella distribuzione).
Concentrazione : La maggior parte degli annunci ha un tasso di conversione tra il 9% e il 13 % , con pochi casi oltre il 20%.
Trend Temporale : Dal 2010 - 2011 l’efficienza resta bassa (5 % -10%) ; dal 2012 si denota un trend crescente , con gran parte delle città che arriva tra il 10% e il 15%. Dal 2013 si registra un trend crescente raggiungendo picchi notevoli (Le città che raggiunge più rapidamente questi picchi è Bryan-College Station).
AVG Price : I prezzi medi degli immobili si attesta intorno ai 150-170k $ con un distribuzione abbastanza simmetrica/ equilibrata
Ads Efficency : il tasso di conversione pubblicità / vendita degli immobili si concentra sul 10 % con pochi casi che innalzano la media. Dal 2012 mostra un trend crescente nel tempo, suggerendo un miglioramento delle capacità di convertire gli annunci di vendite.
Usa il pacchetto dplyr
o il linguaggio base di R per
effettuare analisi statistiche condizionate per città, anno e mese.
Genera dei summary (media, deviazione standard) e
rappresenta graficamente i risultati.
Inizialmente generiamo dei summary (media e deviazione standard) per effettuare analisi statistiche condizionate per città , anno, mese.
library(dplyr)
#Mean & standard deviation for City & Year/Month
summary_city_year<- data %>%
group_by(city,year) %>%
summarise(
mean_sales = mean(sales, na.rm= TRUE),
sd_sales = sd(sales, na.rm = TRUE),
mean_volume = mean(volume, na.rm = TRUE),
sd_volume = sd(volume, na.rm= TRUE),
mean_listings = mean(listings, na.rm= TRUE),
sd_listings= sd(listings, na.rm = TRUE),
mean_avg_price = mean(avg_price, na.rm = TRUE),
sd_avg_price = sd(avg_price, na.rm = TRUE),
mean_efficency = mean(efficency, na.rm = TRUE ),
sd_efficency = sd(efficency, na.rm = TRUE),
.groups= "drop"
)
kable(head(summary_city_year), caption = "Average and Standard Deviation per city and year")
city | year | mean_sales | sd_sales | mean_volume | sd_volume | mean_listings | sd_listings | mean_avg_price | sd_avg_price | mean_efficency | sd_efficency |
---|---|---|---|---|---|---|---|---|---|---|---|
Beaumont | 2010 | 156.1667 | 36.92457 | 22.65383 | 4.954348 | 1731.083 | 101.90768 | 146582.5 | 13960.173 | 0.0900000 | 0.0200000 |
Beaumont | 2011 | 144.0000 | 22.65552 | 21.09525 | 4.300522 | 1747.917 | 74.67439 | 145921.9 | 12655.337 | 0.0808333 | 0.0131137 |
Beaumont | 2012 | 171.9167 | 28.38840 | 24.46767 | 4.921853 | 1691.333 | 54.55662 | 141475.9 | 10345.771 | 0.1016667 | 0.0158592 |
Beaumont | 2013 | 201.1667 | 37.73070 | 30.30917 | 6.436956 | 1639.583 | 54.91888 | 150079.0 | 6245.121 | 0.1233333 | 0.0210339 |
Beaumont | 2014 | 213.6667 | 36.48993 | 32.13208 | 7.049593 | 1586.667 | 57.37331 | 149142.7 | 11234.169 | 0.1341667 | 0.0227470 |
Bryan-College Station | 2010 | 167.5833 | 70.75368 | 28.73117 | 10.817885 | 1562.417 | 165.15748 | 174601.8 | 11964.068 | 0.1050000 | 0.0382575 |
Ora posso utilizzare questo summarise per le seguenti variabili :
sales
, volume
, avg_price
,
listings
, efficency
per costruire dei grafici
per visualizzare analisi statistiche condizionate per città , anno ,
mese.
#Graphics per Year
library(scales)
library(ggplot2)
#Barplot x Sales
ggplot(summary_city_year, aes(x= year, y= mean_sales, fill=city))+
geom_bar(stat= "identity", position= "dodge")+
geom_errorbar(aes(ymin=mean_sales-sd_sales, ymax = mean_sales+sd_sales), position = position_dodge(width = 0.9))+geom_text(aes(label = round(mean_sales, 1)),position = position_dodge(width = 0.9), size=2.5, vjust= -0.4, hjust= 0.5) +
labs(title= "Avg Sales Trend per city", x= "Year", y= "Avg Sales")+theme_gray()+
theme(legend.position = "bottom")
#Barplot x Volume
ggplot(summary_city_year, aes(x= year, y= mean_volume, fill=city))+
geom_bar(stat= "identity", position="dodge")+
geom_errorbar(aes(ymin=mean_volume-sd_volume, ymax = mean_volume+sd_volume), position = position_dodge(width = 0.9))+
geom_text(aes(label = round(mean_volume, 1)),position = position_dodge(width = 0.9), size=2.5, vjust= -0.4, hjust= 0.5) +
labs(title= "Avg Volume Trend per city", x= "Year", y= "Avg Volume [$]")+theme_gray()+theme(legend.position = "bottom")
#Barplot x Listings
ggplot(summary_city_year, aes(x= year, y= mean_listings, fill=city))+
geom_bar(stat= "identity", position="dodge")+
geom_errorbar(aes(ymin=mean_listings- sd_listings, ymax = mean_listings+sd_listings), position = position_dodge(width = 0.9))+geom_text(aes(label = round(mean_listings, 1)),position = position_dodge(width = 0.9), size=2.5, vjust= -0.4, hjust= 0.5)+
labs(title= "Listings Trend per city", x= "Year", y= "N° Listings")+theme_grey()+theme_gray()+theme(legend.position = "bottom")
#Barplot x AVG Price
ggplot(summary_city_year, aes(x= year, y= mean_avg_price, fill=city))+
geom_bar(stat= "identity", position="dodge")+
geom_errorbar(aes(ymin=mean_avg_price- sd_avg_price, ymax = mean_avg_price+sd_avg_price), position = position_dodge(width = 0.9))+ geom_text(aes(label = round(mean_avg_price, 1)),position = position_dodge(width = 0.9), size=2.5, vjust= -0.4, hjust= 0.5)+ labs(title= "Avg Price Trend per city", x= "Year", y= "Avg Price [$]")+theme_gray()+theme_gray()+theme(legend.position = "bottom")
#Barplot x Ads Efficency
ggplot(summary_city_year, aes(x= year, y= mean_efficency, fill=city))+
geom_bar(stat= "identity", position= "dodge")+
geom_errorbar(aes(ymin=mean_efficency- sd_efficency, ymax = mean_efficency+sd_efficency), position = position_dodge(width = 0.9))+ geom_text(aes(label = round(mean_efficency, 3)),position = position_dodge(width = 0.9), size=2.5, vjust= -0.4, hjust= 0.5)+ labs(title= "Ads Efficency Trend per city", x= " Year", y= "Ads Efficency")+theme_grey()+theme_gray()+theme(legend.position = "bottom")
library(dplyr)
#Add Var "Period" : Month +Year
summary_city_month <- data %>%
group_by(city,year, month) %>%
summarise(
mean_sales = mean(sales, na.rm= TRUE),
sd_sales = sd(sales, na.rm = TRUE),
mean_volume = mean(volume, na.rm = TRUE),
sd_volume = sd(volume, na.rm= TRUE),
mean_listings = mean(listings, na.rm= TRUE),
sd_listings= sd(listings, na.rm = TRUE),
mean_avg_price = mean(avg_price, na.rm = TRUE),
sd_avg_price = sd(avg_price, na.rm = TRUE),
mean_efficency = mean(efficency, na.rm = TRUE ),
sd_efficency = sd(efficency, na.rm = TRUE),
.groups = "drop"
)%>%
mutate(period = as.Date(paste(year, month, "01", sep = "-")))
#Barplot x Sales
ggplot(summary_city_month, aes(x = period, y = mean_sales, color = city, group = city)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_sales - sd_sales, ymax = mean_sales + sd_sales), width = 10) +
scale_x_date(date_labels = "%m-%Y", date_breaks = "6 months") +
labs(title = "Avg Sales Trend per city (2010–2014)",
x = "Period", y = "Avg Sales") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
## 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.
#Barplot x Volume
ggplot(summary_city_month, aes(x = period, y = mean_volume, color = city, group = city)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_volume - sd_volume, ymax = mean_volume + sd_volume), width = 10) +
scale_x_date(date_labels = "%m-%Y", date_breaks = "6 months") +
labs(title = "Avg Volume Trend per city (2010–2014)",
x = "Period", y = "Avg Volume [$]") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
#Barplot x Listings
ggplot(summary_city_month, aes(x = period, y = mean_listings, color = city, group = city)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_listings - sd_listings, ymax = mean_listings + sd_listings), width = 10) +
scale_x_date(date_labels = "%m-%Y", date_breaks = "6 months") +
labs(title = "Listings Trend per city (2010–2014)",
x = "Period", y = "N° Listings") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
#Barplot x AVG Price
ggplot(summary_city_month, aes(x = period, y = mean_avg_price, color = city, group = city)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_avg_price - sd_avg_price, ymax = mean_avg_price + sd_avg_price), width = 10) +
scale_x_date(date_labels = "%m-%Y", date_breaks = "6 months") +
labs(title = "Avg Price Trend per city (2010–2014)",
x = "Period", y = "Avg Price [$]") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
#Barplot x Ads Efficency
ggplot(summary_city_month, aes(x = period, y = mean_efficency, color = city, group = city)) +
geom_line(size = 1) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = mean_efficency - sd_efficency, ymax = mean_efficency + sd_efficency), width = 10) +
scale_x_date(date_labels = "%m-%Y", date_breaks = "6 months") +
labs(title = "Ads Efficency Trend per city (2010–2014)",
x = "Period", y = "Ads Efficency") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
Beaumont : Ha una crescita moderata in termini di vendite e ricavi dalle vendite, con picchi solo nel 2013 e nel 2014. Questo può essere dovuto a uno dei più bassi tassi di conversione annuncio - vendita degli immobili. Beaumont si dimostra tra le città peggiori in termini di vendite; un aumento di annunci pubblicitari porterebbe portare un drastico incremento del fatturato.
Bryan-College Station : si dimostra la città con la crescita migliore in termini di vendita, ricavi, prezzi medi. Per ora dimostra un volume di vendita e un fatturato peggiore rispetto a Tyler , probabilmente dovuti a bassi investimenti in annunci pubblicitari. Tuttavia dimostra sempre un alto tasso di conversione e ciò potrebbe suggerire un maggiore investimento in advertising per consentire una crescita sostanziale delle vendite.
Tyler : presenta un crescita solida in termini di vendite e ricavi, ma ciò è dovuto a maggior investimenti in annunci pubblicitari e un minor prezzo medio degli immobili venduti rispetto a Bryan-College Station. La sua efficienza pubblicitaria è buona ma non eccellente. Per Tyler è preferibile ottimizzare il rapporto tra pubblicità e prezzi medi contenuti per aumentare i ricavi.
Wichita Falls : mostra le performance più basse in termini di vendite e ricavi di vendita , nonostante ha tassi di conversione più alti rispetto ad altre città come Beaumont e Tyler. Quindi l’unico modo per risollevare le vendite in questa città sembra essere un aumento significativo degli investimenti pubblicitari.
Sintesi : Bryan-College Station mostra la crescita più marcata sia nelle vendite che nei prezzi medi , con alta efficienza pubblicitaria. Tyler mantiene vendite solide grazie a investimenti pubblicitari ma con prezzi medi più bassi. Beaumont e Wichita Falls restano indietro: la prima per bassi tassi di conversione, la seconda per volumi di vendita ridotti nonostante una buona efficienza. In entrambi i casi, maggiori investimenti in advertising potrebbero migliorare le performance.
#Boxplot Avg Price x city
ggplot(data, aes(x = factor(year), y = median_price, fill = city)) +
geom_boxplot() +
labs(title = "Median Price Boxplot per City and Year",
x = "Year", y = "Median Price [$]") +
theme_minimal() +
theme(legend.position = "bottom")
Insights :
Beaumont : Mediana intermedia (= 130k $) , posizionato nella fascia intermedia rispetto alle altre città. La variabilità è moderata, con outlier isolato che indica la presenza di pochi immobili di valore molto superiore alla media. Questo suggerisce un mercato tendenzialmente omogeneo, ma con qualche episodio di vendita di immobili di lusso che però non incide sulla distribuzione complessiva.
Bryan-College Station : Mediana più alta (= 157k $) e una variabilità contenuta. La stabilità dei valori, unita alla collocazione nella fascia alta, riflette un mercato caratterizzato da domanda costante per immobili di qualità e da un’offerta che si mantiene su livelli di prezzo sostenuti. Potrebbe indicare un’area con forte attrattività residenziale e da acquirenti con un buon reddito.
Tyler : Mediana intermedia (= 141k $) ma con un IQR più ampio rispetto a Beaumont e Bryan‑College Station. Questo segnala una maggiore dispersione dei prezzi, con immobili il cui prezzo medio spazia sia nella fascia media sia in quella più economica. Tale configurazione può riflettere un mercato eterogeneo, in cui coesistono quartieri con valori più accessibili e zone con immobili di livello superiore.
Wichita Falls : Mediana nettamente più bassa (102,7k $) e IQR ridotto , a indicare un mercato con immobili a basso prezzo e valori fortemente concentrati attorno alla mediana. La scarsa variabilità suggerisce un’offerta piuttosto uniforme, con poche eccezioni verso l’alto, tipica di mercati meno dinamici.
#BarChart Sales x month & city
library(dplyr)
sales_monthly <- data %>%
group_by(year, month, city) %>%
summarise(total_sales = sum(sales, na.rm = TRUE), .groups = "drop")
ggplot(sales_monthly, aes(x = factor(month), y = total_sales, fill = city)) +
geom_bar(stat = "identity", position = "dodge") +
facet_wrap(~year, ncol = 2) +
labs(title = "Sales Trend per city and month",
x = "Month", y = "Total Sales") +
theme_minimal() +
theme(legend.position = "bottom")
Insights :
Andamento generale : Le vendite mostrano una tendenza complessivamente stabile nella maggior parte delle città analizzate, con oscillazioni fisiologiche legate alla stagionalità. L’eccezione più evidente è Bryan‑College Station,che evidenzia una crescita progressiva e visibile nel tempo, segnale di un mercato in espansione e di una domanda in aumento.
Pattern stagionale : In tutte le città si osservano picchi ricorrenti nei mesi estivi, in particolare tra marzo e settembre, con massimi spesso concentrati in giugno‑luglio. Al contrario, i mesi invernali registrano un calo marcato delle vendite. Questo andamento conferma che la stagionalità è un fattore fondamentale per la pianificazione di strategie commerciali e di marketing, ad esempio concentrando campagne promozionali e attività di vendita nei periodi di maggiore domanda.
data <- data %>%
mutate(date = as.Date(paste(year, month, "01", sep = "-")))
sales_monthly <- data %>%
group_by(date, city) %>%
summarise(total_sales = sum(sales, na.rm = TRUE), .groups = "drop")
ggplot(sales_monthly, aes(x = date, y = total_sales, color = city)) +
geom_line(size = 1) +
geom_point(size = 1.5) +
labs(title = "Storic Sales Trend by City",
x = "Period", y = "Total Sales") +
scale_x_date(date_labels = "%m-%Y", date_breaks = "4 months") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom")
Insights :
Tramite il Line Chart si evidenzia l’evoluzione storica delle vendite immobiliari nelle diverse città, mettendo in evidenza le tendenze di lungo periodo.
Tyler: Si conferma come la città con i volumi di vendita più elevati in tutto l’arco temporale analizzato, mostrando una crescita costante e sostenuta dal 2010 al 2015.
Bryan-Collage Station : presenta un trend in crescita marcata soprattutto tra il 2012 e il 2014, segnale di un’espansione significativa della domanda in quegli anni. La curva suggerisce un mercato in consolidamento, capace di attrarre acquirenti in modo crescente.
Beaumont : mostra un andamento stabile senza variazioni rilevanti per gran parte del periodo, con una lieve crescita negli ultimi due anni. Questo comportamento può indicare un mercato maturo, con incrementi graduali nel tempo.
Wichita Falls è l’unica città a evidenziare un calo delle vendite negli ultimi due anni, dopo una fase iniziale più stabile. Questo potrebbe riflettere un rallentamento della domanda o altri fattori che hanno inciso negativamente sul mercato.
Nel complesso tutte le città , tranne Wichita Falls, mostrano un crescita positiva nel periodo analizzato , sintomo di una fase di espansione del mercato immobiliare, probabilmente sostenuta da una domanda residenziale in aumento e da buone condizioni economiche.
Nel periodo 2010 - 2014, il mercato immobiliare presenta alcune caratteristiche distintive :
Crescita costante : Si osserva una crescita costante sia in termini di vendite che di importo generato dalle vendite , seppur con dinamiche decisamente diverse da città a città.
Stagionalità Marcata : Le vendite di immobili si concentrano tra marzo e settembre, mentre nei mesi invernali si registra un rallentamento significativo.
Segmentazione Netta : Alcune città si attestano su prezzi elevati e stabili, altre privilegiavano i volumi , con prezzi medi più bassi ma un maggiore numero di vendite.
Bryan-College Station
Volumi di Vendita : Vendite e Ricavi crescono in modo rilevante soprattutto dal 2012 in poi.
Prezzo Medio degli Immobili : Prezzo medio è il più alto (175k $) tra le città analizzate , confermando il posizionamento nel segmento dei immobili di fascia alta.
Tasso di conversione tra annunci e vendite : è tra i più alti tra le città analizzate con un picco del 23,6% nel
In termini operativi , conviene incrementare l’investimento pubblicitario per sfruttare al massimo l’efficienza ed aumentare ulteriormente i volumi.
Tyler
Volumi di Vendita : Leader indiscusso in termini di vendite e ricavi in tutta la serie storica.
Prezzo Medio degli Immobili : Il prezzo medio si colloca intorno a 141k $ ma con alta variabilità , segno di un mercato eterogeneo.
Tasso di conversione tra annunci e vendite : l’efficienza pubblicitaria è buona con una media del 10% , ma inferiore dei top performer.
La strategia dovrebbe integrare campagne pubblicitarie mirate con una revisione del pricing, al fine di massimizzare i ricavi per unità venduta.
Beaumont
Volumi di Vendita : andamento stabile per vendite e ricavi , con alcuni picchi nel biennio 2013 - 2014.
Prezzo Medio degli Immobili : Il prezzo medio si colloca intorno a 131k $ , con variabilità contenuta.
Tasso di conversione tra annunci e vendite : l’efficienza pubblicitaria è tra i più bassi.
La priorità è aumentare il numero di annunci e ottimizzare le campagne per migliorare i tassi di conversione.
Wichita Falls
Volumi di Vendita : Vendite e Ricavi sono contenuti e mostrano una tendenza verso il basso.
Prezzo Medio degli Immobili : Prezzo medio basso (circa 102k $) e una bassa variabilità, segno di un mercato omogeneo.
Tasso di conversione tra annunci e vendite : l’efficienza pubblicitaria, rapportata alla dimensione del mercato, è discreta.
Un ampliamento dell’offerta e un potenziamento della visibilità potrebbero stimolare la domanda.
Variabilità : Il coefficiente di variazione è massimo per volume e listings , indicando differenze sostanziali tra mercati per dimensione e valore delle vendite.
Asimmetria : Positiva su vendite e ricavi riflette la presenza di code destre, con pochi casi di valori molto elevati che influenzano la media.
Distribuzione : L’analisi tramite il boxplot conferma la netta separazione nei livelli di prezzo tra città; inoltre la concentrazione in specifiche fasce è evidente; l’indice di Gini evidenzia maggiore eterogeneità nei mercati segmentati.
Sul piano operativo, è fondamentale pianificare le campagne nei mesi di maggiore attività (primavera-estate) per ottimizzare l’impatto.
Strategie specifiche per area :
Bryan-College Station : aumentare i volumi mantenendo elevato il prezzo d’acquisto.
Tyler : lavorare sull’aumento del prezzo medio senza perdere competitività.
Beaumont : migliorare l’efficienza pubblicitaria per valorizzare il potenziale di crescita.
Wichita Falls : ampliare offerta e visibilità per stimolare la domanda.
Le analisi statistiche confermano che le dinamiche locali devono guidare le strategie operative: un approccio uniforme al mercato texano rischierebbe di non valorizzare le specificità di ciascuna area. L’integrazione di analisi descrittive, indici di variabilità e distribuzione, e osservazioni temporali ha permesso di delineare un quadro chiaro delle opportunità e delle criticità per ogni città.