## ── 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.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── 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
setwd("/Users/gpalma/Documents/GP/Corso Data science/Script") 
dati <- read.csv(file = "realestate_Texas.csv", header = TRUE, sep = ",", dec = ".")
ntot <- nrow(dati)
variable_names <- c("City", "Year", "Month", 
                    "Sales", "Volume", "Median Price", 
                    "Listings", "Months Inventory")
tab_city <- dati %>% 
group_by(city) %>% 
count() %>% 
mutate(f = round(n/ntot,4)) %>%
mutate(p=f*100) 
#verifico tab_city
sapply(tab_city, is.numeric)
##  city     n     f     p 
## FALSE  TRUE  TRUE  TRUE
tab_city <- rbind(
  data.frame(tab_city), 
  c("Totale", colSums(tab_city[, -1]))
)

#prosecuzione dell'attvità con year 

tab_month <- dati %>% group_by(year) %>% 
  count() %>% 
  mutate(f=round(n/ntot,4)) %>%
  mutate(p=f*100) 

tab_month <- rbind(data.frame(tab_month), c("Totale", colSums(tab_month[, -1])))
#presecuzione dell'attività con Month

tab_month <- dati %>% group_by(month) %>% 
  count() %>% 
  mutate(f=round(n/ntot, 4)) %>%
  mutate(p=f*100) 

tab_month <- rbind(data.frame(tab_month), c("Totale", colSums(tab_month[, -1])))
dati_quant <- dati %>% select(sales, volume, median_price, listings, months_inventory)

tab_var_quantitative <- dati_quant %>% 
  reframe(minimo = round(sapply(dati_quant, min), 2),  
          massimo = round(sapply(dati_quant, max), 2),
          `1° qu.` = round(sapply(dati_quant, function(x) {quantile(x, 0.25)}), 2), 
          median = round(sapply(dati_quant, median), 2),
          `3° qu.` = round(sapply(dati_quant, function(x) {quantile(x, 0.75)}), 2),
          media = round(sapply(dati_quant, mean), 2),
          `dev. std.` = round(sapply(dati_quant, sd), 2), 
          asimmetria = round(sapply(dati_quant, skewness), 2),
          curtosi = round(sapply(dati_quant, function(x) {kurtosis(x) - 3}), 2)) %>%
  mutate(CV = round(`dev. std.`/media,4) * 100) %>%  
  relocate(CV, .before=asimmetria)

tab_var_quantitative <- t(tab_var_quantitative)
tab_var_quantitative <- as.data.frame(tab_var_quantitative)
colnames(tab_var_quantitative) <- c("Sales", "Volume", "Median Price", "Listings", "Months Inventory")
kable(tab_var_quantitative, caption = "Statistiche descrittive delle variabili quantitative")
Statistiche descrittive delle variabili quantitative
Sales Volume Median Price Listings Months Inventory
minimo 79.00 8.17 73800.00 743.00 3.40
massimo 423.00 83.55 180000.00 3296.00 14.90
1° qu. 127.00 17.66 117300.00 1026.50 7.80
median 175.50 27.06 134500.00 1618.50 8.95
3° qu. 247.00 40.89 150050.00 2056.00 10.95
media 192.29 31.01 132665.42 1738.02 9.19
dev. std. 79.65 16.65 22662.15 752.71 2.30
CV 41.42 53.69 17.08 43.31 25.03
asimmetria 0.72 0.88 -0.36 0.65 0.04
curtosi -0.31 0.18 -0.62 -0.79 -0.17
testo_Analisi <- "
In media, si registrano circa 192 vendite al mese (deviazione standard = 80), 
con un minimo di 79 vendite e un massimo di 423. La variabile vendite mostra 
una leggera asimmetria positiva, la media supera la mediana.

Il valore totale delle vendite (volume) ha una media di 31 milioni di dollari 
al mese (deviazione standard = 16.65). Anche in questo caso, la variabile 
presenta un'andamento asimmetrico positivo.

Il prezzo mediano delle vendite (median_price) ha una media di 132.655,42 dollari 
(deviazione standard = 22.662,15).

Si registrano mediamente circa 1.738 annunci attivi (listings) al mese 
(deviazione standard = 753). Anche in questo caso, la variabile presenta 
un'andamento asimmetrico positivo e platicurtico.

Infine, il tempo medio necessario per vendere tutte le inserzioni attuali, 
considerando il ritmo delle vendite, è di 9 mesi e 6 giorni (deviazione 
standard = 2 mesi e 9 giorni). Questa variabile (months_inventory) risulta 
quasi simmetrica.
"

