— Data Cleaning —

Pulizia di ‘volume’ e ‘median_price’ che sono ‘chr’

if ("volume" %in% names(df) && is.character(df$volume)) {
  
  temp_vol <- gsub("\\.00$", "", df$volume)
  
  temp_vol <- gsub("[^0-9.]", "", temp_vol)
  df$volume_clean <- as.numeric(temp_vol)
  cat("Colonna 'volume' pulita in 'volume_clean'")

  na_count_vol <- sum(is.na(df$volume_clean))
  if (na_count_vol > 0) {
    warning(paste("Pulizia di 'volume' ha prodotto", na_count_vol, "valori NA. Verifica i dati originali problematici."))
  }
} else if ("volume" %in% names(df) && is.numeric(df$volume)) {
  
  df$volume_clean <- df$volume
  cat("\nColonna 'volume' era già numerica, copiata in 'volume_clean'.\n")
} else {
  warning("Colonna 'volume' non trovata.")
}
## Colonna 'volume' pulita in 'volume_clean'
if ("median_price" %in% names(df) && is.character(df$median_price)) {
  temp_mp <- gsub("[^0-9.]", "", df$median_price)
  df$median_price_clean <- as.numeric(temp_mp)
  cat("Colonna 'median_price' pulita in 'median_price_clean'.\n")
  na_count_mp <- sum(is.na(df$median_price_clean))
  if (na_count_mp > 0) {
    warning(paste("Pulizia di 'median_price' ha prodotto", na_count_mp, "valori NA. Verifica i dati originali problematici."))
  }
} else if ("median_price" %in% names(df) && is.numeric(df$median_price)) {
  
  df$median_price_clean <- df$median_price
  cat("\nColonna 'median_price' era già numerica, copiata in 'median_price_clean'.\n")
} else {
  warning("Colonna 'median_price' non trovata o di tipo inatteso.")
}
## Colonna 'median_price' pulita in 'median_price_clean'.
if ("year" %in% names(df) && "month" %in% names(df) && is.numeric(df$year) && is.numeric(df$month)) {
  df$year_month <- as.Date(paste(df$year, df$month, "01", sep = "-"), format = "%Y-%m-%d")
  cat("Variabile temporale 'year_month' creata/verificata.\n")
} else {
  warning("Colonne 'year'/'month' non trovate o non numeriche. Impossibile creare 'year_month'.")
}
## Variabile temporale 'year_month' creata/verificata.
cat("\n--- Struttura del Dataframe dopo la pulizia mirata ---\n")
## 
## --- Struttura del Dataframe dopo la pulizia mirata ---
str(df) 
## 'data.frame':    240 obs. of  11 variables:
##  $ city              : chr  "Beaumont" "Beaumont" "Beaumont" "Beaumont" ...
##  $ year              : int  2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
##  $ month             : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ sales             : int  83 108 182 200 202 189 164 174 124 150 ...
##  $ volume            : chr  "16.42" "18.09" "39.41.00" "39.39.00" ...
##  $ median_price      : chr  "163800" "138200" "122400" "123200" ...
##  $ listings          : int  1533 1586 1689 1708 1771 1803 1857 1830 1829 1779 ...
##  $ months_inventory  : num  9.5 10 10.6 10.6 10.9 11.1 11.7 11.6 11.7 11.5 ...
##  $ volume_clean      : num  16.4 18.1 39.4 39.4 41.5 ...
##  $ median_price_clean: num  163800 138200 122400 123200 123100 ...
##  $ year_month        : Date, format: "2010-01-01" "2010-02-01" ...

— 1. Analisi delle variabili

