# Carico il dataframe
df = read.csv("realestate_texas.csv")

Analisi della struttura del data frame

head(df)
##       city year month sales volume median_price listings months_inventory
## 1 Beaumont 2010     1    83 14.162       163800     1533              9.5
## 2 Beaumont 2010     2   108 17.690       138200     1586             10.0
## 3 Beaumont 2010     3   182 28.701       122400     1689             10.6
## 4 Beaumont 2010     4   200 26.819       123200     1708             10.6
## 5 Beaumont 2010     5   202 28.833       123100     1771             10.9
## 6 Beaumont 2010     6   189 27.219       122800     1803             11.1

Numero di osservazioni

n = length(df$city)
n
## [1] 240

Il data frame contiene 240 oservazioni e 8 variabili

TIPOLOGIA DI VARIBILI

Variabili Quantitative

Variabili Qualitative

Tipo analisi

  1. city: osservare per ogni città le unita vendute e per quali volumi
  2. year e Month: oservare i trend storici e individuare stagionalità
  3. sales, volume, median price, listings e month inventory: individuare relazioni tra variabili e identificare stragegie per migliorare il business.
attach(df)

Indici di posizione

Esaminate le frequenze per la variabile categoriale city

table(city)
## city
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60

Osservazioni:

Uguale numero di osservazioni per ogni città, uniforme.

summary(sales)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    79.0   127.0   175.5   192.3   247.0   423.0
summary(volume)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   8.166  17.660  27.062  31.005  40.893  83.547
summary(median_price)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   73800  117300  134500  132665  150050  180000
summary(listings)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     743    1026    1618    1738    2056    3296
summary(months_inventory)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   3.400   7.800   8.950   9.193  10.950  14.900

Indici di variabilità

sales

range(sales)
## [1]  79 423
IQR(sales)
## [1] 120
var(sales)
## [1] 6344.3
sd(sales)
## [1] 79.65111

volume

range(volume)
## [1]  8.166 83.547
IQR(volume)
## [1] 23.2335
var(volume)
## [1] 277.2707
sd(volume)
## [1] 16.65145

listings

range(listings)
## [1]  743 3296
IQR(listings)
## [1] 1029.5
var(listings)
## [1] 566569
sd(listings)
## [1] 752.7078

months_inventory

range(months_inventory)
## [1]  3.4 14.9
IQR(months_inventory)
## [1] 3.15
var(months_inventory)
## [1] 5.306889
sd(months_inventory)
## [1] 2.303669

Variabilità

# Creata la funzione per calcolare il coeff. di varibilità
cv = function(x){
  return(sd(x)/mean(x)*100)
  }
cv(sales)
## [1] 41.42203
cv(volume)
## [1] 53.70536
cv(listings)
## [1] 43.30833
cv(months_inventory)
## [1] 25.06031

Osservazioni:

Variabilità del volume delle vendite significativo: 53,70%. Il volume delle vendite varia molto tra le diverse osservazioni

Distribuzione in classi

Mesi di Invetario dell’immobile

# Create le calssi di passo 2 dal volore minimo al massimo della vatibile months_invetory
months_inventory_cl = cut(months_inventory, seq(1, 15, 2))
freq_months = table(months_inventory_cl)

distr_freq_months_inventory = as.data.frame( 
  cbind(
    ni = table(months_inventory_cl),
    fi = table(months_inventory_cl)/n,
    Ni = cumsum(table(months_inventory_cl)),
    Fi = cumsum(table(months_inventory_cl)/n)))
    
distr_freq_months_inventory
##         ni        fi  Ni        Fi
## (1,3]    0 0.0000000   0 0.0000000
## (3,5]   15 0.0625000  15 0.0625000
## (5,7]   15 0.0625000  30 0.1250000
## (7,9]   97 0.4041667 127 0.5291667
## (9,11]  53 0.2208333 180 0.7500000
## (11,13] 48 0.2000000 228 0.9500000
## (13,15] 12 0.0500000 240 1.0000000
barplot(freq_months,
        main = "Distribuzione di Frequenze di Months Inventory",
        xlab = "Classi",
        ylab = "Freq Assolute",
        col = "lightblue")

Osservazioni:

Le proprietà tendono a rimanere nell’inventario tra i 7 e i 9 mesi (classe modale).

Volumi di vendita degli immobili

# Create le calssi di passo 11 dal volore minimo al massimo della vatibile volume
volume_cl = cut(volume, seq(8, 85, 11))
freq_volume = table(volume_cl)

distr_freq_volume_cl = as.data.frame( 
  cbind(
    ni = table(volume_cl),
    fi = table(volume_cl)/n,
    Ni = cumsum(table(volume_cl)),
    Fi = cumsum(table(volume_cl)/n) ))
