In questa analisi abbiamo esplorato un dataset relativo al mercato immobiliare in Texas, esaminando le caratteristiche delle vendite,il volume delle transazioni e i prezzi mediani delle proprietà. L’analisi è stata effettuata attraverso statistiche descrittive, misure di dispersione e distribuzione e visualizzazioni grafiche con ggplot2. Abbiamo utilizzato la libreria tidyverse per la manipolazione dei dati e moments per calcolare l’asimmetria (skewness) e la curtosi (kurtosis). Il dataset in oggetto contiene le seguenti variabili:
Dopo il caricamento, abbiamo eseguito un’esplorazione iniziale con glimpse() e summary(), ottenendo una visione generale delle variabili presenti.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
library(dplyr)
library(moments) # Per skewness e kurtosis
library(ineq) # Per indice di Gini
library(conflicted)
conflict_prefer("filter", "dplyr")
## [conflicted] Will prefer dplyr::filter over any other package.
conflict_prefer("lag", "dplyr")
## [conflicted] Will prefer dplyr::lag over any other package.
# Caricamento dataset
dataset <- read.csv("realestate_texas.csv", header = TRUE, stringsAsFactors = FALSE)
sum(is.na(dataset)) # Per vedere il numero di valori mancanti nel dataset
## [1] 0
# Esplorazione iniziale del dataset
glimpse(dataset)
## Rows: 240
## Columns: 8
## $ city <chr> "Beaumont", "Beaumont", "Beaumont", "Beaumont", "Beau…
## $ year <int> 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010,…
## $ month <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5,…
## $ sales <int> 83, 108, 182, 200, 202, 189, 164, 174, 124, 150, 150,…
## $ volume <dbl> 14.162, 17.690, 28.701, 26.819, 28.833, 27.219, 22.70…
## $ median_price <dbl> 163800, 138200, 122400, 123200, 123100, 122800, 12430…
## $ listings <int> 1533, 1586, 1689, 1708, 1771, 1803, 1857, 1830, 1829,…
## $ months_inventory <dbl> 9.5, 10.0, 10.6, 10.6, 10.9, 11.1, 11.7, 11.6, 11.7, …
summary(dataset)
## city year month sales
## Length:240 Min. :2010 Min. : 1.00 Min. : 79.0
## Class :character 1st Qu.:2011 1st Qu.: 3.75 1st Qu.:127.0
## Mode :character Median :2012 Median : 6.50 Median :175.5
## Mean :2012 Mean : 6.50 Mean :192.3
## 3rd Qu.:2013 3rd Qu.: 9.25 3rd Qu.:247.0
## Max. :2014 Max. :12.00 Max. :423.0
## volume median_price listings months_inventory
## Min. : 8.166 Min. : 73800 Min. : 743 Min. : 3.400
## 1st Qu.:17.660 1st Qu.:117300 1st Qu.:1026 1st Qu.: 7.800
## Median :27.062 Median :134500 Median :1618 Median : 8.950
## Mean :31.005 Mean :132665 Mean :1738 Mean : 9.193
## 3rd Qu.:40.893 3rd Qu.:150050 3rd Qu.:2056 3rd Qu.:10.950
## Max. :83.547 Max. :180000 Max. :3296 Max. :14.900
Abbiamo identificato le variabili numeriche e categoriche nel dataset, determinando il loro tipo con sapply(dataset, class). Questo passaggio è cruciale per comprendere quali operazioni statistiche possiamo applicare.
# Identificazione delle variabili numeriche e categoriali
sapply(dataset, class)
## city year month sales
## "character" "integer" "integer" "integer"
## volume median_price listings months_inventory
## "numeric" "numeric" "integer" "numeric"
Abbiamo calcolato le seguenti statistiche per le variabili “sales”, “volume”, “median_price”, “listings” e “months_inventory”:
Questi valori ci permettono di capire la distribuzione dei dati e la presenza di eventuali skewness o outlier.
# Seleziono solo le colonne numeriche
numeric_cols <- c("sales", "volume", "median_price", "listings", "months_inventory")
stats <- data.frame (
Media = sapply(dataset[numeric_cols], mean, na.rm = TRUE),
Mediana = sapply(dataset[numeric_cols], median, na.rm = TRUE),
Moda = sapply(dataset[numeric_cols], function(x) as.numeric(names(sort(table(x), decreasing=TRUE)[1]))),
Range = sapply(dataset[numeric_cols], function(x) max(x, na.rm = TRUE) - min(x, na.rm = TRUE)),
Varianza = sapply(dataset[numeric_cols], var, na.rm = TRUE),
Dev_Standard = sapply(dataset[numeric_cols], sd, na.rm = TRUE),
Coeff_Variazione = sapply(dataset[numeric_cols], function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE)),
Asimmetria = sapply(dataset[numeric_cols], skewness, na.rm = TRUE),
Curtosi = sapply(dataset[numeric_cols], kurtosis, na.rm = TRUE)
)
stats
## Media Mediana Moda Range Varianza
## sales 192.29167 175.5000 124.000 344.000 6.344300e+03
## volume 31.00519 27.0625 14.003 75.381 2.772707e+02
## median_price 132665.41667 134500.0000 130000.000 106200.000 5.135730e+08
## listings 1738.02083 1618.5000 1581.000 2553.000 5.665690e+05
## months_inventory 9.19250 8.9500 8.100 11.500 5.306889e+00
## Dev_Standard Coeff_Variazione Asimmetria Curtosi
## sales 79.651111 0.4142203 0.71810402 2.686824
## volume 16.651447 0.5370536 0.88474203 3.176987
## median_price 22662.148687 0.1708218 -0.36455288 2.377038
## listings 752.707756 0.4330833 0.64949823 2.208210
## months_inventory 2.303669 0.2506031 0.04097527 2.825552
Risultati:
Le vendite (sales) mostrano una distribuzione asimmetrica, con un valore medio superiore alla mediana, indicando la presenza di pochi valori molto elevati.
Il volume delle transazioni (volume) segue una distribuzione simile, evidenziando una forte variabilità.
Il prezzo mediano (median_price) ha una minore dispersione rispetto agli altri parametri.
Successivamente, abbiamo calcolato: il Coefficiente di variazione (CV) per determinare quale variabile ha la maggiore variabilità relativa e Skewness per identificare la variabile con la maggiore asimmetria
cv_values <- sapply(dataset[, c("sales", "volume", "median_price")],
function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE))
var_max_cv <- names(cv_values)[which.max(cv_values)]
skewness_values <- sapply(dataset[, c("sales", "volume", "median_price")],
skewness, na.rm = TRUE)
var_max_skew <- names(skewness_values)[which.max(abs(skewness_values))]
# Risultati della variabilità e asimmetria
cat("La variabile con la più alta variabilità è:", var_max_cv, "\n")
## La variabile con la più alta variabilità è: volume
cat("La variabile con la distribuzione più asimmetrica è:", var_max_skew, "\n")
## La variabile con la distribuzione più asimmetrica è: volume
L’alta variabilità del volume delle vendite indica che il valore totale delle transazioni varia notevolmente tra le città e i mesi. L’alta asimmetria suggerisce che ci sono alcuni periodi in cui il volume delle vendite è eccezionalmente alto rispetto alla norma. Questi risultati indicano che il mercato immobiliare è soggetto a grandi fluttuazioni, probabilmente legate a stagionalità o fattori economici.
A questo punto, abbiamo selezionato la variabile quantitativa “sales” e l’abbiamo suddivisa in classi, creato una distribuzione di frequenze e rappresentato i dati con un grafico a barre.
#Visualizzazione dell'analisi della distribuzione delle vendite
ggplot(dataset, aes(x = sales)) +
geom_histogram(binwidth = 10, fill = "skyblue", color = "black", alpha = 0.7) +
facet_wrap(~ city) +
labs(title = "Distribuzione delle Vendite per Città")
#Creazione di classi per la variabile "sales" e distribuzione di frequenza
breaks <- seq(min(dataset$sales, na.rm = TRUE), max(dataset$sales, na.rm = TRUE), length.out = 6)
dataset$sales_class <- cut(dataset$sales, breaks = breaks, include.lowest = TRUE)
freq_table <- table(dataset$sales_class)
print(freq_table)
##
## [79,148] (148,217] (217,285] (285,354] (354,423]
## 84 77 41 27 11
# Istogramma
col_palette <- terrain.colors(length(freq_table))
barplot(freq_table,
main = "Distribuzione delle Vendite (Sales)",
col = col_palette,
xlab = "Classi di Sales",
ylab = "Frequenza",
border = "black")
Abbiamo calcolato l’indice di Gini per la variabile sales e il risultato vicino a 0 indica che le vendite sono distribuite in modo abbastanza equo tra le città. Tuttavia, c’è ancora un certo livello di concentrazione.
#Calcolo dell'indice di Gini per le vendite
gini_sales <- Gini(dataset$sales, na.rm = TRUE)
cat("Indice di Gini per le vendite:", gini_sales, "\n")
## Indice di Gini per le vendite: 0.2310975
Abbiamo calcolato le probabilità condizionate:
-Probabilità che una transazione avvenga a Beaumont. -Probabilità che una vendita avvenga nel mese di luglio. -Probabilità che una vendita avvenga nel dicembre 2012.
prob_beaumont <- sum(dataset$city == "Beaumont", na.rm=TRUE) / nrow(dataset)
prob_july <- sum(dataset$month == 7, na.rm=TRUE) / nrow(dataset)
prob_december_2012 <- sum(dataset$month == 12 & dataset$year == 2012, na.rm=TRUE) / nrow(dataset)
cat("Probabilità di Beaumont:", prob_beaumont, "\n")
## Probabilità di Beaumont: 0.25
cat("Probabilità di Luglio:", prob_july, "\n")
## Probabilità di Luglio: 0.08333333
cat("Probabilità di Dicembre 2012:", prob_december_2012, "\n")
## Probabilità di Dicembre 2012: 0.01666667
Abbiamo creato due nuove variabili:
avg_price: il prezzo medio per transazione (volume/sales).
marketing_efficiency: l’efficienza di mercato, data dal rapporto tra vendite e inserzioni (sales/listings).
dataset$avg_price <- dataset$volume / dataset$sales
dataset$marketing_efficiency <- ifelse(dataset$listings > 0, dataset$sales / dataset$listings, NA)
# Visualizzazione delle nuove variabili
head(dataset[c("volume", "sales", "avg_price", "marketing_efficiency")])
## volume sales avg_price marketing_efficiency
## 1 14.162 83 0.1706265 0.05414220
## 2 17.690 108 0.1637963 0.06809584
## 3 28.701 182 0.1576978 0.10775607
## 4 26.819 200 0.1340950 0.11709602
## 5 28.833 202 0.1427376 0.11405985
## 6 27.219 189 0.1440159 0.10482529
Risultati:
L’analisi dell’efficienza di mercato aiuta a capire quanto il mercato sia reattivo rispetto alle nuove offerte. Nel caso specifico, l’efficacia degli annunci (vendite/annunci) è molto bassa (<10%), il che significa che ci sono troppi immobili disponibili rispetto alla domanda
Abbiamo calcolato la media e la deviazione standard delle vendite per ciascuna città.
# Analisi condizionata per città
summary_by_city <- dataset %>%
group_by(city) %>%
summarise(avg_sales = mean(sales, na.rm=TRUE),
sd_sales = sd(sales, na.rm=TRUE))
print(summary_by_city)
## # A tibble: 4 × 3
## city avg_sales sd_sales
## <chr> <dbl> <dbl>
## 1 Beaumont 177. 41.5
## 2 Bryan-College Station 206. 85.0
## 3 Tyler 270. 62.0
## 4 Wichita Falls 116. 22.2
# Calcolo della media e della deviazione standard per prezzo medio e vendite per città, anno e mese
summary_stats <- dataset %>%
group_by(city, year, month) %>%
summarise(
mean_price = mean(avg_price, na.rm = TRUE),
sd_price = sd(avg_price, na.rm = TRUE),
mean_sales = mean(sales, na.rm = TRUE),
sd_sales = sd(sales, na.rm = TRUE),
.groups = "drop"
)
head(summary_stats)
## # A tibble: 6 × 7
## city year month mean_price sd_price mean_sales sd_sales
## <chr> <int> <int> <dbl> <dbl> <dbl> <dbl>
## 1 Beaumont 2010 1 0.171 NA 83 NA
## 2 Beaumont 2010 2 0.164 NA 108 NA
## 3 Beaumont 2010 3 0.158 NA 182 NA
## 4 Beaumont 2010 4 0.134 NA 200 NA
## 5 Beaumont 2010 5 0.143 NA 202 NA
## 6 Beaumont 2010 6 0.144 NA 189 NA
Risultati:
Alcune città mostrano un volume di vendite più elevato e una maggiore variabilità rispetto ad altre.
Infine, abbiamo utilizzato diversi tipi di grafici per esplorare le distribuzioni e le relazioni tra le variabili:
# Visualizzazione delle medie per prezzo medio per città
ggplot(summary_stats, aes(x = city, y = mean_price, fill = city)) +
geom_bar(stat = "identity", show.legend = FALSE) +
labs(title = "Media del Prezzo Medio per Città", x = "Città", y = "Prezzo Medio") +
theme_minimal()
# Line chart del prezzo medio nel tempo
ggplot(summary_stats, aes(x = as.Date(paste(year, month, "1", sep = "-")),
y = mean_price, group = city, color = city)) +
geom_line() +
labs(title = "Andamento del Prezzo Medio nel Tempo", x = "Data", y = "Prezzo Medio") +
theme_minimal()
Evidenzia le differenze nei prezzi mediani.
# Boxplot per il prezzo mediano tra città
ggplot(dataset, aes(x = city, y = median_price)) +
geom_boxplot() +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
labs(title = "Distribuzione del Prezzo Mediano per Città")
Risultati:
Bryan-College Station ha i prezzi mediani più alti rispetto alle altre città, con una mediana intorno ai 150.000 dolllari, mentre alcune osservazioni superano i 175.000 dollari. Le città di Beaumont e Tyler presentano prezzi mediani simili, intorno ai 125.000-135.000 dollari, con una dispersione moderata. Wichita Falls ha i prezzi mediani più bassi, con una mediana inferiore ai 100.000 dollari e una distribuzione che mostra una maggiore variabilità con alcuni outlier al ribasso.
Mostra l’andamento delle transazioni immobiliari.
# Boxplot per il valore totale delle vendite per città e anno
ggplot(dataset, aes(x = city, y = volume, fill = factor(year))) +
geom_boxplot() +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
labs(title = "Distribuzione del Valore Totale delle Vendite per Città e Anno")
Risultati:
Bryan-College Station e Tyler hanno il volume di vendite più alto, con una tendenza alla crescita negli anni 2013 e 2014. Ciò suggerisce un mercato più attivo e dinamico. Beaumont mostra un volume inferiore ma comunque in crescita nel tempo, anche se con maggiore variabilità nelle transazioni tra gli anni. Wichita Falls ha il volume di vendita più basso rispetto alle altre città e una distribuzione più compatta, suggerendo un mercato più stabile ma meno attivo.
Permette di confrontare l’andamento delle vendite tra città.
# Grafico a barre sovrapposte per vendite mensili per città
ggplot(dataset, aes(x = factor(month), y = sales, fill = city)) +
geom_col(position = "stack") +
ggtitle("Vendite Mensili per Città - Grafico Sovrapposto")
Risultati:
Si nota una stagionalità nelle vendite, con un picco massimo intorno ai mesi maggio, giugno e luglio, suggerendo che il mercato immobiliare è più attivo durante la tarda primavera e l’inizio dell’estate. Le città di Tyler (azzurro) e Beaumont (rosso) sembrano contribuire maggiormente al volume totale delle vendite rispetto a Bryan-College Station (verde) e Wichita Falls (viola).
# Grafico a barre normalizzato per vendite mensili per città
ggplot(dataset, aes(x = factor(month), y = sales, fill = city)) +
geom_bar(stat = "identity", position = "fill") +
labs(title = "Distribuzione Normalizzata delle Vendite Mensili per Città", x = "Mese", y = "Proporzione delle Vendite")
Risultati:
La proporzione delle vendite tra le città rimane relativamente costante nel tempo, indicando che la stagionalità influisce in modo simile su tutte le città. Tyler e Beaumont dominano la maggior parte delle vendite ogni mese, mentre Wichita Falls rappresenta sempre una quota minore delle transazioni.
# Grafico a barre delle vendite mensili per città
ggplot(dataset, aes(x = factor(month), y = sales, fill = city)) +
geom_bar(stat = "identity", position = "dodge") +
ggtitle("Vendite Mensili per Città")
Mostra la stagionalità e le variazioni nel tempo.
#Andamento delle vendite negli anni
ggplot(dataset, aes(x = factor(month), y = sales, fill = city)) +
geom_bar(stat = "identity", position = "dodge") +
facet_wrap(~year) +
ggtitle("Vendite Mensili per Città con Anno") +
labs(x = "Mese", y = "Numero di Vendite") +
theme_minimal()
Permette di osservare l’andamento del mercato immobiliare nel tempo.
# Line chart per il confronto storico delle vendite
ggplot(dataset, aes(x = as.Date(paste(year, month, "1", sep = "-")), y = sales, color = city)) +
geom_line(linewidth = 1) +
geom_point() +
labs(title = "Andamento delle Vendite nel Tempo",
x = "Data",
y = "Numero di Vendite") +
theme_minimal()
Dalle analisi svolte, possiamo affermare che, in generale, il mercato immobiliare in Texas è in crescita, con un aumento generale delle vendite tra il 2010 e il 2014. Abbiamo dimostrato che alcune città (Tyler, Bryan-College Station) mostrano maggiore dinamicità, mentre altre (Wichita Falls) rimangono più stabili. Il volume totale delle vendite, ha mostrato una forte asimmetria, suggerendo che in alcuni periodi o città si verificano picchi di transazioni molto elevate rispetto alla media. La stagionalità, infatti, gioca un ruolo importante, con vendite più alte nei mesi primaverili ed estivi e più basse in inverno.
L’analisi storica delle vendite ha permesso di individuare alcune tendenze chiave:
in alcuni anni si è registrato un calo delle vendite, spesso riconducibile a fattori economici, come crisi finanziarie o variazioni nei tassi di interesse sui mutui.
una ciclicità del mercato: in diverse città emergono pattern ripetitivi nel tempo, segnalando un comportamento ciclico del settore immobiliare.
dinamiche territoriali: mentre alcune città mostrano una crescita costante delle vendite, altre evidenziano oscillazioni più marcate.
L’indice di Gini indica che alcune città dominano il mercato, mentre altre hanno un minor numero di vendite. Per quel che riguarda l’efficacia degli annunci, essenziale per prevedere ed indirizzare le vendite, seppur evidenziando dei miglioramenti rispetto al passato, è ancora relativamente bassa, suggerendo un mercato con troppa offerta rispetto alla domanda.