variabili <- data.frame(
  Nome = names(df),
  Tipo = sapply(df, class)
)
cat("\n--- Tipi Variabili Aggiornati ---\n")
## 
## --- Tipi Variabili Aggiornati ---
print(variabili)
##                                  Nome      Tipo
## city                             city character
## year                             year   integer
## month                           month   integer
## sales                           sales   integer
## volume                         volume character
## median_price             median_price character
## listings                     listings   integer
## months_inventory     months_inventory   numeric
## volume_clean             volume_clean   numeric
## median_price_clean median_price_clean   numeric
## year_month                 year_month      Date
analisi_possibili <- data.frame(
  Nome = names(df),
  Analisi_Suggerita = sapply(names(df), function(col_name) {
    col_data <- df[[col_name]] 
    if (grepl("city", col_name)) return("Frequenze / Raggruppamento")
    if (col_name %in% c("year", "month") && (is.numeric(col_data) || is.integer(col_data))) return("Analisi temporali / Raggruppamento")
    if (inherits(col_data, "Date")) return("Serie Storiche / Trend")  
    if (col_name %in% c("sales", "listings", "months_inventory") && (is.numeric(col_data) || is.integer(col_data))) return("Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni")
    if (col_name %in% c("volume_clean", "median_price_clean") && is.numeric(col_data)) return("Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni")
    if (col_name %in% c("volume", "median_price") && is.character(col_data)) return("Tipo originale Character, usare versione _clean per analisi")
    if (is.factor(col_data) || is.character(col_data)) return("Frequenze / Tabelle")
    return("Verificare tipo e contesto")
  })
)

cat("\n--- Analisi Possibili Suggerite ---\n")
## 
## --- Analisi Possibili Suggerite ---
print(analisi_possibili)
##                                  Nome
## city                             city
## year                             year
## month                           month
## sales                           sales
## volume                         volume
## median_price             median_price
## listings                     listings
## months_inventory     months_inventory
## volume_clean             volume_clean
## median_price_clean median_price_clean
## year_month                 year_month
##                                                                Analisi_Suggerita
## city                                                  Frequenze / Raggruppamento
## year                                          Analisi temporali / Raggruppamento
## month                                         Analisi temporali / Raggruppamento
## sales              Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni
## volume               Tipo originale Character, usare versione _clean per analisi
## median_price         Tipo originale Character, usare versione _clean per analisi
## listings           Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni
## months_inventory   Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni
## volume_clean       Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni
## median_price_clean Analisi quantitativa (media, mediana, ecc.) / Visualizzazioni
## year_month                                                Serie Storiche / Trend

#Calcola gli indici per le variabili numeriche

cat("\n--- Calcolo Indici Descrittivi ---\n")
## 
## --- Calcolo Indici Descrittivi ---
numeric_cols_analyze <- names(df)[sapply(df, function(x) is.numeric(x) || is.integer(x))]