distr_freq_volume_cl
##         ni         fi  Ni        Fi
## (8,19]  72 0.30000000  72 0.3000000
## (19,30] 62 0.25833333 134 0.5583333
## (30,41] 48 0.20000000 182 0.7583333
## (41,52] 29 0.12083333 211 0.8791667
## (52,63] 15 0.06250000 226 0.9416667
## (63,74] 10 0.04166667 236 0.9833333
## (74,85]  4 0.01666667 240 1.0000000
barplot(freq_volume,
        main = "Distribuzione di Frequenze di volume",
        xlab = "Classi",
        ylab = "Freq volume",
        col = "orange",
)

Osservazioni:

La maggior parte degli immobili è stata venduta per un valore complessivo compreso tra gli 8 e i 19 milioni di dollari mensili (classe modale).

Indice di GINI

# Creata funzione per calcolare l'indice
gini.index = function(x){
  ni = table(x)
  fi = ni/length(x)
  fi2 = fi^2
  j = length(table(x))
  gini = 1-sum(fi2)
  gini_norm = gini/((j-1)/j)
  return(gini_norm)
}
gini.index(months_inventory)
## [1] 0.9944444
gini.index(volume)
## [1] 0.9999484

Osservazioni:

Si osserva una notevole disuguaglianza nella distribuzione dei dati per le variabili months_inventory e volume. In particolare, le classi da 7 a 9 mesi per la variabile months_inventory e da 8 a 19 milioni di dollari per la variabile volume emergono come le principali caratteristiche del mercato immobiliare.

Indici di forma

#Calcolata la distribuzione per le varibili sales, volume, median_price, listings e months_inventory
distr_sales = rnorm(n,mean(sales),sd(sales))
distr_volume = rnorm(n,mean(volume),sd(volume))
distr_median_price = rnorm(n,mean(median_price),sd(median_price))
distr_listings = rnorm(n,mean(listings),sd(listings))
distr_months_inventory = rnorm(n,mean(months_inventory),sd(months_inventory))

#Normalizzazione delle distribuzioni
norm_sales = (distr_sales-mean(distr_sales))/sd(distr_sales)
norm_volume = (distr_volume-mean(distr_volume))/sd(distr_volume)
norm_median_price = (distr_median_price-mean(distr_median_price))/sd(distr_median_price)
norm_listings = (distr_listings-mean(distr_listings))/sd(distr_listings)
norm_months_inventory = (distr_months_inventory-mean(distr_months_inventory))/sd(distr_months_inventory)
plot(density(norm_sales), col=2, lwd=2, main = "Distribuzione Variabili Normalizzate")
lines(density(norm_volume), col=3, lwd=2)
lines(density(norm_median_price), col=4, lwd=2)
lines(density(norm_listings), col=5, lwd=2)
lines(density(norm_months_inventory), col=6, lwd=2)
abline(v=0, col="grey")
legend("topright", 
       legend=c("Sales", "Volume", "Median Price", "Listings", "Months Inventory"), 
       col=c(2, 3, 4, 5, 6), 
       lwd=4, 
       )

Asimmetria e Curtosi

# create le funzioni per calcolare l'asimmetria e la curtosi
Asim.index = function(x){

  mu = mean(x)
  sigma = sd(x)
  n = length(x)
  m3 = sum((x-mu)^3)/n
  return(m3/sigma^3)
}
Curt.index = function(x){

  mu = mean(x)
  sigma = sd(x)
  n = length(x)
  m4 = sum((x-mu)^4)/n
  return(m4/sigma^4 -3)
}

Normale della variabile: sales

plot(density(norm_sales), col=2, lwd=3, main = "Immobili venduti")
abline(v=0, col= "grey")

Asim.index(sales)
## [1] 0.7136206
Curt.index(sales)
## [1] -0.33552

Normale della variabile: volume

plot(density(norm_volume), col=3, lwd=3, main = "Volume Vendite")
abline(v=0, col= "grey")

Asim.index(volume)
## [1] 0.8792182
Curt.index(volume)
## [1] 0.1505673

Normale della variabile: median_price

plot(density(norm_median_price), col=4, lwd=3, main = "Prezzo mediano")
abline(v=0, col= "grey")

Asim.index(median_price)
## [1] -0.3622768
Curt.index(median_price)
## [1] -0.6427292

Normale della variabile: listings

plot(density(norm_listings), col=5, lwd=3, main = "Annunci Attivi")
abline(v=0, col= "grey")

Asim.index(listings)
## [1] 0.6454431
Curt.index(listings)
## [1] -0.8101534

