knitr::opts_chunk$set(echo = TRUE)



# install.packages("dplyr") # manipolare facilmente i dati
# install.packages("e1071") # per skewness e kurtosis
# install.packages("purrr") #funzioni potenti ed evita for loop
# install.packages("kableExtra") #kableExtra per la gestione delle tabelle nel                                   #documento markdown
# install.packages("ggplot2") # per i grafici

#se i pacchetti non sono installati li installa
if (!require("dplyr")) {
  install.packages("dplyr")
}
if (!require("e1071")) {
  install.packages("e1071")
}
if (!require("purrr")) {
  install.packages("purrr")
}
if (!require("kableExtra")) {
  install.packages("kableExtra")
}
if (!require("ggplot2")) {
  install.packages("ggplot2")
}

#carica i pachetti
library(ggplot2)
library(kableExtra)
library(purrr)
library(dplyr)
library(e1071)

# toglie la notazione scientica
options(scipen = 999) 
#Utility -> funzioni per il calcolo della Moda, Indici, Frequenza, GINI Index

# Funzione per il calcolo della moda
get_mode <- function(v) {
  uniqv <- unique(v)
  uniqv[which.max(tabulate(match(v, uniqv)))]
}


# Funzione per calcolare tutti gli indici su un singolo vettore
# per variabili Quantitative, la funzione ha due paramtri:
# x -> variabile su cui calcolare gli indici
# variabile_continua -> indica se la variabile è continua o discreta
# se la variabile è continua non viene calcolato l'indice Moda
calcola_indici <- function(x,variabile_continua = FALSE) {
  if (variabile_continua)
    {
       data.frame(
                  media = mean(x, na.rm = TRUE), # Media aritmetica
                  mediana = median(x, na.rm = TRUE), # Mediana
                  minimo = min(x, na.rm = TRUE), # Minimo
                  massimo = max(x, na.rm = TRUE), # Massimo
                  Q1 = quantile(x, 0.25, na.rm = TRUE), # Primo quartile 
                  Q3 = quantile(x, 0.75, na.rm = TRUE), # Terzo quartile
                  varianza = var(x, na.rm = TRUE), # Varianza
                  deviazione_std = sd(x, na.rm = TRUE), # Deviazione standard
                  coeff_var = sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE), # Coefficiente di variazione
                  skewness = skewness(x, na.rm = TRUE), # Asimmetria (skewness)
                  kurtosis = kurtosis(x, na.rm = TRUE) # Curtosi
                )
  }
  else
  {
    
    data.frame(
                  media = mean(x, na.rm = TRUE),
                  mediana = median(x, na.rm = TRUE),
                  moda = get_mode(x), # Moda da funziona 
                  minimo = min(x, na.rm = TRUE),
                  massimo = max(x, na.rm = TRUE),
                  Q1 = quantile(x, 0.25, na.rm = TRUE),
                  Q3 = quantile(x, 0.75, na.rm = TRUE),
                  varianza = var(x, na.rm = TRUE),
                  deviazione_std = sd(x, na.rm = TRUE),
                  coeff_var = sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE),
                  skewness = skewness(x, na.rm = TRUE),
                  kurtosis = kurtosis(x, na.rm = TRUE)
                )
  }
 
}

# funzione per calcolare la frequenza per variabili categoriche
get_frequenze <- function(var) {
  df %>%
    count({{var}}, name = "Frequenza") %>%
    mutate(Frequenza_percentuale = round(Frequenza / sum(Frequenza) * 100, 2))
}

#indice di GINI
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)
  
}
caricamento dei dati del csv in un dataframe
#carica i dati del csv in un dataframe
df <- read.csv("Real Estate Texas.csv", sep = ",", header = TRUE)

1. Analisi delle variabili

Identifica e descrivi il tipo di variabili statistiche presenti nel dataset.
Variabile Descrizione Tipo di Variabile
city città di riferimento Qualitativa nominale
year anno di riferimento Quantitativa continua da trattare come qualitativa ordinale in questo caso
month mese di riferimento (es. 1,2, …) Qualitativa nominale
sales numero totale di vendite Quantitativa discreta
volume valore totale delle vendite (in milioni di dollari) Quantitativa continua
median_price prezzo mediano di vendita (in dollari) Quantitativa continua
listings numero totale di annunci immobiliari attivi Quantitativa discreta
months_inventory quantità di tempo necessaria per vendere tutte le inserzioni correnti, espresso in mesi Quantitativa continua
Valuta come gestire le variabili che sottintendono una dimensione tempo e commenta sul tipo di analisi che può essere condotta su ciascuna variabile.
Variabile Tipo di analisi
year
  • confronto tra anni (esempio confrontare la variabile Sales tra il 2013 e il 2014)

  • analisi storica (esempio valutare l’evoluzione della variabile Volume negli anni)

  • trend nel tempo (esempio come cambiano le variabili Listings, Sales)