for (col in numeric_cols_analyze) {
  cat("\n\nIndici per la colonna:", col, "\n")
  col_data <- df[[col]]
  valid_data <- col_data[!is.na(col_data)] 
  
  if(length(valid_data) > 0) {
    media <- mean(valid_data)
    mediana <- median(valid_data)
    moda_table <- table(valid_data)
    moda_values <- as.numeric(names(moda_table[moda_table == max(moda_table)]))
    moda_print <- if(length(moda_values) == 1) as.character(moda_values) else paste(moda_values, collapse=", ")
    
    dev_std <- sd(valid_data)
    varianza <- var(valid_data)
    intervallo <- range(valid_data)
    
    skewness_value <- suppressWarnings(e1071::skewness(valid_data))
    kurtosis_value <- suppressWarnings(e1071::kurtosis(valid_data))
    
    cat("Media:", media, "\n")
    cat("Mediana:", mediana, "\n")
    cat("Moda (valore/i più frequente/i):", moda_print, "\n")
    cat("Deviazione standard:", dev_std, "\n")
    cat("Varianza:", varianza, "\n")
    cat("Intervallo (Min, Max):", intervallo[1], ",", intervallo[2], "\n")
    cat("Asimmetria (Skewness):", skewness_value, "\n")
    cat("Curtosi:", kurtosis_value, "\n")
  } else {
    cat("Nessun dato numerico valido (non NA) trovato per l'analisi.\n")
  }
}
## 
## 
## Indici per la colonna: year 
## Media: 2012 
## Mediana: 2012 
## Moda (valore/i più frequente/i): 2010, 2011, 2012, 2013, 2014 
## Deviazione standard: 1.417169 
## Varianza: 2.008368 
## Intervallo (Min, Max): 2010 , 2014 
## Asimmetria (Skewness): 0 
## Curtosi: -1.314137 
## 
## 
## Indici per la colonna: month 
## Media: 6.5 
## Mediana: 6.5 
## Moda (valore/i più frequente/i): 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 
## Deviazione standard: 3.459267 
## Varianza: 11.96653 
## Intervallo (Min, Max): 1 , 12 
## Asimmetria (Skewness): 0 
## Curtosi: -1.231612 
## 
## 
## Indici per la colonna: sales 
## Media: 192.2917 
## Mediana: 175.5 
## Moda (valore/i più frequente/i): 124 
## Deviazione standard: 79.65111 
## Varianza: 6344.3 
## Intervallo (Min, Max): 79 , 423 
## Asimmetria (Skewness): 0.7136206 
## Curtosi: -0.33552 
## 
## 
## Indici per la colonna: listings 
## Media: 1738.021 
## Mediana: 1618.5 
## Moda (valore/i più frequente/i): 1581 
## Deviazione standard: 752.7078 
## Varianza: 566569 
## Intervallo (Min, Max): 743 , 3296 
## Asimmetria (Skewness): 0.6454431 
## Curtosi: -0.8101534 
## 
## 
## Indici per la colonna: months_inventory 
## Media: 9.1925 
## Mediana: 8.95 
## Moda (valore/i più frequente/i): 8.1 
## Deviazione standard: 2.303669 
## Varianza: 5.306889 
## Intervallo (Min, Max): 3.4 , 14.9 
## Asimmetria (Skewness): 0.04071944 
## Curtosi: -0.1979448 
## 
## 
## Indici per la colonna: volume_clean 
## Media: 37.94758 
## Mediana: 35.18 
## Moda (valore/i più frequente/i): 40.35 
## Deviazione standard: 17.72691 
## Varianza: 314.2433 
## Intervallo (Min, Max): 9.4 , 93.34 
## Asimmetria (Skewness): 0.7401135 
## Curtosi: 0.087581 
## 
## 
## Indici per la colonna: median_price_clean 
## Media: 131915.5 
## Mediana: 134500 
## Moda (valore/i più frequente/i): 130000 
## Deviazione standard: 25099.47 
## Varianza: 629983492 
## Intervallo (Min, Max): 10005 , 180000 
## Asimmetria (Skewness): -1.131604 
## Curtosi: 3.155215
non_numeric_cols <- names(df)[!sapply(df, function(x) is.numeric(x) || is.integer(x) || inherits(x, "Date"))]
if(length(non_numeric_cols) > 0) {
  cat("\n--- Frequenze per Colonne Non Numeriche ---\n")
  for(col in non_numeric_cols) {
    cat("\nFrequenze per:", col, "\n")
    print(table(df[[col]], useNA = "ifany")) 
  }
}
## 
## --- Frequenze per Colonne Non Numeriche ---
## 
## Frequenze per: city 
## 
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60 
## 
## Frequenze per: volume 
## 
##    10.46    12.15    12.22    12.32    12.47    13.31    13.56    14.03 
##        1        1        1        1        1        1        1        2 
##    14.34    14.44    14.47    15.09    15.21    15.22    16.08     16.2 
##        1        1        1        1        1        1        1        1 
##    16.42    17.27    17.31    17.43    17.55    18.05    18.09    18.19 
##        1        1        1        1        1        1        2        1 
##    18.25    18.46    19.02    19.06    19.07    19.17    19.26    19.31 
##        1        1        1        2        1        1        1        1 
##    19.36    19.43    19.47    19.59    20.06    20.23    20.25    20.27 
##        1        1        1        1        1        1        1        1 
##    20.32    20.35    20.53    20.58    21.05    21.12    21.16    21.37 
##        1        1        1        1        1        1        1        1 
##    21.44    22.12    22.54    23.05    23.09    23.29    23.51    23.55 
##        1        1        1        1        1        1        1        1 
## 24.04.00 24.07.00 24.12.00 24.52.00 24.55.00 25.01.00 25.03.00 25.26.00 
##        1        1        1        1        1        1        1        1 
## 25.27.00 25.42.00 26.26.00 26.28.00 26.37.00 27.31.00 27.35.00 27.36.00 
##        1        1        1        1        1        1        1        1 
## 27.44.00 27.48.00 27.55.00 28.25.00 28.32.00 28.36.00 28.48.00 28.57.00 
##        1        1        1        1        1        1        1        1 
## 29.12.00 29.26.00 29.41.00 29.44.00 29.54.00 30.13.00 30.24.00 30.26.00 
##        1        1        1        1        1        1        1        1 
## 30.35.00 30.39.00 30.44.00 30.51.00 30.53.00 30.57.00 30.59.00 31.08.00 
##        1        1        1        1        1        1        1        1 
## 31.24.00 31.26.00 31.44.00 31.52.00 32.09.00 32.11.00 32.19.00 32.39.00 
##        1        1        1        1        1        1        1        1 
## 33.01.00 33.07.00 33.23.00 33.26.00 33.27.00 33.46.00 34.11.00 34.15.00 
##        1        1        1        1        1        1        1        1 
## 34.17.00 34.41.00 34.57.00 35.14.00 35.22.00 35.23.00 36.13.00 36.26.00 
##        1        1        1        1        1        1        1        1 
## 36.27.00 36.37.00 36.44.00 36.47.00 36.54.00 37.06.00 37.28.00 37.49.00 
##        1        1        1        1        1        1        1        1 
## 38.04.00 38.16.00 38.23.00 38.26.00 39.21.00 39.25.00 39.39.00 39.41.00 
##        1        1        1        1        1        1        1        1 
## 39.49.00 39.56.00 39.59.00 40.35.00 40.51.00 40.58.00 41.09.00 41.21.00 
##        1        1        1        3        1        1        1        1 
## 41.33.00 41.34.00 41.35.00 41.53.00 41.56.00 42.01.00 42.07.00 42.24.00 
##        1        1        1        1        1        1        1        1 
## 42.28.00 42.42.00 42.53.00 43.21.00 43.33.00 43.38.00 44.11.00 44.22.00 
##        1        2        1        1        1        1        1        1 
## 45.06.00 45.09.00 45.34.00 45.53.00 46.24.00 47.19.00 47.26.00 48.13.00 
##        1        1        1        1        1        1        1        1 
## 48.19.00 48.21.00 49.03.00 49.26.00 49.27.00 49.31.00 49.47.00 51.13.00 
##        1        1        1        1        1        1        1        2 
## 51.16.00 51.17.00 51.44.00 51.56.00 52.05.00 52.08.00 52.39.00 53.01.00 
##        1        1        1        1        1        1        1        1 
##     53.2 54.05.00 54.33.00 54.43.00 54.52.00 55.17.00 55.23.00 55.25.00 
##        1        1        1        1        1        1        1        1 
## 55.48.00 56.01.00 56.44.00 57.14.00 57.19.00 57.36.00 57.41.00 58.43.00 
##        1        1        1        1        1        1        1        1 
## 59.25.00 59.56.00 61.08.00 61.19.00 61.32.00 62.28.00 62.56.00 63.25.00 
##        1        1        1        1        1        1        1        1 
## 63.28.00 63.44.00 63.46.00 63.48.00 64.14.00 67.28.00 69.41.00 70.13.00 
##        1        1        1        1        2        1        1        1 
## 70.16.00 70.39.00 70.41.00 71.04.00 74.49.00 75.14.00 75.39.00 77.56.00 
##        1        1        1        1        1        1        1        1 
## 78.05.00 78.36.00 79.43.00 80.24.00      9.4 92.07.00 93.23.00 93.34.00 
##        1        1        1        1        1        1        1        1 
## 
## Frequenze per: median_price 
## 
## 1,00E+05   100700   101400   102300   102500   102900   103800   104700 
##        2        2        1        3        2        1        1        2 
##   105000   105200   105800   106700   108000   108300   109100   109400 
##        1        2        1        1        1        1        1        1 
##   110000   111100   112100   113300   113600   114000   114300   115700 
##        2        2        1        1        1        1        1        1 
##   116000   116500   116700   117500   118200   118800   119200   120000 
##        1        1        1        1        1        2        1        1 
##   120600   120700   121100   121200   121300   121800   122400   122800 
##        1        1        2        1        1        1        1        1 
##   123100   123200   123800   124200   124300   126100   126200   127000 
##        1        1        1        1        2        1        1        1 
##   128100   128200   128800   129100   129200   129400   129600   130000 
##        1        1        1        1        1        1        1        4 
##   130700   130800   131200   131400   131500   132100   132400   132500 
##        2        2        1        1        1        1        1        2 
##   132800   132900   133200   133300   133600   133800   134100   134200 
##        1        1        2        1        1        1        2        2 
##   134300   134400   134500   134700   135000   135100   135300   135700 
##        1        1        2        1        1        1        1        2 
##   136000   136100   136300   136800   137600   138200   138300   138500 
##        1        1        1        1        1        1        1        1 
##   138900   139200   139400   139600   140000   140500   140600   140700 
##        1        1        1        1        2        1        1        1 
##   142000   142200   142400   142700   143100   143600   144000   144100 
##        1        1        2        1        1        1        1        2 
##   144600   144800   144900   145000   145800   146700   146900   147000 
##        2        2        1        1        1        1        1        1 
##   147400   147600   147700   147900   148100   148300   148400   148500 
##        1        1        1        1        1        1        1        2 
##   148700   148900   149100   149300   149400   150000   150200   150700 
##        1        1        1        2        1        1        1        1 
##   151000   151200   151500   151700   151900   152000   152100   152200 
##        1        1        1        1        1        1        2        1 
##   152300   152600   153100   153300   153900   154300   154400   155200 
##        1        1        2        1        1        1        1        2 
##   155300   155500   155600   155700   156200   156400   156500   156600 
##        2        1        2        1        1        1        3        1 
##   157300   158200   158800   159300   159400   159700   161000   161200 
##        1        1        1        1        1        1        2        1 
##   161400   161600   163700   163800   165200   165300   166100   167300 
##        1        1        1        1        1        1        1        1 
##   168500   169500   169600   170000   172200   172600   172800   176100 
##        1        1        1        1        1        1        1        1 
##   177300   180000    73800    82100    85900    86400    87000    87200 
##        1        1        1        1        1        1        1        1 
##    87500    88600    89400    90000    90800    91200    91700    92200 
##        1        1        1        2        1        1        1        1 
##    93000    94000    95000    96000    96700    97500    99300    99600 
##        1        1        1        1        1        2        1        1

