1. Analisi delle variabili

# Caricamento dataset
data <- read.csv("realestate_texas.csv")

# Creazione nuova colonna per facilitare analisi temporali e le 2 nuove variabili richieste
data$date <- as.Date(paste(data$year, data$month, "01", sep = "-"))

variables <- data.frame(
  name = c("city",
           "year",
           "month",
           "sales",
           "volume",
           "median_price",
           "listings",
           "months_inventory",
           "average_price_per_sale",
           "listings_effectiveness"),
  type = c("Qualitativa Nominale", 
           "Quantitativa Discreta",
           "Quantitativa Discreta",
           "Quantitativa Discreta",
           "Quantitativa Continua",
           "Quantitativa Continua",
           "Quantitativa Discreta",
           "Quantitativa Continua",
           "Quantitativa Continua",
           "Quantitativa Continua"),
  description = c("Città del Texas in cui sono stati raccolti i dati",
                  "Anno in cui sono stati raccolti i dati (2010-2014)",
                  "Mese (espresso numericamente 1-12) in cui sono stati raccolti i dati",
                  "Numero totale di vendite immobiliari concluse nel mese",
                  "Valore complessivo delle vendite immobiliari concluse (in milioni di dollari)",
                  "Prezzo mediano degli immobili venduti (in dollari)", 
                  "Numero totale di annunci immobiliari attivi nel mese", 
                  "Numero medio di mesi necessari per vendere tutti gli immobili disponibili sul mercato",
                  "Prezzo medio per singola transazione",
                  "Efficacia annunci (rapporto tra vendite ed annunci)")
)

kable(variables, caption = "Analisi Variabili")
Analisi Variabili
name type description
city Qualitativa Nominale Città del Texas in cui sono stati raccolti i dati
year Quantitativa Discreta Anno in cui sono stati raccolti i dati (2010-2014)
month Quantitativa Discreta Mese (espresso numericamente 1-12) in cui sono stati raccolti i dati
sales Quantitativa Discreta Numero totale di vendite immobiliari concluse nel mese
volume Quantitativa Continua Valore complessivo delle vendite immobiliari concluse (in milioni di dollari)
median_price Quantitativa Continua Prezzo mediano degli immobili venduti (in dollari)
listings Quantitativa Discreta Numero totale di annunci immobiliari attivi nel mese
months_inventory Quantitativa Continua Numero medio di mesi necessari per vendere tutti gli immobili disponibili sul mercato
average_price_per_sale Quantitativa Continua Prezzo medio per singola transazione
listings_effectiveness Quantitativa Continua Efficacia annunci (rapporto tra vendite ed annunci)

2. Indici di posizione, variabilità e forma

Distribuzioni di frequenza per city, month e year

table_freq <- function(x) {
  freq_abs <- table(x)
  
  table_res <- data.frame(
    Categoria = names(freq_abs), # Categoria nome temporaneo
    Frequenza_Assoluta = as.integer(freq_abs),
    Frequenza_Relativa_In_Percentuale = as.numeric(prop.table(freq_abs)) * 100
  )
  
  return(table_res)
}

# colonne da analizzare
columns <- c("city", "month", "year")

for (column in columns) {
  caption_table <- paste("Distribuzione di Frequenza per", column)
  
  table_frame <- table_freq(data[[column]])
  
  names(table_frame)[1] <- column # nome relativa colonna (city, month, year)
  
  # stampa tabelle
  print(
    kable(
      table_frame,
      caption = caption_table,
      digits = 2
    )
  )
  
  cat("\n\n") # per separare tabelle
}
Distribuzione di Frequenza per city
city Frequenza_Assoluta Frequenza_Relativa_In_Percentuale
Beaumont 60 25
Bryan-College Station 60 25
Tyler 60 25
Wichita Falls 60 25
Distribuzione di Frequenza per month
month Frequenza_Assoluta Frequenza_Relativa_In_Percentuale
1 20 8.33
2 20 8.33
3 20 8.33
4 20 8.33
5 20 8.33
6 20 8.33
7 20 8.33
8 20 8.33
9 20 8.33
10 20 8.33
11 20 8.33
12 20 8.33
Distribuzione di Frequenza per year
year Frequenza_Assoluta Frequenza_Relativa_In_Percentuale
2010 48 20
2011 48 20
2012 48 20
2013 48 20
2014 48 20