month
  • stagionalità (esempio identificare i mesi in cui avvengono più vendite variabile Sales)

  • pattern mensili (esempio capire se ci sono ricorrenze tipo tra estate e inverno )

  • visualizzazioni cicliche (esmpio grafici per vedere l’andamento di una variabile nell’anno)

2. Indici di posizione, variabilità e forma

# viene utilizzata la funzione calcola_indici per calcolare gli indici
riassunto_statistico_no_continue <- df %>%
  select(where(is.numeric)) %>%
  map_dfr(calcola_indici, .id = "variabile")

# dal riassunto statistico vengono tolte le varibili quantitative continue
# perchè alcuni indici non devono essere calcolati per tali variabili
riassunto_statistico_no_continue <- riassunto_statistico_no_continue %>%
  filter(!variabile %in% c("year", "month","volume","median_price","months_inventory"))

# gli indici vengono arrotondati alla seconda cifra decimale
riassunto_statistico_no_continue <- riassunto_statistico_no_continue %>%
  mutate(across(where(is.numeric), ~round(., 2)))

# viene creata la tabella degli indici tramite la funzione kbl del pacchetto  # knitr e poi formatta tramite la funzione kable_styling del pacchetto        kableExtra

riassunto_statistico_no_continue %>%
  kbl(caption = "Riepilogo statistico delle variabili quantitative discrete",
      align = "c", 
      booktabs = TRUE,
      row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 14)
Riepilogo statistico delle variabili quantitative discrete
variabile media mediana moda minimo massimo Q1 Q3 varianza deviazione_std coeff_var skewness kurtosis
sales 192.29 175.5 124 79 423 127.0 247 6344.3 79.65 0.41 0.71 -0.34
listings 1738.02 1618.5 1581 743 3296 1026.5 2056 566569.0 752.71 0.43 0.65 -0.81

Variabile Sales -> media e mediana sono maggiori della moda e questo si riflette sull’asimmetria che sarà positiva infatti l’indice skewness ha un valore positivo

Variabile Listings -> media e mediana sono maggiori della moda e questo si riflette sull’asimmetria che sarà positiva infatti l’indice skewness ha un valore positivo; il range è molto elevato tra un massimo di 3296 ed un minimo di 743 questo significa che i dati sono molto dispersi.

# viene utilizzata la funzione calcola_indici per calcolare gli indici
riassunto_statistico_continue <- df %>%
  select(where(is.numeric)) %>%
  map_dfr(~calcola_indici(.x, variabile_continua = TRUE), .id = "variabile")


# dal riassunto statistico vengono tolte le varibili quantitative discrete
# perchè già calcolate
riassunto_statistico_continue <- riassunto_statistico_continue %>%
  filter(!variabile %in% c("year", "month","sales","listings"))

# gli indici vengono arrotondati alla seconda cifra decimale
riassunto_statistico_continue <- riassunto_statistico_continue %>%
  mutate(across(where(is.numeric), ~round(., 2)))

# viene creata la tabella degli indici tramite la funzione kbl del pacchetto knitr e poi formatta tramite la funzione kable_styling del pacchetto kableExtra

riassunto_statistico_continue %>%
  kbl(caption = "Riepilogo statistico delle variabili quantitative continue",
      align = "c", 
      booktabs = TRUE,
      row.names = FALSE
      ) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 14)
Riepilogo statistico delle variabili quantitative continue
variabile media mediana minimo massimo Q1 Q3 varianza deviazione_std coeff_var skewness kurtosis
volume 31.01 27.06 8.17 83.55 17.66 40.89 277.27 16.65 0.54 0.88 0.15
median_price 132665.42 134500.00 73800.00 180000.00 117300.00 150050.00 513572983.09 22662.15 0.17 -0.36 -0.64
months_inventory 9.19 8.95 3.40 14.90 7.80 10.95 5.31 2.30 0.25 0.04 -0.20

Variabile Volume -> la media è superiore alla mediana questo denota una asimmetria positiva; il coefficiente di variazione ha un valore di 0.54 che denota una variabilità moderata

Variabile Median_price -> la media è leggermente inferiore alla mediana questo denota una asimmetria negativa; il coefficiente di variazione ha un valore di 0.17 che denota una bassa variabilità e cioè prezzi abbastanza stabili

Variabile Month_inventory -> media e mediana sono quasi simili questo denota una distribuzione simmetrica

# usando la funzione get_frequenze calcola la frequenza assoluta e percentuale delle varibili city, year e month
frequenze_city        <- get_frequenze(city)
frequenze_year        <- get_frequenze(year)
frequenze_month       <- get_frequenze(month)
#tramite le funzioni kbl e kable_styling knitr e kableExtra visualizza i dati un una tabella
frequenze_city %>%
  kbl(caption = "Distribuzione di frequenza per la variabile City",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 14)
Distribuzione di frequenza per la variabile City
city Frequenza Frequenza_percentuale
Beaumont 60 25
Bryan-College Station 60 25
Tyler 60 25
Wichita Falls 60 25