— 3. Max Variabilità e Asimmetria

cat("\n--- Identificazione Max Variabilità e Asimmetria ---\n")
## 
## --- Identificazione Max Variabilità e Asimmetria ---
dev_std_values <- numeric(0)
skewness_values <- numeric(0)

for (col in numeric_cols_analyze) {
  valid_data <- df[[col]][!is.na(df[[col]])]
  if (length(valid_data) > 1) { 
    dev_std_values[col] <- sd(valid_data) 
  }
  if (length(valid_data) > 0) {
    skewness_values[col] <- suppressWarnings(e1071::skewness(valid_data)) 
  }
}

print("Contenuto di dev_std_values:")
## [1] "Contenuto di dev_std_values:"
print(dev_std_values)
##               year              month              sales           listings 
##           1.417169           3.459267          79.651111         752.707756 
##   months_inventory       volume_clean median_price_clean 
##           2.303669          17.726908       25099.471956
print("Contenuto di skewness_values:")
## [1] "Contenuto di skewness_values:"
print(skewness_values)
##               year              month              sales           listings 
##         0.00000000         0.00000000         0.71362055         0.64544309 
##   months_inventory       volume_clean median_price_clean 
##         0.04071944         0.74011347        -1.13160353
if (length(dev_std_values) > 0 && any(!is.na(dev_std_values))) {
  max_dev_std_value <- max(dev_std_values, na.rm = TRUE)
  max_dev_std_col <- names(dev_std_values)[which.max(dev_std_values)]
  cat("\n\nVariabile con la maggiore variabilità (Deviazione Standard):\n")
  cat("Colonna:", max_dev_std_col, "\n")
  cat("Deviazione standard:", max_dev_std_value, "\n\n")
} else {
  cat("\nImpossibile determinare la variabile con massima deviazione standard.\n")
}
## 
## 
## Variabile con la maggiore variabilità (Deviazione Standard):
## Colonna: median_price_clean 
## Deviazione standard: 25099.47
if (length(skewness_values) > 0 && any(!is.na(skewness_values))) {
  abs_skewness <- abs(skewness_values)
  max_abs_skewness_value <- max(abs_skewness, na.rm = TRUE)
  max_skewness_col <- names(skewness_values)[which.max(abs_skewness)]
  original_max_skewness_value <- skewness_values[max_skewness_col]
  cat("Variabile con la distribuzione più asimmetrica (Skewness Assoluto Massimo):\n")
  cat("Colonna:", max_skewness_col, "\n")
  cat("Asimmetria (Skewness):", original_max_skewness_value, "(Valore Assoluto Massimo:", max_abs_skewness_value, ")\n")
} else {
  cat("\nImpossibile determinare la variabile con massima asimmetria.\n")
}
## Variabile con la distribuzione più asimmetrica (Skewness Assoluto Massimo):
## Colonna: median_price_clean 
## Asimmetria (Skewness): -1.131604 (Valore Assoluto Massimo: 1.131604 )