# Stampa il testo
cat(testo_Analisi)
## 
## In media, si registrano circa 192 vendite al mese (deviazione standard = 80), 
## con un minimo di 79 vendite e un massimo di 423. La variabile vendite mostra 
## una leggera asimmetria positiva, la media supera la mediana.
## 
## Il valore totale delle vendite (volume) ha una media di 31 milioni di dollari 
## al mese (deviazione standard = 16.65). Anche in questo caso, la variabile 
## presenta un'andamento asimmetrico positivo.
## 
## Il prezzo mediano delle vendite (median_price) ha una media di 132.655,42 dollari 
## (deviazione standard = 22.662,15).
## 
## Si registrano mediamente circa 1.738 annunci attivi (listings) al mese 
## (deviazione standard = 753). Anche in questo caso, la variabile presenta 
## un'andamento asimmetrico positivo e platicurtico.
## 
## Infine, il tempo medio necessario per vendere tutte le inserzioni attuali, 
## considerando il ritmo delle vendite, è di 9 mesi e 6 giorni (deviazione 
## standard = 2 mesi e 9 giorni). Questa variabile (months_inventory) risulta 
## quasi simmetrica.
# Estrai i valori del CV
cv_values <- as.numeric(tab_var_quantitative["CV", ])  # Assicurati che siano numerici

# Trova il valore massimo del CV e l'indice della variabile associata
max_cv_index <- which.max(cv_values)
max_cv <- cv_values[max_cv_index]

# Trova il nome della variabile associata al CV massimo
max_cv_variable <- colnames(tab_var_quantitative)[max_cv_index]

# Stampa i risultati
cat("Il CV massimo è:", max_cv, "relativo alla variabile", max_cv_variable, "\n")
## Il CV massimo è: 53.69 relativo alla variabile Volume
breaks_sales <- seq(min(dati$sales), max(dati$sales), length.out = 6) # Suddivisione in 5 classi
sales_classes <- cut(dati$sales, breaks = breaks_sales, include.lowest = TRUE, right = FALSE)
sales_cat <- cut(dati$sales,
                 breaks = breaks_sales)

tab_sales_class <- dati %>%
  mutate(sales_cat = sales_cat) %>%
  group_by(sales_cat) %>%
  count() %>%
  mutate(f=n/ntot) %>%
  mutate(p=f*100)

#in %
perc = paste0(round(tab_sales_class[-6, ]$p, 2), "%")
perc[1] = "35.00%"
perc
## [1] "35.00%" "32.08%" "17.08%" "11.25%" "4.58%"
ggplot(tab_sales_class[-6, ]) +
  geom_bar(aes(x = sales_cat, y = n),
           stat = "identity",
           color = "black",  # Colore del bordo
           fill = "darkgreen") +  # Colore di riempimento
  geom_text(aes(x = sales_cat, y = n, label = perc),
            stat = "identity",
            vjust = -0.3, size = 5) +
  labs(x = "Numero totale di vendite in classi",
       y = "Frequenze assolute") +
  theme_minimal(base_size = 10)

#indice di Gini
gini_index <- ineq(dati$sales, type = "Gini")
cat("Indice di Gini per la variabile Sales:", round(gini_index, 3), "\n")
## Indice di Gini per la variabile Sales: 0.231
# Discussione dei risultati
# Controlla e arrotonda l'indice di Gini per ogni condizione
if (gini_index > 0.5) {
  cat(round(gini_index, 3), "La distribuzione delle vendite è molto disuguale, con una significativa eterogeneità.\n")
} else if (gini_index > 0.3) {
  cat(round(gini_index, 3), "La distribuzione delle vendite mostra un moderato livello di disuguaglianza.\n")
} else {
  cat(round(gini_index, ), "La distribuzione delle vendite è abbastanza uniforme.\n")
}
## 0 La distribuzione delle vendite è abbastanza uniforme.
# Numero totale di righe nel dataset
ntot <- nrow(dati)

# Funzione per calcolare e formattare le probabilità in percentuale
calcola_probabilita <- function(condizione, nome) {
  count <- nrow(dati[condizione, ])
  prob <- (count / ntot) * 100
  formatted_prob <- paste0(round(prob, 2), "%")
  cat("La probabilità che una riga del dataset riporti", nome, "è:", formatted_prob, "\n")
}