Variabile City -> Ogni città compare 60 volte nel dataset ed ha una frequenza del 25%, la distribuzione è perfettamente bilanciata

#tramite le funzioni kbl e kable_styling knitr e kableExtra visualizza i dati un una tabella
frequenze_year %>%
  kbl(caption = "Distribuzione di frequenza per la variabile Year",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 14)
Distribuzione di frequenza per la variabile Year
year Frequenza Frequenza_percentuale
2010 48 20
2011 48 20
2012 48 20
2013 48 20
2014 48 20

Variabile Year -> ogni anno compare 48 volte ed ha una frequenza del 20%, la distribuzione è perfettamente bilanciata

#tramite le funzioni kbl e kable_styling knitr e kableExtra visualizza i dati un una tabella
frequenze_month %>%
  kbl(caption = "Distribuzione di frequenza per la variabile Month",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = FALSE,
                font_size = 14)
Distribuzione di frequenza per la variabile Month
month Frequenza Frequenza_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

Variabile Month -> ogni mese compare 20 volte e la frequenza è di 8.33%, la distribuzione è perfettamente bilanciata

3. Identificazione delle variabili con maggiore variabilità e asimmetria

Determina: - Qual è la variabile con la più alta variabilità - Qual è la variabile con la distribuzione più asimmetrica Spiega come sei giunto a queste conclusioni e fornisci considerazioni statistiche.

La variabile con la più alta variabilità è Volume che ha il coefficiente di variazione di 0.54

Questo indica che i valori sono abbastanza dispersi attorno al valore medio.

Sono giunto a questa conclusione osservando l’indice “coeff_var” che mette in relazione la devianzione standard con la media ed è un indice adimensionale.

La variabile con la distribuzione più asimmetrica è Volume con un indice skewness di 0.88, asimmetrica positiva.

Questo indica che la distribuzione è asimmetrica positivamente, cioè con una coda più lunga verso valori maggiori, questo suggerisce la presenza di alcuni valori elevati.

Sono giunto a questa conclusione osservando l’indice “skewness” che misura la simmetria o asimmetria della distribuzione di una variabile rispetto alla sua media.

  • skewness = 0 -> distribuzione perfettamente simmetrica

  • skewness > 0 -> distribuzione asimmetrica a destra positiva

  • skewness < 0 -> distribuzione asimmetrica a sinistra negativa

4. Creazione di classi per una variabile quantitativa

Seleziona una variabile quantitativa (es. sales o median_price) e suddividila in classi. Crea una distribuzione di frequenze e rappresenta i dati con un grafico a barre. Calcola l’indice di eterogeneità Gini e discuti i risultati.

La variabile scelta per essere suddivisa in classi è Sales

# è una sequenza numerica che va da un valore minimo di 0 ad un valore massimo di 500 e un passo di 100
classi <- seq(0, 500, by = 100)

# crea la variabile sales_class utilizzando la sequenza numerica Classi per la variabile Sales
df <- df %>%
  mutate(sales_class = cut(
    sales,
    breaks = classi,   # numero di classi
    include.lowest = TRUE,
    right = FALSE, # intervalli chiusi a sinistra, aperti a destra
    dig.lab = 10   # evita notazione scientifica 
  ))

# tramite la funzione get_frequenze valorizza frequenze_sales_class con la frequenza delle varie classi calcolate nel precedente passaggio
frequenze_sales_class <- get_frequenze(sales_class)

# tramite le funzioni kbl e kable_styling viene creata la tabella da visualizzare
frequenze_sales_class %>%
  kbl(caption = "Distribuzione di frequenza delle Classi della variabile Sales",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = TRUE,
                font_size = 14)
Distribuzione di frequenza delle Classi della variabile Sales
sales_class Frequenza Frequenza_percentuale
[0,100) 20 8.33
[100,200) 127 52.92
[200,300) 67 27.92
[300,400) 23 9.58
[400,500] 3 1.25
index_gini_sales_class <- round( gini.index(df$sales_class) ,2)

L’indice di GINI per la variabile sales_class è 0.78 questo indica una concentrazione nella distribuzione delle classi, ovvero una classe o poche classi pesano più delle altre. Come si può osservare nella tabella “Distribuzione di frequenza delle Classi della variabile Sales” la classe 100,200 ha 127 occorrenze, corrispondente al 52.92% del totale.