— 4. Frequenze e Gini per Sales Classificate

cat("\n--- Analisi Distribuzione Sales Classificate ---\n")
## 
## --- Analisi Distribuzione Sales Classificate ---
if ("sales" %in% names(df) && (is.numeric(df$sales) || is.integer(df$sales)) && sum(!is.na(df$sales)) > 0) {
  sales_class <- cut(df$sales, breaks = 4,
                     labels = c("Basso", "Medio", "Alto", "Molto Alto"),
                     include.lowest = TRUE)
  
  
  df$sales_class <- sales_class
  
  cat("\nFrequenze per 'sales_class':\n")
  print(summary(df$sales_class))
  
  N <- sum(!is.na(df$sales_class))
  if (N > 0) {
    ni <- table(df$sales_class)
    fi <- ni / N
    Ni <- cumsum(ni)
    Fi <- Ni / N
    
    distr_freq_lungh_sales <- as.data.frame(cbind(ni, fi, Ni, Fi))
    print("\nTabella Completa Frequenze (sales_class):")
    print(distr_freq_lungh_sales)
    
    barplot(ni, names.arg = names(ni), col = "pink",
            main = "Distribuzione Frequenze Assolute (Sales Class)",
            xlab = "Categorie di Sales", ylab = "Frequenza Assoluta")
   
    gini.index <- function(x) {
      valid_x <- x[!is.na(x)]
      if (length(valid_x) == 0) return(NA)
      ni <- table(valid_x)
      fi <- ni / length(valid_x)
      fi2 <- fi^2
      J <- length(fi)
      if (J <= 1) return(0)
      gini <- 1 - sum(fi2)
      gini.norm <- gini / ((J - 1) / J)
      return(gini.norm)
    }
    gini_sales_class <- gini.index(df$sales_class)
    cat("\nIndice di Gini Normalizzato per 'sales_class':", gini_sales_class, "\n")
    
  } else {
    cat("\nNessun dato valido in 'sales_class' per calcolare frequenze o Gini.\n")
  }
  
} else {
  warning(" Impossibile classificare e calcolare Gini.")
}
## 
## Frequenze per 'sales_class':
##      Basso      Medio       Alto Molto Alto 
##        110         71         45         14 
## [1] "\nTabella Completa Frequenze (sales_class):"
##             ni         fi  Ni        Fi
## Basso      110 0.45833333 110 0.4583333
## Medio       71 0.29583333 181 0.7541667
## Alto        45 0.18750000 226 0.9416667
## Molto Alto  14 0.05833333 240 1.0000000