Commenti

  • Ogni città, mese ed anno presentano lo stesso numero di osservazioni

Calcolo indici per restanti variabili

vars_index_selected <- data %>% select(sales, volume, median_price, listings, months_inventory)

summary_vars_index <- data.frame(
  Mean                    = sapply(vars_index_selected, mean),
  Median                  = sapply(vars_index_selected, median), 
  Dev.Std                 = sapply(vars_index_selected, sd),
  Var                     = sapply(vars_index_selected, var),
  Min                     = sapply(vars_index_selected, min),
  Max                     = sapply(vars_index_selected, max),
  Q1_25_percentile        = sapply(vars_index_selected, quantile, probs = 0.25),
  Q3_75_percentile        = sapply(vars_index_selected, quantile, probs = 0.75),
  Range_Interquartile_IQR = sapply(vars_index_selected, IQR),
  Skewness                = sapply(vars_index_selected, skewness),
  Kurtosis                = sapply(vars_index_selected, kurtosis)
)

kable(round(summary_vars_index, 2), caption = "Indici di posizione, variabilità e forma")
Indici di posizione, variabilità e forma
Mean Median Dev.Std Var Min Max Q1_25_percentile Q3_75_percentile Range_Interquartile_IQR Skewness Kurtosis
sales 192.29 175.50 79.65 6.34430e+03 79.00 423.00 127.00 247.00 120.00 0.72 2.69
volume 31.01 27.06 16.65 2.77270e+02 8.17 83.55 17.66 40.89 23.23 0.88 3.18
median_price 132665.42 134500.00 22662.15 5.13573e+08 73800.00 180000.00 117300.00 150050.00 32750.00 -0.36 2.38
listings 1738.02 1618.50 752.71 5.66569e+05 743.00 3296.00 1026.50 2056.00 1029.50 0.65 2.21
months_inventory 9.19 8.95 2.30 5.31000e+00 3.40 14.90 7.80 10.95 3.15 0.04 2.83

Commenti:

  • sales:
    • La media è più alta della mediana e l’asimmetria (skewness) è positiva > 0 (coda a destra) e questo indica che nella maggior parte dei mesi si hanno circa 175 vendite di media (quindi inferiore a 192 di Mean), ma ci sono alcuni mesi con un numero di vendite eccezionalmente alto.
    • La deviazione standard è molto alta e quindi indica grande variabilità (possibile incertezza).
    • Il range tra minimo e massimo è grande, il mese migliore ha registrato circa 5 volte le vendite del mese peggiore.
    • Kurtosi vicino a 3 indica una curtosi normale (mesocurtica), quindi la probabilità di valori estremi (le code) non è né esageratamente alta né bassa.
  • volume:
    • La media è più alta della mediana e l’assimetria è positiva ed anche più elevata rispetto a sales quindi nei mesi di picco, non solo si vende di più, ma si vendono anche case di valore mediamente più alto.
    • Kurtosis a 3.18 leggermente leptocurtica (maggiore di 3). A differenza delle sales, qui c’è una probabilità leggermente più alta di osservare valori estremi.
  • median_price:
    • La media è inferiore alla mediana e l’assimetria è negativa < 0 (-0.36) e questo indica che ci sono dei casi con prezzi mediani insolitamente bassi che abbassano la media, suggerisce che una o più città fanno scendere la media.
    • La variabilità è meno elevata e quindi si ha una maggiore stabiltà dei prezzi.
    • Kurtosis a 2.38 platicurtica (minore di 3), quindi più piatta di una normale e con code più sottili che indica che shock di prezzo estremi sono poco probabili.
  • listings:
    • Offerta tende a seguire la domanda, ecco perché è simile a sales.
  • months_inventory:
    • Media e mediana quasi identiche e la distribuzione è praticamente simmetrica (skewness = 0.04), quindi è l’indicatore più stabile e suggerisce che in media c’è più offerta che domanda.

3. Identificazione delle variabili con maggiore variabilità e asimmetria

summary_vars_index$CV <- (summary_vars_index$Dev.Std / summary_vars_index$Mean) * 100