# grafico a barre per la variabile sales_class
df %>%
  count(sales_class) %>%
  mutate(perc = round(n / sum(n) * 100, 1)) %>%
  ggplot(aes(x = sales_class, y = perc)) +
  geom_col() +
  geom_text(aes(label = paste0(perc, "%")), vjust = -0.5) +
  theme_minimal() +
  labs(
    title = "Distribuzione % delle Classi di Sales",
    x = "Classi di Sales",
    y = "Percentuale"
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

5. Calcolo della probabilità

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?
# Calcolo della probabilità

# utilizzando la formalura -> numero di osservazioni con filtro (city = Beaumont o month = 7) diviso il numero totale delle osservazioni moltiplicato per 100 per avere il valore in percentuale
p_beaumont <- round((sum(df$city == "Beaumont") / nrow(df)) * 100,2)
p_luglio <- round((sum(df$month == 7) / nrow(df))* 100,2)
p_dicembre_2012 <- round((sum(df$month == 12 & df$year == 2012) / nrow(df))* 100,2)

La probabilità che preso un record a caso del dataset esso riporti:

  • la città di Beaumont è del 25%

  • Il mese di Luglio è dell’8.33%

  • Il mese di dicembre dell’anno 2012 è dell’1.67%

6. Creazione di nuove variabili

Crea una nuova colonna che calcoli il prezzo medio degli immobili utilizzando le variabili disponibili.
# crea nuova variabile mean_price in questo modo: dividendo il volume totale per il numero di vendite (volume / sales). Poiché 'volume' è espresso in milioni di dollari, lo moltiplichiamo per 1000000 per ottenere il valore in dollari prima della divisione.
df$mean_price <- (df$volume * 1000000) / df$sales

# calcola il minimo e il massimo della variabile mean_price
min_mean_price <- round( min(df$mean_price),2)
max_mean_price <- round( max(df$mean_price),2)

# estrae la città con il minimo mean_price ed il massimo mean_price, è stata usata la funzione slice per estrarre solo la prima città
city_min_mean_price <- df %>% filter(mean_price == min(mean_price)) %>% slice(1) %>% pull(city)
city_max_mean_price <- df %>% filter(mean_price == max(mean_price)) %>% slice(1) %>% pull(city)

il prezzo medio minore del dataset è di 97010.2 per la città di Wichita Falls

il prezzo medio maggiore del dataset è 213233.94 per la città di Bryan-College Station

Prova a creare una colonna che misuri l’efficacia degli annunci di vendita. Commenta e discuti i risultati.
#efficacia annunci

# crea nuova variabile listing_performance in questo modo: immobili venduti (sales) / immobili in listino (listings)

df <- df %>%
  mutate(listing_performance = round(sales / listings, 2))

#listing_performance_percent, viene calcolata l'efficacia annunci in percentuale
df <- df %>%
  mutate(listing_performance_percent = round((sales / listings) * 100, 2))


min_listing_performance <- min(df$listing_performance)
max_listing_performance <- max(df$listing_performance)

# estrae la città con il minimo listing_performance_percent ed il massimo listing_performance_percent, è stata usata la funzione slice per estrarre solo la prima città
city_min_listing_performance_perc <- df %>% filter(listing_performance_percent == min(listing_performance_percent)) %>% slice(1) %>% pull(city)
city_max_listing_performance_perc <- df %>% filter(listing_performance_percent == max(listing_performance_percent)) %>% slice(1) %>% pull(city)


min_listing_performance_perc <- min(df$listing_performance_percent)
max_listing_performance_perc <- max(df$listing_performance_percent)

la città con la più bassa efficacia degli annuncci è Tyler con un valore del 5.01%

la città con la più alta efficacia degli annuncci è Bryan-College Station con un valore del 38.71%

7. Analisi condizionata

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.
#utilizzando il pacchetto dplyr viene calcolata una summary statistica per le città, le varibili calcolate sono: la media del prezzo medio media_mean_price, la deviazione standard del prezzo medio sd_mean_price, la media delle vendite media_sales, la deviazione standard delle vendite sd_sales 
summary_stats_city <- df %>%
  group_by(city) %>%
  summarise(
    media_mean_price = mean(mean_price, na.rm = TRUE),
    sd_mean_price = sd(mean_price, na.rm = TRUE),
    media_sales = mean(sales, na.rm = TRUE),
    sd_sales = sd(sales, na.rm = TRUE),
    .groups = "drop"
  )

#tabella per summary statistico delle città
summary_stats_city %>%
  kbl(caption = "Summary Statistico delle città",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 14)
Summary Statistico delle città
city media_mean_price sd_mean_price media_sales sd_sales
Beaumont 146640.4 11232.13 177.3833 41.48395
Bryan-College Station 183534.3 15149.35 205.9667 84.98374
Tyler 167676.8 12350.51 269.7500 61.96380
Wichita Falls 119430.0 11398.48 116.0667 22.15192
# tramite la libreria ggplot2 viene creato il grafico per media_mean_price e ordinato per media_mean_price, viene usata la funzione geom_errorbar per creare le linee nere che rappresentano la variabilità dei dati ed è così calcolata: il minimo (ymin) media_mean_price - sd_mean_pric; il massimo (ymax) media_mean_price + sd_mean_price

ggplot(summary_stats_city, aes(x = reorder(city, media_mean_price), y = media_mean_price)) +
  geom_col(fill = "lightblue") +
   geom_errorbar(aes(ymin = media_mean_price - sd_mean_price,
                     ymax = media_mean_price + sd_mean_price),
                 width = 0.2, color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media del Prezzo Medio per Città con Deviazione Standard",
    x = "Città",
    y = "Media del prezzo medio"
  )

Le barre azzurre rappresentano la media del prezzo medio per ogni città; le linee nere mostrano di quanto i prezzi possono variare rispetto alla media.

Bryan-College Station ha la media del prezzo medio delle case più alto, mentre Wichita Falls ha il più basso. La barra di errore più lunga di Bryan-College Station indica una deviazione standard maggiore, quindi i prezzi in questa città sono più dispersi e meno concentrati attorno alla media rispetto a Beaumont, Tyler e Wichita Falls.

# grafico di Sales per City, media e deviazione standard
ggplot(summary_stats_city, aes(x = reorder(city, media_sales), y = media_sales)) +
  geom_col(fill = "lightblue") +
   geom_errorbar(aes(ymin = media_sales - sd_sales,
                     ymax = media_sales + sd_sales),
                 width = 0.2, color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media delle Vendite per Città con Deviazione Standard",
    x = "Città",
    y = "Media delle Vendite"
  )

Le barre azzurre rappresentano la media delle vendite per ogni città; le linee nere mostrano di quanto le vendite possono variare rispetto alla media.

Tyler ha la media delle vendite più alta di tutte le città con un valore di 269.75 mentre Wichita Falls ha la media delle vendite più bassa di tutte le città. La deviazione standard di Bryan-College Station è la maggiore e denota una variabilità maggiore nelle vendite mentre quella più bassa è di Wichita Falls che indica una maggiore stabilità nel numero delle vendite

#utilizzando il pacchetto dplyr viene calcolata una summary statistica per year, le varibili calcolate sono: la media del prezzo medio media_mean_price, la deviazione standard del prezzo medio sd_mean_price, la media delle vendite media_sales, la deviazione standard delle vendite sd_sales 
summary_stats_year <- df %>%
  group_by(year) %>%
  summarise(
    media_mean_price = mean(mean_price, na.rm = TRUE),
    sd_mean_price = sd(mean_price, na.rm = TRUE),
    media_sales = mean(sales, na.rm = TRUE),
    sd_sales = sd(sales, na.rm = TRUE),
    .groups = "drop"
  )

#tabella per summary statistico per Year
summary_stats_year %>%
  kbl(caption = "Summary Statistico per Anno",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 14)
Summary Statistico per Anno
year media_mean_price sd_mean_price media_sales sd_sales
2010 150188.6 23279.55 168.6667 60.53708
2011 148250.6 24938.38 164.1250 63.87042
2012 150898.7 26438.50 186.1458 70.90509
2013 158705.2 26523.81 211.9167 83.99641
2014 163558.7 31740.53 230.6042 95.51490
# tramite la libreria ggplot2 viene creato il grafico per media_mean_price, viene usata la funzione geom_errorbar per creare le linee nere che rappresentano la variabilità dei dati ed è così calcolata: il minimo (ymin) media_mean_price - sd_mean_pric; il massimo (ymax) media_mean_price + sd_mean_price

ggplot(summary_stats_year, aes(x = year, y = media_mean_price)) +
  geom_col(fill = "lightblue") +
   geom_errorbar(aes(ymin = media_mean_price - sd_mean_price,
                     ymax = media_mean_price + sd_mean_price),
                 width = 0.2, color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media del Prezzo Medio per Anno con Deviazione Standard",
    x = "Anno",
    y = "Media del prezzo medio"
  )

Le barre azzurre rappresentano la media del prezzo medio per ogni anno; le linee nere mostrano di quanto i prezzi possono variare rispetto alla media.

Dal 2010 al 2014, si osserva una crescita costante del prezzo medio delle case e della deviazione standard.

# grafico di Sales per Year, media e deviazione standard
ggplot(summary_stats_year, aes(x = year, y = media_sales)) +
  geom_col(fill = "lightblue") +
   geom_errorbar(aes(ymin = media_sales - sd_sales,
                     ymax = media_sales + sd_sales),
                 width = 0.2, color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media delle Vendite per Anno con Deviazione Standard",
    x = "Anno",
    y = "Media delle Vendite"
  )

Le barre azzurre rappresentano la media delle vendite per ogni anno; le linee nere mostrano di quanto le vendite possono variare rispetto alla media.

Anche per le vendite si osserva una crescita costante nel periodo analizzato; il valore più alto della deviazione standard si registra nel 2014, il che suggerisce che il numero di case vendute ha mostrato maggiori fluttuazioni rispetto agli anni precedenti.

#utilizzando il pacchetto dplyr viene calcolata una summary statistica per month, le varibili calcolate sono: la media del prezzo medio media_mean_price, la deviazione standard del prezzo medio sd_mean_price, la media delle vendite media_sales, la deviazione standard delle vendite sd_sales 
summary_stats_month <- df %>%
  group_by(month) %>%
  summarise(
    media_mean_price = mean(mean_price, na.rm = TRUE),
    sd_mean_price = sd(mean_price, na.rm = TRUE),
    media_sales = mean(sales, na.rm = TRUE),
    sd_sales = sd(sales, na.rm = TRUE),
    .groups = "drop"
  )

#tabella per summary statistico per Year
summary_stats_month %>%
  kbl(caption = "Summary Statistico per Mese",
      align = "c", 
      booktabs = TRUE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                font_size = 14)
Summary Statistico per Mese
month media_mean_price sd_mean_price media_sales sd_sales
1 145640.4 29819.11 127.40 43.38372
2 148840.5 25120.42 140.85 51.06783
3 151136.5 23237.92 189.45 59.17812
4 151461.3 26174.30 211.70 65.40489
5 158235.0 25787.19 238.85 83.11582
6 161545.8 23470.46 243.55 94.99832
7 156881.0 27220.12 235.75 96.27421
8 156455.6 28253.21 231.45 79.22883
9 156522.3 29669.41 182.35 72.51807
10 155897.4 32527.29 179.90 74.95395
11 154233.0 29684.87 156.85 55.46670
12 154995.5 27008.87 169.40 60.74658
# tramite la libreria ggplot2 viene creato il grafico per media_mean_price, viene usata la funzione geom_errorbar per creare le linee nere che rappresentano la variabilità dei dati ed è così calcolata: il minimo (ymin) media_mean_price - sd_mean_pric; il massimo (ymax) media_mean_price + sd_mean_price

#in questi due grafici viene usata la funzione scale_x_continuous per gestire la variabile month perchè ggplot2 mette automaticamente nell'asse delle x valori tipo 2,5 o 7,5 invece per la variabile month i valori devono essere quelli presenti nella tabella
ggplot(summary_stats_month, aes(x = month, y = media_mean_price)) +
  geom_col(fill = "lightblue") +
  geom_errorbar(aes(ymin = media_mean_price - sd_mean_price,
                    ymax = media_mean_price + sd_mean_price),
                width = 0.2, color = "black") +
  scale_x_continuous(breaks = summary_stats_month$month) +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media del Prezzo Medio per Mese con Deviazione Standard",
    x = "Mese",
    y = "Media del prezzo medio"
  )