## 
## Indice di Gini Normalizzato per 'sales_class': 0.8851389

— 5. Calcolo della probabilità

cat("\n--- Calcolo Probabilità  ---\n")
## 
## --- Calcolo Probabilità  ---
if (exists("df") && nrow(df) > 0) {
  total_rows <- nrow(df)
  if ("city" %in% names(df)) {
    prob_beaumont <- sum(df$city == "Beaumont", na.rm = TRUE) / total_rows
    cat("Probabilità Beaumont:", prob_beaumont, "\n")
  } else { cat("Colonna 'city' non trovata.\n") }
  if ("month" %in% names(df) && is.numeric(df$month)) {
    prob_july <- sum(df$month == 7, na.rm = TRUE) / total_rows
    cat("Probabilità Luglio (mese == 7):", prob_july, "\n")
  } else { cat("Colonna 'month' non trovata o non numerica.\n") }
  if ("month" %in% names(df) && "year" %in% names(df) && is.numeric(df$month) && is.numeric(df$year)) {
    prob_dec_2012 <- sum(df$month == 12 & df$year == 2012, na.rm = TRUE) / total_rows
    cat("Probabilità Dicembre 2012:", prob_dec_2012, "\n")
  } else { cat("Colonne 'month'/'year' non trovate o non numeriche.\n") }
} else { cat("Dataframe 'df' non trovato o vuoto.\n") }
## Probabilità Beaumont: 0.25 
## Probabilità Luglio (mese == 7): 0.08333333 
## Probabilità Dicembre 2012: 0.01666667