# Calcolo delle probabilità
calcola_probabilita(dati$city == "Beaumont", "'Beaumont'")
## La probabilità che una riga del dataset riporti 'Beaumont' è: 25%
calcola_probabilita(dati$month == "7", "'Luglio'")
## La probabilità che una riga del dataset riporti 'Luglio' è: 8.33%
calcola_probabilita(dati$month == "12" & dati$year == 2012, "'Dicembre 2012'")
## La probabilità che una riga del dataset riporti 'Dicembre 2012' è: 1.67%
# Calcolo del prezzo medio
dati <- dati %>% 
  mutate(average_price = volume * 1e6 / sales)

# Calcolo delle statistiche descrittive
tab_avgprice <- dati %>% 
  summarize(
    minimo = round(min(average_price, na.rm = TRUE), 2),
    massimo = round(max(average_price, na.rm = TRUE), 2),
    `1° qu.` = round(quantile(average_price, 0.25, na.rm = TRUE), 2),
    median = round(median(average_price, na.rm = TRUE), 2),
    `3° qu.` = round(quantile(average_price, 0.75, na.rm = TRUE), 2),
    media = round(mean(average_price, na.rm = TRUE), 2),
    `dev. std.` = round(sd(average_price, na.rm = TRUE), 2),
    asimmetria = round(skewness(average_price, na.rm = TRUE), 2),
    curtosi = round(kurtosis(average_price, na.rm = TRUE) - 3, 2)
  ) %>%
  mutate(CV = round(`dev. std.` / media * 100, 2)) %>%
  relocate(CV, .before = asimmetria)

# Trasponi e aggiungi la colonna 'Median Price' da tab_avgprice
tab_avgprice <- t(rbind(`Average Price` = tab_avgprice, `Median Price` = tab_var_quantitative$`Median Price`))
# efficacia = percentuale di vendite sul totale degli annunci attivi a inizio mese
dati <- dati %>% mutate(efficacy = round(sales/(listings+sales), 4)*100)

efficacia_annunci <- dati %>% select(efficacy) %>% 
  reframe(minimo = round(min(efficacy), 2),  
          massimo = round(max(efficacy), 2),
          `1° qu.` = round(quantile(efficacy, 0.25), 2), 
          median = round(median(efficacy), 2),
          `3° qu.` = round(quantile(efficacy, 0.75), 2),
          media = round(mean(efficacy), 2),
          `dev. std.` = round(sd(efficacy), 2), 
          asimmetria = round(skewness(efficacy), 2),
          curtosi = round(kurtosis(efficacy)-3, 2)) %>%
  mutate(CV = round(`dev. std.`/media*100, 2)) %>%  
  relocate(CV, .before=asimmetria)



kable(efficacia_annunci, caption = "Statistiche descrittive relative alla nuova variabile efficacy.")
Statistiche descrittive relative alla nuova variabile efficacy.
minimo massimo 1° qu. median 3° qu. media dev. std. CV asimmetria curtosi
4.77 27.91 8.24 9.88 11.89 10.47 3.49 33.33 1.6 4.17
# Commento sui risultati
commento <- c(
  "L'efficienza massima registrata è di ", round(max(efficacia_annunci$massimo), 2), 
  "%, indicando che in alcuni casi le vendite rappresentano più di un quarto del totale degli annunci attivi all'inizio del mese. ",
  "Un'efficienza così elevata suggerisce che ci possono essere periodi o località in cui la domanda di mercato supera significativamente l'offerta. ",
  "Il valore di assimmetria è di ", round(efficacia_annunci$asimmetria, 2), 
  ", che indica una distribuzione asimmetrica a destra, con la maggior parte dei valori concentrati nella parte bassa della distribuzione e alcuni casi di alta efficienza che tirano verso l'alto la media. ",
  "La curtosi è di ", round(efficacia_annunci$curtosi, 2), 
  ", suggerendo che la distribuzione ha code più pesanti rispetto a una distribuzione normale, indicando più valori estremi e una maggiore variabilità nel mercato."
)
print(commento)
##  [1] "L'efficienza massima registrata è di "                                                                                                                                                                     
##  [2] "27.91"                                                                                                                                                                                                     
##  [3] "%, indicando che in alcuni casi le vendite rappresentano più di un quarto del totale degli annunci attivi all'inizio del mese. "                                                                           
##  [4] "Un'efficienza così elevata suggerisce che ci possono essere periodi o località in cui la domanda di mercato supera significativamente l'offerta. "                                                         
##  [5] "Il valore di assimmetria è di "                                                                                                                                                                            
##  [6] "1.6"                                                                                                                                                                                                       
##  [7] ", che indica una distribuzione asimmetrica a destra, con la maggior parte dei valori concentrati nella parte bassa della distribuzione e alcuni casi di alta efficienza che tirano verso l'alto la media. "
##  [8] "La curtosi è di "                                                                                                                                                                                          
##  [9] "4.17"                                                                                                                                                                                                      
## [10] ", suggerendo che la distribuzione ha code più pesanti rispetto a una distribuzione normale, indicando più valori estremi e una maggiore variabilità nel mercato."
# Funzione per calcolare statistiche descrittive
calc_stats <- function(data, group_var) {
  data %>%
    group_by({{ group_var }}) %>%
    summarise(
      minimo = round(min(sales, na.rm = TRUE), 2),
      massimo = round(max(sales, na.rm = TRUE), 2),
      `1° qu.` = round(quantile(sales, 0.25, na.rm = TRUE), 2),
      median = round(median(sales, na.rm = TRUE), 2),
      `3° qu.` = round(quantile(sales, 0.75, na.rm = TRUE), 2),
      media = round(mean(sales, na.rm = TRUE), 2),
      `dev. std.` = round(sd(sales, na.rm = TRUE), 2),
      asimmetria = round(moments::skewness(sales, na.rm = TRUE), 2),
      curtosi = round(moments::kurtosis(sales, na.rm = TRUE) - 3, 2)
    ) %>%
    mutate(CV = round(`dev. std.` / media * 100, 2)) %>%
    relocate(CV, .before = asimmetria)
}