Le barre azzurre rappresentano la media del prezzo medio per ogni mese; le linee nere mostrano di quanto i prezzi possono variare rispetto alla media.

L’analisi per mesi evidenzia una stagionalità dei prezzi di vendita, con prezzi alti nei mesi estivi e prezzi bassi nei mesi invernali come Gennaio e Febbraio mentre la deviazione standard non segue questo andamento infatti i valori più alti si registrano nei mesi autunnali ed invernali.

# grafico di Sales per Month, media e deviazione standard
ggplot(summary_stats_month, aes(x = month, y = media_sales)) +
  geom_col(fill = "lightblue") +
   geom_errorbar(aes(ymin = media_sales - sd_sales,
                     ymax = media_sales + sd_sales),
                 width = 0.2, color = "black") +
  scale_x_continuous(breaks = summary_stats_month$month) +
  theme_minimal() +
  coord_flip() +
  labs(
    title = "Media delle Vendite per Mese con Deviazione Standard",
    x = "Mese",
    y = "Media delle Vendite"
  )

Le barre azzurre rappresentano la media delle vendite per ogni mese; le linee nere mostrano di quanto le vendite possono variare rispetto alla media.

L’analisi per mesi evidenzia una stagionalità delle vendite, con numero di vendite alte nei mesi estivi e numero di vendite basse nei mesi invernali come Gennaio e Febbraio anche la deviazione standard segue questo andamento con valori alti nei mesi estivi.