kable(round(summary_vars_index, 2) %>% select(CV, Skewness) %>% arrange(desc(CV)))
CV Skewness
volume 53.71 0.88
listings 43.31 0.65
sales 41.42 0.72
months_inventory 25.06 0.04
median_price 17.08 -0.36

Commenti:

  1. volume è la variabile con il coefficiente di variazione (CV) più alto indicando quindi una forte variabilità nel volume totale di vendite.
  2. volume è la variabile con la distribuzione più asimmetrica (Skewness) (verso destra) e quindi indica una forte probabilità di outliers.

4. Creazione di classi per una variabile quantitativa

data$sales_class <- cut(data$sales, breaks = pretty(data$sales, n = 8), right = FALSE)
freq_sales_class <- data %>%
  count(sales_class, name = "Frequenza") %>%
  mutate(Percentuale = round(Frequenza / sum(Frequenza) * 100, 2))

kable(freq_sales_class, caption = "Distribuzione delle vendite mensili per classi")
Distribuzione delle vendite mensili per classi
sales_class Frequenza Percentuale
[50,100) 20 8.33
[100,150) 69 28.75
[150,200) 58 24.17
[200,250) 33 13.75
[250,300) 34 14.17
[300,350) 14 5.83
[350,400) 9 3.75
[400,450) 3 1.25

Commenti:

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)
}

kable(data.frame(round(gini.index(data$sales_class), 2)), col.names = "Indice di Gini per le Classi di Vendite")
Indice di Gini per le Classi di Vendite
0.92

Commenti:

5. Calcolo della probabilità

total_rows <- nrow(data)

prob_beaumont          <- (sum(data$city  == "Beaumont") / total_rows) * 100
prob_july              <- (sum(data$month == 7) / total_rows) * 100
prob_december_2012     <- (nrow(filter(data, month == 12 & year == "2012")) / total_rows) * 100

prob_df <- data.frame(
  "Evento" = c("Una riga riporta la città Beaumont",
                           "Una riga riporta il mese di luglio",
                           "Una riga riporta il mese di Dicembre 2012"),
  "Probabilità" = c(prob_beaumont,
                    prob_july,
                    prob_december_2012)
)

kable(prob_df, digits = 2, caption = "Riepilogo Probabilità")
Riepilogo Probabilità
Evento Probabilità
Una riga riporta la città Beaumont 25.00
Una riga riporta il mese di luglio 8.33
Una riga riporta il mese di Dicembre 2012 1.67

6. Creazione di nuove variabili (prezzo medio immobili ed efficacia annunci attivi)

data <- data %>%
  mutate(
    average_price_per_sale = (volume * 1e6) / sales,
    listings_effectiveness    = sales / listings
  )

ggplot(data, aes(x = average_price_per_sale)) +
  geom_histogram(binwidth = 10000, fill = "cyan", color = "black") +
  scale_x_continuous(labels = dollar_format()) +
  labs(title = "Prezzo medio per vendita", x = "Prezzo medio", y = "Frequenza") +
  theme_minimal()

Commenti:

ggplot(data, aes(x = listings_effectiveness)) +
  geom_histogram(binwidth = 0.05, fill = "lightgreen", color = "black") +
  scale_x_continuous(
    labels = percent_format(accuracy = 1),
    breaks = seq(0, 1, by = 0.05)
  ) +
  labs(
    title = "Efficacia annunci (vendite/listings)",
    x = "Efficacia",
    y = "Frequenza"
  ) +
  theme_minimal()

Commenti:

# Questo chunk esegue l'analisi condizionata ma non mostra nulla.
# I dataframe creati qui saranno usati nel blocco di visualizzazione successivo.
summary_city <- data %>%
  group_by(city) %>%
  summarise(
    mean_sales_city       = mean(sales),
    dev_std_sales_city    = sd(sales)
  )

summary_month <- data %>%
  group_by(month) %>%
  summarise(
    mean_sales_month       = mean(sales),
    dev_std_sales_month    = sd(sales)
  )

summary_year <- data %>%
  group_by(year) %>%
  summarise(
    mean_sales_year       = mean(sales),
    dev_std_sales_year    = sd(sales)
  )