# Statistiche per città
tabella_citta <- calc_stats(dati, city)

# Statistiche per anno
tabella_anno <- calc_stats(dati, year)

# Statistiche per mese
tabella_mese <- calc_stats(dati, month)

# Stampa delle tabelle usando kable
kable(tabella_citta, caption = "Statistiche descrittive per le vendite condizionatamente alla città.")
Statistiche descrittive per le vendite condizionatamente alla città.
city minimo massimo 1° qu. median 3° qu. media dev. std. CV asimmetria curtosi
Beaumont 83 273 150.00 176.5 202.00 177.38 41.48 23.38 0.19 -0.16
Bryan-College Station 89 403 134.75 186.5 282.50 205.97 84.98 41.26 0.65 -0.60
Tyler 143 423 227.00 271.0 313.75 269.75 61.96 22.97 0.14 -0.40
Wichita Falls 79 167 97.00 114.5 130.00 116.07 22.15 19.08 0.32 -0.59
kable(tabella_anno, caption = "Statistiche descrittive per le vendite condizionatamente all'anno.")
Statistiche descrittive per le vendite condizionatamente all’anno.
year minimo massimo 1° qu. median 3° qu. media dev. std. CV asimmetria curtosi
2010 83 316 120.75 162.0 202.00 168.67 60.54 35.89 0.59 -0.51
2011 79 313 113.75 144.5 200.50 164.12 63.87 38.92 0.73 -0.57
2012 90 322 124.75 171.0 238.75 186.15 70.91 38.09 0.52 -1.06
2013 79 402 147.75 193.5 272.25 211.92 84.00 39.64 0.48 -0.75
2014 89 423 149.50 215.0 300.75 230.60 95.51 41.42 0.30 -1.03
kable(tabella_mese, caption = "Statistiche descrittive per le vendite condizionatamente al mese.")
Statistiche descrittive per le vendite condizionatamente al mese.
month minimo massimo 1° qu. median 3° qu. media dev. std. CV asimmetria curtosi
1 79 238 89.00 112.5 153.75 127.40 43.38 34.05 0.87 0.15
2 79 244 101.00 124.5 181.00 140.85 51.07 36.26 0.70 -0.80
3 102 298 148.50 175.5 243.25 189.45 59.18 31.24 0.49 -0.95
4 111 323 166.75 199.0 256.50 211.70 65.40 30.89 0.22 -1.05
5 102 388 159.75 246.0 290.25 238.85 83.12 34.80 -0.01 -1.08
6 111 423 162.25 258.0 304.75 243.55 95.00 39.01 0.09 -1.11
7 104 403 159.75 209.0 299.50 235.75 96.27 40.84 0.48 -1.07
8 123 357 157.25 228.0 296.50 231.45 79.23 34.23 0.08 -1.42
9 95 361 126.25 165.5 221.00 182.35 72.52 39.77 0.85 -0.12
10 97 369 113.75 163.5 220.25 179.90 74.95 41.66 0.85 0.08
11 93 300 114.50 157.0 177.75 156.85 55.47 35.36 0.91 0.47
12 81 332 126.75 155.5 203.75 169.40 60.75 35.86 0.79 0.58
ggplot(dati) + 
  geom_boxplot(aes(x=city, y=median_price), 
               fill="orange3") + 
  labs(x="Città", 
       y="Prezzo mediano delle vendite condizionato alla città") + 
  theme_minimal(base_size = 10)