— 6. Creazione di nuove variabili

cat("\n--- Creazione Nuove Variabili: Prezzo Medio ed Efficacia Annunci ---\n")
## 
## --- Creazione Nuove Variabili: Prezzo Medio ed Efficacia Annunci ---
if ("volume_clean" %in% names(df) && "sales" %in% names(df) && is.numeric(df$volume_clean) && (is.numeric(df$sales) || is.integer(df$sales))) {
  df$average_price <- ifelse(!is.na(df$volume_clean) & !is.na(df$sales) & df$sales != 0,
                             (df$volume_clean * 1000) / df$sales, 
                             NA)
  
  average_price_mean <- mean(df$average_price, na.rm = TRUE)
  cat("Media calcolata per average_price :", average_price_mean, "\n")
  
  if (!is.na(average_price_mean)) {
    df$average_price[is.na(df$average_price)] <- average_price_mean
    cat("NA in 'average_price' sostituiti con la media.\n")
  } else {
    cat("Media di 'average_price' è NA, impossibile.\n")
  }
  
  cat("\nSommario 'average_price' dopo imputazione:\n")
  print(summary(df$average_price))
  cat("\nPrimi valori 'average_price':\n")
  print(head(df$average_price))
  
} else {
  warning("Colonne 'volume_clean' o 'sales' non trovate o non numeriche. Impossibile calcolare 'average_price'.")
}
## Media calcolata per average_price : 195.8766 
## NA in 'average_price' sostituiti con la media.
## 
## Sommario 'average_price' dopo imputazione:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   106.3   168.7   196.1   195.9   220.9   313.4 
## 
## Primi valori 'average_price':
## [1] 197.8313 167.5000 216.5385 196.9500 205.5941 160.7937
if ("sales" %in% names(df) && "listings" %in% names(df) && (is.numeric(df$sales) || is.integer(df$sales)) && (is.numeric(df$listings) || is.integer(df$listings))) {
  df$efficacia_annunci <- ifelse(!is.na(df$sales) & !is.na(df$listings) & df$listings > 0,
                                 df$sales / df$listings,
                                 NA)
  
  cat("\nSommario 'efficacia_annunci':\n")
  print(summary(df$efficacia_annunci)) 
  cat("\nPrimi valori 'efficacia_annunci':\n")
  print(head(df$efficacia_annunci))
  
} else {
  warning("Colonne 'sales' o 'listings' non trovate o non numeriche. Impossibile calcolare 'efficacia_annunci'.")
}
## 
## Sommario 'efficacia_annunci':
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.05014 0.08980 0.10963 0.11874 0.13492 0.38713 
## 
## Primi valori 'efficacia_annunci':
## [1] 0.05414220 0.06809584 0.10775607 0.11709602 0.11405985 0.10482529

— 7. Analisi condizionata