8. Creazione di visualizzazioni con ggplot2

Utilizza ggplot2 per creare grafici personalizzati. Assicurati di esplorare: - Boxplot per confrontare la distribuzione del prezzo mediano tra le città. - Grafici a barre per confrontare il totale delle vendite per mese e città. - Line charts per confrontare l’andamento delle vendite in periodi storici differenti.
# 1 boxplot per confrontare la distribuzione del prezzo mediano tra le varie città , fill = city
    ggplot(df, aes(x = city, y = median_price)) +
      geom_boxplot() +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
      labs(
        title = "Distribuzione del prezzo mediano per città",
        x = "Città",
        y = "Prezzo Mediano",
        fill = "Città"
      )

Prezzi più alti: Bryan-College Station ha i prezzi mediani più elevati, con valori che si aggirano intorno ai 150.000-160.000 $.

Prezzi intermedi: Tyler mostra prezzi leggermente inferiori rispetto a Bryan-College Station, con una mediana intorno ai 140.000 $ e una distribuzione abbastanza ampia.

Prezzi più bassi: Beaumont ha prezzi poco più bassi, con una mediana di circa 130.000 $. Wichita Falls presenta i prezzi più bassi del gruppo, con una mediana intorno ai 100.000 $.

Variabilità: Bryan-College Station e Tyler mostrano una maggiore variabilità nei prezzi (box più ampie), mentre Beaumont e Wichita Falls hanno delle distribuzioni più concentrate.