Normale della variabile: months_inventory

plot(density(norm_months_inventory), col=6, lwd=3, main = " Mesi Inventario")
abline(v=0, col= "grey")

Asim.index(months_inventory)
## [1] 0.04071944
Curt.index(months_inventory)
## [1] -0.1979448

Osservazioni:

  • Curtosi < 0 → distribuzione piatta
  • Asimmetria > 0 → coda a destra (più valori bassi)

Tutte le variabili, esclusa sales, presentano curtosi negativa e quindi una distribuzione più piatta rispetto alla normale. Le variabili sales, volume e listings mostrano una asimmetria positiva: maggior numero di valori al di sotto della media

Calcolo delle Probabilità

Citta di Beaumont

freq_city = table(city)
prob_city = freq_city/n
prob_city
## city
##              Beaumont Bryan-College Station                 Tyler 
##                  0.25                  0.25                  0.25 
##         Wichita Falls 
##                  0.25

La probabilità che venga estratta la Citta di Beaumont é del 25%.

Mese di Luglio

month_7 = nrow(df[df$month == 7,])

P_month_7 = month_7/n
P_month_7
## [1] 0.08333333

La probabilità che venga estratto il mese di luglio (7) è dell’8,34%

Dicembre 2012

# Aggiunta al dataframe la colonna in formato data
df$mese_anno = as.Date(paste(year, month, "01", sep="-"), "%Y-%m-%d")
mese_anno_dic12 = nrow(df[df$mese_anno == "2012-12-01",])

P_mese_anno_dic12 = mese_anno_dic12/n
P_mese_anno_dic12
## [1] 0.01666667

La probabilità che venga estratto Dicembre 2012 è del 1,67%

Analisi condizionata

# Inizializzazione pacchetto dplyr
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

Creazione di nuovi data frame raggruppati

# per città: media e dev. standard delle unità vendute
group_city = df %>%
 group_by(city)%>%
  summarise(mean_sales = mean(sales),
            d.st_sales = sd(sales))
# per città e anno
group_city_year = df %>%
  group_by(city, year)%>%
  summarise(mean_sales = mean(sales),
            d.st_sales = sd(sales))
## `summarise()` has grouped output by 'city'. You can override using the
## `.groups` argument.
# per città e mese
group_city_month = df %>%
  group_by(city, month)%>%
  summarise(mean_sales = mean(sales),
            d.st_sales = sd(sales))
## `summarise()` has grouped output by 'city'. You can override using the
## `.groups` argument.
# Inizializzazione ggplot2
library(ggplot2)

Boxplot per città

ggplot(df, aes(x = city, y = median_price, fill = city)) +
  geom_boxplot() +
  labs(title = "Distribuzione del Prezzo Mediano per Città") +
  theme_minimal() +
  theme(legend.position = "none")

Osservazioni:

  • Beaumont:
    • Mostra outlier alti, ma la maggior parte dei prezzi è concentrata in una fascia ristretta
  • Bryan-College Station:
    • Ha la mediana del prezzo più alta tra le città analizzate
    • Anche in questo caso mostra outlier alti
  • Tyler:
    • Ha una mediana inferiore a Bryan-College Station, ma comunque più alta di Beaumont e Wichita Falls.
  • Wichita Falls:
    • Ha i prezzi mediani più bassi tra le città analizzate.
    • Anche qui ci sono outlier superiori.

I prezzi più economici si trovano a Wichita Falls e quelli più elevati a Bryan-College Station. Gli outlier superiori indicano che si potrebbero comunque trovare degli immobili con prezzi decisamente più alti rispetto alla mediana.

Media mensile di immobili venduti per città

ggplot(group_city, aes(x = city, fill = city)) +
  geom_bar(aes(y = mean_sales), stat = "identity", position = "dodge")+
    geom_text(aes(y = mean_sales, label = round(mean_sales)),
            vjust = +1.5,
            color = "white")+
  labs(title = "Media delle Vendite Mensili per Città",
       x = "Città",
       y = "Media Immobili Venduti")+
  theme_minimal()+
  theme(legend.position = "none")

Osservazioni:

La città con il maggior numero medio mensile di immobili venduti è Tyler. Il numero minore per Wichita Falls.

Trend della media mensile degli immobili venduti negli anni

ggplot(group_city_year, aes(x = year, y = mean_sales, color = city))+
  geom_line()+
  geom_point()+
  labs(title = "Trend annuale vendite medie mensili per città",
       x = "Anno",
       y = "Media Immobili venduti")+
  theme_minimal()+
  theme(legend.position = "top")+
  guides(color = guide_legend(title = NULL))