required_cols_7 <- c("city", "year", "month", "listings")
if (all(required_cols_7 %in% names(df))) {
  
  summary_listings_dplyr <- df %>%
    filter(!is.na(listings)) %>% 
    group_by(city, year, month) %>%
    summarise(
      Media_Listings = mean(listings), 
      DeviazioneStandard_Listings = if(n() >= 2) sd(listings) else NA_real_, 
      n = n(), 
      .groups = 'drop' 
    )
  
  print("Sommario Condizionato per Listings :")
  print(head(summary_listings_dplyr)) 
  
} else {
  missing_cols <- required_cols_7[!required_cols_7 %in% names(df)]
  warning(paste("Colonne richieste per l'analisi condizionata mancanti:", paste(missing_cols, collapse=", "), ". Sezione 7 saltata."))
}
## [1] "Sommario Condizionato per Listings :"
## # A tibble: 6 × 6
##   city      year month Media_Listings DeviazioneStandard_Listings     n
##   <chr>    <int> <int>          <dbl>                       <dbl> <int>
## 1 Beaumont  2010     1           1533                          NA     1
## 2 Beaumont  2010     2           1586                          NA     1
## 3 Beaumont  2010     3           1689                          NA     1
## 4 Beaumont  2010     4           1708                          NA     1
## 5 Beaumont  2010     5           1771                          NA     1
## 6 Beaumont  2010     6           1803                          NA     1

— 8. Creazione di visualizzazioni con ggplot2

cat("\n--- Altre visualizzazioni ---\n")
## 
## --- Altre visualizzazioni ---
required_cols_8 <- c("city", "median_price_clean", "sales", "month", "year", "year_month")

if(all(required_cols_8 %in% names(df))) {
  boxplot_sales_city <- ggplot(df, aes(x = city, y = sales)) +
      geom_boxplot(fill = "lightgreen", outlier.color = "darkgreen", na.rm = TRUE) +
      labs(title = "Distribuzione Valore Totale Vendite  per Città",
           x = "Città", y = "Valore Vendite") +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1))
  print(boxplot_sales_city)
  boxplot_sales_year <- ggplot(df, aes(x = factor(year), y = sales)) +
      geom_boxplot(fill = "orange", outlier.color = "red", na.rm = TRUE) +
      labs(title = "Distribuzione Valore Totale Vendite  per Anno",
           x = "Anno", y = "Valore Vendite")
  print(boxplot_sales_year)

  vendite_mensili <- df %>%
    filter(!is.na(sales)) %>%
    group_by(city, month) %>%
    summarise(TotaleVendite = sum(sales, na.rm = TRUE), .groups = 'drop')

  if(nrow(vendite_mensili) > 0) {
      stacked_barplot_sales_month_city <- ggplot(vendite_mensili, aes(x = factor(month), y = TotaleVendite, fill = city)) +
        geom_col(position = "stack") +
        labs(title = "Totale Vendite Mensiliper Città ",
             x = "Mese", y = "Totale Vendite", fill = "Città") +
        scale_x_discrete(limits = factor(1:12)) +
        theme_minimal() +
        theme(axis.text.x = element_text(angle = 45, hjust = 1))
      print(stacked_barplot_sales_month_city)
  }
  linechart_median_price_time_city <- ggplot(df, aes(x = year_month, y = median_price_clean, color = city)) +
      geom_line(na.rm = TRUE, size = 1, alpha=0.8) +
      labs(title = "Andamento Prezzo Mediano  nel Tempo per Città",
           x = "Data", y = "Prezzo Mediano ") +
      theme_minimal() +
      scale_x_date(date_breaks = "1 year", date_labels = "%Y")
  print(linechart_median_price_time_city)
} else {
    missing_cols <- required_cols_8[!required_cols_8 %in% names(df)]
    warning(paste("Colonne richieste per le visualizzazioni mancanti:", paste(missing_cols, collapse=", "), ". Sezione 8 saltata/parziale."))
}

## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

9. Conclusioni

Qualità dei Dati e Impatto Statistico:

Analisi Descrittiva:

Numero di Vendite (sales):

Numero di Annunci (listings):