total_volume_month <- data %>%
  group_by(month) %>%
  summarise(total_volume = sum(volume))

total_volume_year <- data %>%
  group_by(year) %>%
  summarise(total_volume = sum(volume))

total_volume_month_city <- data %>%
  group_by(month, city) %>%
  summarise(total_volume = sum(volume), .groups = 'drop')

monthly_sales_city <- data %>%
  group_by(year, month, city) %>%
  summarise(total_sales = sum(volume), .groups = 'drop')

7. Creazione di visualizzazioni con ggplot2

# grafico a barre sovrapposte vendite medie per mese e città
ggplot(data, aes(x = factor(month), y = sales, fill = city)) +
  geom_col(position = "stack") +
  labs(title = "Totale vendite per mese e città", x = "Mese", y = "Totale vendite") +
  theme_minimal()

Commenti:

# boxplot prezzo mediano per città ed anno
ggplot(data, aes(x = factor(year), y = median_price, fill = city)) +
  geom_boxplot(position = position_dodge(width = 0.8)) +
  labs(
    title = "Distribuzione del prezzo mediano per anno e città",
    x = "Anno", y = "Prezzo mediano", fill = "Città"
  ) +
  theme_minimal()

Commenti:

# line charts valore totale vendite per città ed anno 
ggplot(data, aes(x = city, y = sales, fill = factor(year))) +
  geom_boxplot(position = position_dodge(width = 0.8)) +
  labs(
    title = "Distribuzione del valore totale delle vendite per città e anno",
    x = "Città", y = "Totale vendite", fill = "Anno"
  ) +
  theme_minimal()

Commenti:

# plot normalizzato
ggplot(monthly_sales_city, aes(x = month, y = total_sales, fill = city)) +
  geom_col(position = "fill") + 
  facet_wrap(~ year) +
  scale_x_continuous(breaks = seq(1, 12, by = 1)) +
  scale_y_continuous(labels = percent_format()) +
  labs(
    title = "Valore totale delle vendite (Normalizzato) per Città",
    x = "Mese",
    y = "Quota Percentuale sul Totale Vendite",
    fill = "Città"
  ) +
  theme_minimal()

Commenti:

Commenti:

  1. Tyler è la città con il numero di vendite maggiore e quindi è il mercato più grande.
  2. Wichita Falls è la città con il minor numero di vendite (meno della metà di Tyler).
  3. Tyler pur essendo prima per numero di vendite ha un prezzo mediano inferiore a Bryan-College Station con una distribuzione stretta e quindi maggiore stabilità.
  4. Wichita Falls non solo ha il prezzo mediano più basso, ma ha anche le code del boxplot estese indicando una forte variabilità nei prezzi.
  5. Le vendite sono basse tra gennaio ed inizio febbraio e poi crescono rapidamente subito dopo raggiungendo il massimo tra maggio e giugno per poi calare un minimo fino ad inizio agosto ed avendo un calo drastico (tranne tra settembre ed ottobre che si stabilizza quasi) subito dopo fino ad inizio novembre ed infine una crescita subito dopo fino dicembre.
  6. Il valore totale delle vendite crescono in modo costante fino a giugno dove si raggiunge il massimo per poi calare in modo costante fino a novembre per poi infine risalire a dicembre.
  7. Le vendite medie dimuiscono dal 2010 al 2011 per poi crescere rapidamente in modo costante fino al 2014.
  8. Il valore totale delle vendite è molto simile tra il 2010 e il 2011 per salire in modo costante fino al 2014.
  9. Tyler mostra una crescita costante per il valore delle vendite totali. Bryan-College Station tra il 2010 e 2011 ha performance modesta per poi esplodere nel 2012 ed aumentando molto dopo nel 2013 per stabilizzarsi nel 2014 ma avendo comunque dei picchi molto alti. Beaumount ha una crescita costante, ma molta lenta che accelera tra il 2013 e 2014. Wichita Falls non ha una crescita praticamente, anzi tra il 2011 e 2012 la perfomance diminuisce.
  10. Tutte le città hanno un forte aumento di valore delle vendite tra marzo ed agosto, soprattutto Tyler e Brayan-College Station e in particolare da aprile a luglio.