#due

dati$year <- as.factor(dati$year)
dati$month <- as.factor(dati$month)
dati <- dati %>% 
  mutate(month_lab = month, .after = month)
levels(dati$month_lab) <- c("Gennaio", "Febbraio", "Marzo", "Aprile", 
                            "Maggio", "Giugno", "Luglio", "Agosto",
                            "Settembre", "Ottobre", "Novembre", "Dicembre")

commento <- data.frame(
  Città = c("Beaumont", "Bryan-College Station", "Tyler", "Wichita Falls"),
  Analisi = c(
    "Aumento del valore delle vendite, ma oscillazioni nella variabilità; 2012 con minore variabilità.",
    "Crescita progressiva della mediana e variabilità dal 2010 al 2014, mercato diversificato.",
    "Aumento della mediana delle vendite e crescente variabilità, mercato in espansione.",
    "Mediana costante e bassa variabilità, suggerendo un mercato stabile."
  )
)

knitr::kable(commento, col.names = c("Città", "Analisi"), caption = "Analisi delle vendite per città")
Analisi delle vendite per città
Città Analisi
Beaumont Aumento del valore delle vendite, ma oscillazioni nella variabilità; 2012 con minore variabilità.
Bryan-College Station Crescita progressiva della mediana e variabilità dal 2010 al 2014, mercato diversificato.
Tyler Aumento della mediana delle vendite e crescente variabilità, mercato in espansione.
Wichita Falls Mediana costante e bassa variabilità, suggerendo un mercato stabile.
ggplot(data=dati) + 
  geom_boxplot(aes(x=year, y=volume, fill=city)) + 
  facet_wrap(~city) + 
  labs(x="Città", 
       y="Volume totale delle vendite") + 
  labs(fill = "Città") +
  theme_minimal(base_size = 10)

#Line chart per l'andamento delle vendite nel tempo ( due visualizzazioni)


ggplot(dati, aes(x = as.Date(paste(year, month, "01", sep = "-")), y = sales, color = city)) +
  geom_line() +
  theme_minimal() +
  labs(title = "Andamento delle Vendite Storiche", x = "Data", y = "Vendite")

#grafico a barre sovrapposte

ggplot(dati, aes(x = interaction(month, year), y = sales, fill = city)) +
  geom_bar(stat = "identity", position = "stack") +
  theme_minimal() +
  labs(title = "Totale delle Vendite per Mese e Anno (Barre Sovrapposte)", x = "Mese e Anno", y = "Numero di Vendite") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))  # Ruota le etichette per renderle leggibili

#grafico condizionato solo ai mesi
ggplot(dati, aes(x = factor(month), y = sales, fill = city)) +
  geom_bar(stat = "identity", position = "stack") +
  theme_minimal() +
  labs(title = "Totale delle Vendite per Mese e Città (Barre Sovrapposte)", x = "Mese", y = "Numero di Vendite") +
  scale_x_discrete(labels = month.abb) +  # Usa le abbreviazioni dei mesi
  theme(axis.text.x = element_text(angle = 90, hjust = 1))  # Ruota le etichette dei mesi per renderle leggibili

commento_stagionale <- data.frame(
  Mesi = "maggio-Agosto",
  Osservazione = "Le vendite si concentrano prevalentemente nei mesi estivi, con un picco tra maggio e luglio, tipico dell'andamento stagionale del mercato immobiliare."
)

knitr::kable(commento_stagionale, col.names = c("Mesi", "Osservazione"), caption = "Commento sulle vendite stagionali")
Commento sulle vendite stagionali
Mesi Osservazione
maggio-Agosto Le vendite si concentrano prevalentemente nei mesi estivi, con un picco tra maggio e luglio, tipico dell’andamento stagionale del mercato immobiliare.

```