Outliers: Si possono notare alcuni valori anomali a Bryan-College Station e a Wichita Falls.

Il grafico suggerisce la presenza di differenze importanti nel mercato immobiliare tra le città prese in esame.

# 2 distribuzione delle vendite  tra le varie città e anni


# 2-1 Boxplot per confronto tra città , fill = city
ggplot(df, aes(x = city, y = sales)) +
  geom_boxplot(alpha = 0.7) +
  labs(title = "Distribuzione valore vendite per città",
       x = "Città",
       y = "Sales") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        legend.position = "none") 

Tyler al top: ha la mediana più alta (intorno a 275) e la seconda distribuzione più ampia. È il mercato più forte, con vendite che possono arrivare oltre 400.

Bryan-College Station interessante: ha una mediana più bassa di Tyler (circa 190), ma una distribuzione più ampia.

Beaumont stabile: ha una mediana intorno a 175 con una distribuzione meno ampia rispetto alle precedenti.

Wichita Falls ultima: ha una mediana bassa (circa 120) ed una distribuzione ristretta. È chiaramente il mercato più piccolo.

Variabilità: Tyler e Bryan-College Station hanno molta più variabilità nelle vendite rispetto a Beaumont e Wichita Falls

# 2-4 anni per ogni città 
ggplot(df, aes(x = as.factor(year), y = sales)) +
  geom_boxplot(alpha = 0.7) +
  facet_wrap(~city, ncol = 2) +
  labs(title = "Distribuzione valore vendite per anno e città",
       x = "Anno",
       y = "Sales") +
  theme_minimal() +
  theme(legend.position = "none") 

Beaumont: rappresenta il mercato più stabile, con una mediana che, nel corso degli anni, resta sempre con valori intorno a 175-200.

Bryan-College Station: nel 2010-2011 ha un mercato stabile; nel 2012, pur con una mediana stabile rispetto agli anni precedenti si osserva un’ampia distribuzione verso l’alto che culmina nel 2014 con un notevole aumento anche della mediana.

Tyler: Cresce costantemente dal 2010 al 2014, raggiungendo il picco nel 2014 con mediana intorno a 340.

Wichita Falls: è sicuramente il mercato più piccolo, con valori di mediana sempre inferiori a 150 con il minimo raggiunto nel 2014.

# 3 grafico a barre sovrapposte per confrontare il totale delle vendite nei vari mesi


df %>%
  group_by(month, city) %>%  # Raggruppa per mese e città
  summarise(total_sales = sum(sales, na.rm = TRUE), .groups = 'drop') %>%
  ggplot(aes(x = factor(month), y = total_sales, fill = city)) +
  geom_bar(stat = "identity") +  
  labs(
    title = "Totale Vendite per mese per città",
    x = "Mese",
    y = "Totale vendite",
    fill = "Città"
  ) +
  theme_minimal()

Il boom della primavera-estate: i mesi di maggio, giugno, luglio e agosto sono chiaramente i migliori, con vendite totali che superano le 4.500 unità, con giugno che rappresenta l’apice della crescita.

Autunno in calo: a partire dal mese di settembre si ha un calo progressivo delle vendite che culmina a novembre.

L’inverno è duro: i mesi invernali, in particolare gennaio e febbraio, sono i mesi più deboli, con vendite sotto le 3.000 unità.

È interessante vedere come tutte le città seguano lo stesso pattern stagionale, ma Tyler e Bryan-College Station amplificano molto di più l’effetto estate-inverno.

df %>%
  group_by(month, city,year) %>%
  summarise(total_sales = sum(sales, na.rm = TRUE), .groups = 'drop') %>%
  group_by(month,year) %>%
  mutate(perc_sales = total_sales / sum(total_sales)) %>%
  ggplot(aes(x = factor(month), y = perc_sales, fill = city)) +
  geom_bar(stat = "identity", position = "fill") +
  labs(
    title = "Distribuzione percentuale delle vendite per mese e città",
    x = "Mese",
    y = "Percentuale vendite",
    fill = "Città"
  ) +
  scale_y_continuous(labels = scales::percent) +
  theme_minimal()

Beaumont costante: La fascia rossa è rappresentata in modo stabile nel corso dell’anno.

Bryan-College Station tiene bene: La fascia verde è ben rappresentata particolarmente nei mesi estivi, indice che questa città contribuisce notevolmente al totale delle vendite.

Tyler domina sempre: La fascia azzurra è la più ampia ogni mese, confermando che è il mercato più forte durante tutto l’anno.

Wichita Falls sempre piccola: La fascia viola è la meno rappresentata, confermando che è il mercato più piccolo.