ggplot(df, aes(x = mese_anno, y = sales, colour = city))+
  geom_line(lwd = 1)+
  facet_wrap(~ city)+
  geom_smooth(method = "glm", se = F, linetype = "dashed")+
  labs(title = "Trend Storico delle Vendite per Città",
       x = "Data",
       y = "Vendite") +
  theme_minimal() +
  theme(legend.position = "none")
## `geom_smooth()` using formula = 'y ~ x'

Osservazioni:

I trend storici mostrano una crescita positiva negli anni tranne per la città di Wichita Falls che si mantiene stabile, con un leggero calo nel 2014 rispetto al 2013.

Stagionalità

ggplot(group_city_month, aes(x = factor(month), y = mean_sales, fill = city))+
  geom_bar(stat = "identity", position = "stack")+
  labs(title = "Trend Mensili per Città",
       x= "Mese",
       y="Vendite")+
  theme_minimal()+
  theme(legend.position = "top")

ggplot(group_city_month, aes(x = factor(month), y = mean_sales, fill = city))+
  geom_bar(stat = "identity", position = "fill")+
  labs(title = "Trend Mensili per Città",
       x= "Mese",
       y="Vendite")+
  theme_minimal()+
  theme(legend.position = "top")

Osservazioni:

Tutte le città mostrano una forte stagionalità con un aumento delle vendite verso il periodo primaverile-estivo. Stagionalità più marcata per le citta di Tyler e Bryan-College Station. Massimo per il mese di Giugno e minimo per il mese di Gennaio.

Stagionalità per anno

ggplot(df, aes(x = factor(month), y = sales, fill = city))+
  geom_bar(stat = "identity", position = "stack")+
  labs(title = "Trend Mensili per Città_Per anno",
       x= "Mese",
       y="Vendite")+
  theme_minimal()+
  theme(legend.position = "top")+
  facet_wrap(~ year)

Osservazioni:

Si osserva la stagionalità del 2010 spostata verso il mese di Aprile - Maggio e quella del 2012 verso il mese di Agosto.

Trend storico per altre variabili

ggplot(df, aes(x = mese_anno, y = listings, color = city))+
  geom_line(lwd = 1)+
  theme_minimal()+
  theme(legend.position = "top")+
  labs(title = "Annunci",
       x = "Mese - Anno",
       y="")

ggplot(df, aes(x = mese_anno, y = months_inventory, color = city))+
  geom_line(lwd = 1)+
  theme_minimal()+
  theme(legend.position = "top")+
  labs(title = "Mesi di Inventario",
       x = "Mese - Anno",
       y="")

ggplot(df, aes(x = mese_anno, y = median_price, color = city))+
  geom_line(lwd = 0.5)+
  theme_minimal()+
  theme(legend.position = "top")+
  labs(title = "Prezzo Mediano",
       x = "Mese - Anno",
       y="")+
  geom_smooth(method = "glm", se = F, linetype = "dashed")
## `geom_smooth()` using formula = 'y ~ x'

Osservazioni:

Per la città di Bryan-College Station si osserva particolarmente una diminuzione degli annunci e dei mesi di inventario registrando comunque una crescita sul prezzo mediano di vendita.

Da questa osservazione aggiungiamo delle colonne calcolate al data frame finalizzate alla creazione di un indice che misura l’efficacia degli annunci.

\[ \text{Indice di Efficienza} = \left( \frac{\text{Vendite}}{\text{Annunci}} \right) \times \left( \frac{\text{Prezzo Medio}}{\text{Mesi di Inventario}} \right) \]

Indice di efficienza

Prezzo medio per immobile

df$mean_price = round((c(volume)*1000000)/c(sales))

Aggiunto al data frame una colonna calcolata che contiene il prezzo medio per immobile.

df$efficency = round((c(df$sales)/c(listings))*(c(df$mean_price)/c(months_inventory))/100,2)
ggplot(df, aes(x = mese_anno, y = efficency, color = city))+
  geom_line(lwd = 1)+
  theme_minimal()+
  theme(legend.position = "top")+
  labs(title = "Efficenza Annunci",
       x = "Mese - Anno",
       y = "")

Osservazioni:

Evidente il miglioramento dell’efficenza per la citta di Bryan-College Station. Potrebe essere una buona soluzione estendere le caratteristiche degli annunci a tutte le altre città per migliora il business totale.

Conclusioni

Ecco un riepilogo dei principali insight emersi:

Considerazioni finali

Dall’analisi emerge come Bryan-College Station rappresenti il benchmark per performance di mercato, sia in termini di prezzo che di efficienza operativa. Le strategie applicate in quella città potrebbero essere replicate in altri contesti per ottimizzare il business generale.