## ── 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
| 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.
| 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à .
| 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.
| 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.
| 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Ã
| 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
| maggio-Agosto |
Le vendite si concentrano prevalentemente nei mesi
estivi, con un picco tra maggio e luglio, tipico dell’andamento
stagionale del mercato immobiliare. |
```