#Efficacia percentuale nel tempo è stato utilizzato questo as.Date(paste(year, month, "01", sep = "-")) per creare un asse delle x con mese-anno, è stato utilizzato scale_x_date per migliorre la visualizzazione dei dati e mettere un break ogni 3 mesi altrimenti le osservazioni erano troppo sovrapposte
df %>%
  mutate(date = as.Date(paste(year, month, "01", sep = "-"))) %>%
  group_by(date, city) %>%
  summarise(media_eff = mean(listing_performance_percent, na.rm = TRUE), .groups = 'drop') %>%
  ggplot(aes(x = date, y = media_eff, color = city)) +
  geom_line(linewidth = 1) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "3 months"   # una label ogni tre mesi
  ) +
  labs(
    title = "Efficacia percentuale nel tempo per città",
    x = "Mese - Anno",
    y = "Efficacia (%)",
    color = "Città"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Beaumont mostra una lieve flessione nell’efficacia nel 2011 per poi cresce costantemente fino al 2014;

Bryan-College Station ha avuto un picco di crescita a partire dal 2012 arrivando a superare il 20% nel 2014, rappresentando la città con l’efficacia migliore;

Tyler rappresenta una crescita dell’efficacia costante pur rimanendo con la percentuale di efficacia minore;

Wichita Falls ha un andamento altalenante, tuttavia i valori iniziali e finali sono simili mostrando una buona efficacia.

# la variabile sales nel tempo

#media_sales nel tempo è stato utilizzato questo as.Date(paste(year, month, "01", sep = "-")) per creare un asse delle x con mese-anno, è stato utilizzato scale_x_date per migliorre la visualizzazione dei dati e mettere un break ogni 3 mesi altrimenti le osservazioni erano troppo sovrapposte
df %>%
  mutate(date = as.Date(paste(year, month, "01", sep = "-"))) %>%
  group_by(date, city) %>%
  summarise(media_sales = mean(sales, na.rm = TRUE), .groups = 'drop') %>%
  ggplot(aes(x = date, y = media_sales, color = city)) +
  geom_line(linewidth = 1) +
  scale_x_date(
    date_labels = "%b %Y",
    date_breaks = "3 months"   # una label ogni tre mesi
  ) +
  labs(
    title = "Andamento delle vendite negli anni",
    x = "Mese - Anno",
    y = "Vendite",
    color = "Città"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

#dato che si è evidenziato un andamento stagionale delle vendite è stata aggiunta al dataset la variabile season calcolata in questo modo
df <- df %>%
  mutate(season = case_when(
    month %in% c(12, 1, 2) ~ "Winter",
    month %in% c(3, 4, 5) ~ "Spring",
    month %in% c(6, 7, 8) ~ "Summer",
    month %in% c(9, 10, 11) ~ "Autumn"
  ))

df %>%
  group_by(season, year) %>%
  summarise(mean_sales = mean(sales, na.rm = TRUE), .groups = 'drop') %>%
  ggplot(aes(x = season, y = mean_sales, color = factor(year), group = year)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  theme_minimal() +
  labs(
    title = "Vendite medie stagionali per anno",
    x = "Stagione",
    y = "Vendite medie",
    color = "Anno"
  )

Autunno e primavera le mezze stagioni: queste due stagioni hanno vendite simili, con la primavera che presenta vendite leggermente più alte.

Estate al primo posto: l’estate è chiaramente la stagione con più vendite, raggiungendo i picchi più alti soprattutto nel 2013 e 2014.

Inverno fanalino di coda: l’inverno è la stagione con vendite minori in tutti gli anni considerati.

Nel tempo: analizzando l’andamento delle vendite nel corso degli anni si nota una progressiva crescita dal 2011 con culmine nel 2014 in tutte le stagioni.

9. Conclusioni

Fornisci una sintesi dei risultati ottenuti, facendo riferimento alle principali tendenze emerse e fornendo raccomandazioni basate sull’analisi. Questo non è un progetto di programmazione, ma di statistica, e ci si aspetta di leggere commenti e considerazioni statistiche per i vari passaggi e risultati.

Dall’analisi dei grafici emerge un quadro interessante del mercato immobiliare delle quattro città studiate.

Bryan-College Station è il mercato più promettente: mostra un netto miglioramento nell’efficacia delle vendite con i prezzi più elevati.

Tyler conferma la promessa iniziale con una crescita costante con elevati valori di vendite.

Beaumont si posiziona in una fascia intermedia, con una crescita più lenta ma costante.

Wichita Falls presenta i valori più contenuti sia in termini di vendite che di prezzi.

Il dato più rilevante riguarda l’efficacia commerciale: anche se i tassi di conversione da annuncio a vendita sono generalmente bassi in tutte le città, si osservano miglioramenti per Beaumont e Tyler e un boom per quanto riguarda Bryan-College Station.

Raccomandazioni per Texas Realty Insights