L’obiettivo di questa analisi è rendere più efficiente il mercato immobiliare del Texas fornendo insight utili sui dati relativi alle vendite di immobili e verificare se gli annunci pubblicati risultano essere efficaci per finalizzare le vendite. Di seguito, alcune righe del dataset e i tipi di dati delle variabili:
## city year month sales volume median_price listings months_inventory
## 1 Beaumont 2010 1 83 14.162 163800 1533 9.5
## 2 Beaumont 2010 2 108 17.69 138200 1586 10
## 3 Beaumont 2010 3 182 28.701 122400 1689 10.6
## 4 Beaumont 2010 4 200 26.819 123200 1708 10.6
## 5 Beaumont 2010 5 202 28.833 123100 1771 10.9
## 6 Beaumont 2010 6 189 27.219 122800 1803 11.1
## 'data.frame': 240 obs. of 8 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 "14.162" "17.69" "28.701" "26.819" ...
## $ median_price : num 163800 138200 122400 123200 123100 ...
## $ listings : int 1533 1586 1689 1708 1771 1803 1857 1830 1829 1779 ...
## $ months_inventory: chr "9.5" "10" "10.6" "10.6" ...
## Funzione per calcolare l'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)
}
# Funzione per calcolare il coefficiente di variazione
CV <- function(x) {
return(sd(x)/mean(x)*100)
}
# Funzione per calcolare il valore mediano di una determinata classe (E' fuori dallo scope del corso, ma ho approfondito l'argomento e mi è tornata utile nell'analisi)
calcola_mediana_classe <- function(limiti_inferiori, frequenze, totale_frequenze) {
# Calcolo della posizione della mediana
posizione_mediana <- totale_frequenze / 2
# Calcolo la frequenza cumulativa
frequenze_cumulate <- cumsum(frequenze)
# Individuare la classe mediana
indice_classe_mediana <- which(frequenze_cumulate >= posizione_mediana)[1]
# Limite inferiore della classe mediana
L <- limiti_inferiori[indice_classe_mediana]
# Frequenza della classe mediana
f <- frequenze[indice_classe_mediana]
# Frequenza cumulativa della classe precedente
F <- ifelse(indice_classe_mediana == 1, 0, frequenze_cumulate[indice_classe_mediana - 1])
# Ampiezza della classe
w <- limiti_inferiori[indice_classe_mediana + 1] - limiti_inferiori[indice_classe_mediana]
# Calcolo della mediana usando la formula di interpolazione
mediana <- L + ((posizione_mediana - F) / f) * w
return(mediana)
}
# studio preliminare variabile city
table(city)
## city
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
unique(city)
## [1] "Beaumont" "Bryan-College Station" "Tyler"
## [4] "Wichita Falls"
gini.index(city)
## [1] 1
L’ indice di Gini per la variabile city è uguale ad 1 ed indica che city ha eterogeneità massima. Dunque, si può dedurre con questo indice che le frequenze saranno equamente distribuite tra tutti i valori possibili della variabile
# studio preliminare variabile year
# il range degli anni va dal 2010 al 2014, dunque ha ampiezza 4 anni
range(year)
## [1] 2010 2014
gini.index(year)
## [1] 1
n_year_lenght <- length(year)
# l'indice di Gini indicava che la distribuzione è equamente distribuita. Dunque, le frequenze sono uguali per tutte le classi
year_distr_freq <- as.data.frame(
cbind(
ni=table(year),
fi=table(year)/n_year_lenght,
Ni=cumsum(table(year)),
Fi=cumsum(table(year))/n_year_lenght
)
)
print(year_distr_freq)
## ni fi Ni Fi
## 2010 48 0.2 48 0.2
## 2011 48 0.2 96 0.4
## 2012 48 0.2 144 0.6
## 2013 48 0.2 192 0.8
## 2014 48 0.2 240 1.0
# studio preliminare variabile month
table(month)
## month
## 1 2 3 4 5 6 7 8 9 10 11 12
## 20 20 20 20 20 20 20 20 20 20 20 20
gini.index(month)
## [1] 1
n_month_lenght <- length(month)
month_distr_freq <- as.data.frame(
cbind(
ni=table(month),
fi=table(month)/n_month_lenght,
Ni=cumsum(table(month)),
Fi=cumsum(table(month))/n_month_lenght
)
)
print(month_distr_freq)
## ni fi Ni Fi
## 1 20 0.08333333 20 0.08333333
## 2 20 0.08333333 40 0.16666667
## 3 20 0.08333333 60 0.25000000
## 4 20 0.08333333 80 0.33333333
## 5 20 0.08333333 100 0.41666667
## 6 20 0.08333333 120 0.50000000
## 7 20 0.08333333 140 0.58333333
## 8 20 0.08333333 160 0.66666667
## 9 20 0.08333333 180 0.75000000
## 10 20 0.08333333 200 0.83333333
## 11 20 0.08333333 220 0.91666667
## 12 20 0.08333333 240 1.00000000
L’ indice di Gini per la variabile month è uguale ad 1 ed indica che year ha eterogeneità massima. Dunque, si può dedurre con questo indice che le frequenze saranno equamente distribuite tra tutti i valori possibili della variabile
#studio preliminare variabile sales
range(sales)
## [1] 79 423
mean(sales)
## [1] 192.2917
quantile(sales)
## 0% 25% 50% 75% 100%
## 79.0 127.0 175.5 247.0 423.0
IQR(sales)
## [1] 120
varianza_sales <- var(sales)
print(varianza_sales)
## [1] 6344.3
deviazione_standard_sales <- sd(sales)
print(deviazione_standard_sales)
## [1] 79.65111
CV(sales)
## [1] 41.42203
n <- length(sales)
sales_length_cl <- cut(sales, breaks = seq(min(sales), max(sales), by = 30), include.lowest = TRUE)
frequenze <- c(table(sales))
# Ottieni i break points
breaks <- seq(min(sales), max(sales), by = 30)
# I limiti inferiori sono i break points tranne l'ultimo
limiti_inferiori <- breaks[-length(breaks)]
totale_frequenze <- sum(frequenze)
#
#la classe modale è la prima, ovvero quella da [79,129]
table(sales_length_cl)
## sales_length_cl
## [79,109] (109,139] (139,169] (169,199] (199,229] (229,259] (259,289] (289,319]
## 33 42 40 32 21 19 20 13
## (319,349] (349,379] (379,409]
## 8 8 3
sales_distr_freq <- as.data.frame(
cbind(
ni=table(sales_length_cl),
fi=table(sales_length_cl)/n,
Ni=cumsum(table(sales_length_cl)),
Fi=cumsum(table(sales_length_cl))/n
)
)
#calcolo del valore mediano della classe - utile per verificare se l'indice di asimmetria risulta coerente con media>mediana>moda
mediana <- calcola_mediana_classe(limiti_inferiori, frequenze, totale_frequenze)
print(mediana)
## 175
## NA
# calcolo degli indici di forma - assimetria-curtosi
# l'assimetria è maggiore di 0, questo vuol dire che vi è un'asimmetria positiva dove media>moda>mediana (verificato). Sono presenti più modalità basse
skewness(sales)
## [1] 0.718104
#la curtosi negativa indica che vi è una distribuzione platicurtica, ovvero il grafico avrà una forma più appiattita
kurtosis(sales)-3
## [1] -0.3131764
# studio preliminare variabile volume
# si potrebbe rapportare agli anni per evidenziare come è aumentato nel tempo con un line chart
# Questa variabile risulta essere un char anche se contiene solo valori numerici decimali
# Quindi verrà eseguito una conversione in float e saranno individuati eventuali valori nulli o diversi da numeri
# Calcoliamo il numero di valori nulli
num_nulls_volume <- sum(is.na(volume_float))
cat("Numero di valori nulli trovati:", num_nulls_volume, "\n")
## Numero di valori nulli trovati: 0
range(volume_float)
## [1] 8.166 83.547
mean(volume_float)
## [1] 31.00519
quantile(volume_float)
## 0% 25% 50% 75% 100%
## 8.1660 17.6595 27.0625 40.8930 83.5470
IQR(volume_float)
## [1] 23.2335
varianza_volume <- var(volume_float)
print(varianza_volume)
## [1] 277.2707
deviazione_standard_volume <- sd(volume_float)
print(deviazione_standard_volume)
## [1] 16.65145
CV(volume_float)
## [1] 53.70536
n_volume_float <- length(volume_float)
volume_length_cl <- cut(volume_float, breaks = seq(min(volume_float), max(volume_float), by = 10), include.lowest = TRUE)
frequenze_volume <- c(table(volume_float))
# Ottieni i break points
breaks_volume <- seq(min(volume_float), max(volume_float), by = 10)
# I limiti inferiori sono i break points tranne l'ultimo
limiti_inferiori <- breaks[-length(breaks_volume)]
totale_frequenze_volume <- sum(frequenze_volume)
#
#la classe modale è la prima, ovvero quella da [79,129]
table(volume_length_cl)
## volume_length_cl
## [8.17,18.2] (18.2,28.2] (28.2,38.2] (38.2,48.2] (48.2,58.2] (58.2,68.2]
## 66 57 48 27 22 12
## (68.2,78.2]
## 6
volume_distr_freq <- as.data.frame(
cbind(
ni=table(volume_length_cl),
fi=table(volume_length_cl)/n_volume_float,
Ni=cumsum(table(volume_length_cl)),
Fi=cumsum(table(volume_length_cl))/n_volume_float
)
)
print(volume_distr_freq)
## ni fi Ni Fi
## [8.17,18.2] 66 0.27500000 66 0.2750000
## (18.2,28.2] 57 0.23750000 123 0.5125000
## (28.2,38.2] 48 0.20000000 171 0.7125000
## (38.2,48.2] 27 0.11250000 198 0.8250000
## (48.2,58.2] 22 0.09166667 220 0.9166667
## (58.2,68.2] 12 0.05000000 232 0.9666667
## (68.2,78.2] 6 0.02500000 238 0.9916667
# calcolo degli indici di forma
# Vi è un'asimmetria positiva, quindi sono più frequenti modalità basse
skewness(volume_float)
## [1] 0.884742
# la curtosi risulta essere maggiore di 0 e quindi leptocurtica. Il grafico avrà una forma più allungata rispetto alla normale.Tuttavia, è vicino allo zero, quindi non sarà molto accentuata
kurtosis(volume_float)-3
## [1] 0.176987
#studio preliminare variabile median_price
# si potrebbe rapportare agli anni per vedere come è aumentato nel tempo con un line chart
range(median_price)
## [1] 73800 180000
mean(median_price)
## [1] 132665.4
quantile(median_price)
## 0% 25% 50% 75% 100%
## 73800 117300 134500 150050 180000
IQR(median_price)
## [1] 32750
varianza_median_price <- var(median_price)
print(varianza_median_price)
## [1] 513572983
deviazione_standard_median_price <- sd(median_price)
print(deviazione_standard_median_price)
## [1] 22662.15
CV(median_price)
## [1] 17.08218
n <- length(median_price)
median_price_length_cl <- cut(median_price, breaks = seq(min(median_price), max(median_price), by = 25000), include.lowest = TRUE)
frequenze_median_price <- c(table(median_price))
# Ottieni i break points
breaks_median_price <- seq(min(median_price), max(median_price), by = 25000)
# I limiti inferiori sono i break points tranne l'ultimo
limiti_inferiori_median_price <- breaks_median_price[-length(breaks_median_price)]
totale_frequenze_median_price <- sum(frequenze_median_price)
#
#la classe modale è la prima, ovvero quella da [79,129]
table(median_price_length_cl)
## median_price_length_cl
## [7.38e+04,9.88e+04] (9.88e+04,1.24e+05] (1.24e+05,1.49e+05] (1.49e+05,1.74e+05]
## 22 56 96 63
median_price_distr_freq <- as.data.frame(
cbind(
ni=table(median_price_length_cl),
fi=table(median_price_length_cl)/n,
Ni=cumsum(table(median_price_length_cl)),
Fi=cumsum(table(median_price_length_cl))/n
)
)
print(median_price_distr_freq)
## ni fi Ni Fi
## [7.38e+04,9.88e+04] 22 0.09166667 22 0.09166667
## (9.88e+04,1.24e+05] 56 0.23333333 78 0.32500000
## (1.24e+05,1.49e+05] 96 0.40000000 174 0.72500000
## (1.49e+05,1.74e+05] 63 0.26250000 237 0.98750000
#calcolo degli indici di forma
# asimmetria negativa indica che sono più frequenti modalità alte e che la media> mediana>moda. La "campana" sarà traslata verso destra
skewness(median_price)
## [1] -0.3645529
# risulta negativa e questo indica che è presente una distribuzione platicurtica dove la campana risulterà più appiattita
kurtosis(median_price)-3
## [1] -0.6229618
#studio preliminare variabile listings
range(listings)
## [1] 743 3296
mean(listings)
## [1] 1738.021
quantile(listings)
## 0% 25% 50% 75% 100%
## 743.0 1026.5 1618.5 2056.0 3296.0
IQR(listings)
## [1] 1029.5
varianza_listings <- var(listings)
print(varianza_listings)
## [1] 566569
deviazione_standard_listings <- sd(listings)
print(deviazione_standard_listings)
## [1] 752.7078
CV(listings)
## [1] 43.30833
n_listings <- length(listings)
listings_length_cl <- cut(listings, breaks = seq(min(listings), max(listings), by = 500), include.lowest = TRUE)
frequenze_listings <- c(table(listings))
# Ottieni i break points
breaks_listings <- seq(min(listings), max(listings), by = 500)
# I limiti inferiori sono i break points tranne l'ultimo
limiti_inferiori_listings <- breaks_listings[-length(breaks_listings)]
totale_frequenze_listings <- sum(frequenze_listings)
#
table(listings_length_cl)
## listings_length_cl
## [743,1.24e+03] (1.24e+03,1.74e+03] (1.74e+03,2.24e+03] (2.24e+03,2.74e+03]
## 74 83 23 15
## (2.74e+03,3.24e+03]
## 38
listings_distr_freq <- as.data.frame(
cbind(
ni=table(listings_length_cl),
fi=table(listings_length_cl)/n_listings,
Ni=cumsum(table(listings_length_cl)),
Fi=cumsum(table(listings_length_cl))/n_listings
)
)
print(listings_distr_freq)
## ni fi Ni Fi
## [743,1.24e+03] 74 0.30833333 74 0.3083333
## (1.24e+03,1.74e+03] 83 0.34583333 157 0.6541667
## (1.74e+03,2.24e+03] 23 0.09583333 180 0.7500000
## (2.24e+03,2.74e+03] 15 0.06250000 195 0.8125000
## (2.74e+03,3.24e+03] 38 0.15833333 233 0.9708333
# calcolo degli indici di forma
# si ha un'asimmetria positiva
skewness(listings)
## [1] 0.6494982
# si ha una distribuzione leptocurtica poichè è minore di 0
kurtosis(listings)-3
## [1] -0.79179
#studio preliminare variabile months_inventory
#convertiamo in float da string la variabile months inventory per poter calcolare i vari indici
months_inventory_float <- as.numeric(months_inventory)
# Calcoliamo il numero di valori nulli
num_nulls_months_inventory <- sum(is.na(months_inventory_float))
cat("Numero di valori nulli trovati:", num_nulls_months_inventory, "\n")
## Numero di valori nulli trovati: 0
range(months_inventory_float)
## [1] 3.4 14.9
mean(months_inventory_float)
## [1] 9.1925
quantile(months_inventory_float)
## 0% 25% 50% 75% 100%
## 3.40 7.80 8.95 10.95 14.90
IQR(months_inventory_float)
## [1] 3.15
varianza_months_inventory <- var(months_inventory_float)
print(varianza_months_inventory)
## [1] 5.306889
deviazione_standard_months_inventory <- sd(months_inventory_float)
print(deviazione_standard_months_inventory)
## [1] 2.303669
CV(months_inventory_float)
## [1] 25.06031
n_months_inventory <- length(months_inventory_float)
months_inventory_length_cl <- cut(months_inventory_float, breaks = seq(min(months_inventory_float), max(months_inventory_float), by = 1.5), include.lowest = TRUE)
frequenze_months_inventory <- c(table(months_inventory_float))
# Ottieni i break points
breaks_months_inventory <- seq(min(months_inventory_float), max(months_inventory_float), by = 1.5)
# I limiti inferiori sono i break points tranne l'ultimo
limiti_inferiori_months_inventory <- breaks_months_inventory[-length(months_inventory_float)]
totale_frequenze_months_inventory <- sum(frequenze_months_inventory)
#
table(months_inventory_length_cl)
## months_inventory_length_cl
## [3.4,4.9] (4.9,6.4] (6.4,7.9] (7.9,9.4] (9.4,10.9] (10.9,12.4]
## 10 13 49 73 35 42
## (12.4,13.9]
## 13
months_inventory_distr_freq <- as.data.frame(
cbind(
ni=table(months_inventory_length_cl),
fi=table(months_inventory_length_cl)/n_months_inventory,
Ni=cumsum(table(months_inventory_length_cl)),
Fi=cumsum(table(months_inventory_length_cl))/n_months_inventory
)
)
print(months_inventory_distr_freq)
## ni fi Ni Fi
## [3.4,4.9] 10 0.04166667 10 0.04166667
## (4.9,6.4] 13 0.05416667 23 0.09583333
## (6.4,7.9] 49 0.20416667 72 0.30000000
## (7.9,9.4] 73 0.30416667 145 0.60416667
## (9.4,10.9] 35 0.14583333 180 0.75000000
## (10.9,12.4] 42 0.17500000 222 0.92500000
## (12.4,13.9] 13 0.05416667 235 0.97916667
skewness(months_inventory_float)
## [1] 0.04097527
kurtosis(months_inventory_float)-3
## [1] -0.1744475
La variabile con maggiore variabilità è il volume che presenta valori che distano dalla media in media del 53%. Ovvero, che la deviazione standard è il 53% della media. Ho usato il coefficiente di variazione per misurare la variabilità perchè questo indice non viene influenzato dall’ordine di grandezza delle variabili
# Variabili con maggiore variabilità e asimmetria
# Considerazioni sulla variabilità:
CV(year)
## [1] 0.07043584
CV(month)
## [1] 53.21949
CV(sales)
## [1] 41.42203
CV(volume_float)
## [1] 53.70536
CV(median_price)
## [1] 17.08218
CV(listings)
## [1] 43.30833
CV(months_inventory_float)
## [1] 25.06031
skewness(year)
## [1] 0
skewness(month)
## [1] 0
skewness(sales)
## [1] 0.718104
skewness(volume_float)
## [1] 0.884742
skewness(median_price)
## [1] -0.3645529
skewness(listings)
## [1] 0.6494982
skewness(months_inventory_float)
## [1] 0.04097527
n <- length(sales)
sales_length_cl <- cut(sales, breaks = seq(min(sales), max(sales), by = 50), include.lowest = TRUE)
frequenze <- table(sales_length_cl)
#la classe modale è la prima, ovvero quella da [79,129]
sales_distr_freq <- data.frame(
sales_classes = names(frequenze),
ni = as.numeric(frequenze),
fi = as.numeric(frequenze) / n,
Ni = cumsum(as.numeric(frequenze)),
Fi = cumsum(as.numeric(frequenze)) / n
)
# Ottieni l'ordine delle classi dalle righe di sales_distr_freq
ordered_classes <- levels(sales_length_cl)
# Converti sales_classes in un fattore con i livelli ordinati
sales_classes <- factor(sales_length_cl, levels = ordered_classes)
ggplot(sales_distr_freq, aes(x = sales_classes, y = ni)) +
geom_bar(stat = "identity", fill = "steelblue") +
labs(title = "Distribuzione delle vendite", x = "Classe sales", y = "Frequenza assoluta") +
theme_minimal()
gini.index(sales_distr_freq)
## [1] 0.7600977
Nota: Dato che tutti questi dati sono equamente distribuiti, il calcolo delle probabilità è risultato semplice, eseguendo l’operazione 1/n dove n è il numero totale di valori possibili per quella variabile
# calcola `prezzo_medio` espressa in centinaia di migliaia di dollari. Es:150k
dati_immobiliari_texas <- dati_immobiliari_texas %>%
mutate(
prezzo_medio_k = (volume_float / sales) * 1000
)
head(dati_immobiliari_texas)
## city year month sales volume median_price listings months_inventory
## 1 Beaumont 2010 1 83 14.162 163800 1533 9.5
## 2 Beaumont 2010 2 108 17.69 138200 1586 10
## 3 Beaumont 2010 3 182 28.701 122400 1689 10.6
## 4 Beaumont 2010 4 200 26.819 123200 1708 10.6
## 5 Beaumont 2010 5 202 28.833 123100 1771 10.9
## 6 Beaumont 2010 6 189 27.219 122800 1803 11.1
## prezzo_medio_k
## 1 170.6265
## 2 163.7963
## 3 157.6978
## 4 134.0950
## 5 142.7376
## 6 144.0159
# valutazione efficienza annunci
# calcolo delle correlazioni tra le due variabili - argomento non svolto ma ho cercato online su come farlo
# Le due variabili risultano fortemente correlate
correlazione <- cor(dati_immobiliari_texas$listings, months_inventory_float)
print(correlazione)
## [1] 0.7351499
percent_annunci_efficaci <- dati_immobiliari_texas$sales / dati_immobiliari_texas$listings * 100
# CV(percent_annunci_efficaci) # Assicurati che CV sia definito o rimuovilo se non necessario
median(percent_annunci_efficaci)
## [1] 10.96268
dati_immobiliari_texas <- dati_immobiliari_texas %>%
mutate(
percentuale_annunci_efficaci = percent_annunci_efficaci
)
# Crea il grafico base
p <- ggplot(dati_immobiliari_texas, aes(x = listings, y = months_inventory_float)) +
geom_point() +
labs(title = "Relazione tra Numero di Annunci e Tempo di Vendita",
x = "Numero di Annunci",
y = "Tempo di Vendita (mesi)")
# Assicurati che `step` sia definito
step <- 1 # o un altro valore numerico appropriato
# Aggiungi scala continua all'asse Y
p <- p + scale_y_continuous(limits = c(min(months_inventory_float, na.rm = TRUE), max(months_inventory_float, na.rm = TRUE)),
breaks = seq(min(months_inventory_float, na.rm = TRUE), max(months_inventory_float, na.rm = TRUE), by = step))
# evidenziazione punti di interesse
p <- p +
geom_point(data = data.frame(listings = c(1500, 3000), months_inventory_float = c(9, 13.5)),
aes(x = listings, y = months_inventory_float),
color = "red", size = 3) +
# Annotazioni per spiegare i punti chiave
annotate("text", x = 1500, y = 9, label = "9 mesi", vjust = -1) +
annotate("text", x = 3000, y = 13.5, label = "13.5 mesi", vjust = -1)
# Visualizza il grafico
print(p)
# Raggruppare i dati per città, anno e mese e sommare le vendite
vendite_per_mese <- dati_immobiliari_texas %>%
group_by(city, year, month) %>%
summarise(total_sales = sum(sales, na.rm = TRUE), .groups = "keep") %>%
ungroup()
print(vendite_per_mese)
## # A tibble: 240 × 4
## city year month total_sales
## <chr> <int> <int> <int>
## 1 Beaumont 2010 1 83
## 2 Beaumont 2010 2 108
## 3 Beaumont 2010 3 182
## 4 Beaumont 2010 4 200
## 5 Beaumont 2010 5 202
## 6 Beaumont 2010 6 189
## 7 Beaumont 2010 7 164
## 8 Beaumont 2010 8 174
## 9 Beaumont 2010 9 124
## 10 Beaumont 2010 10 150
## # ℹ 230 more rows
ggplot(data = vendite_per_mese, aes(x = month, y = total_sales, color = city, group = interaction(city, year))) +
geom_line(lwd = 1) +
geom_point(size = 2) +
facet_wrap(~ year, ncol = 1, scales = "free_y") +
labs(title = "Vendite Mensili per Città e Anno",
x = "Mese",
y = "Vendite Totali") +
theme_minimal() +
scale_x_continuous(breaks = 1:12, labels = month.abb) +
scale_color_discrete(name = "Città")
# Identificare il mese con il massimo delle vendite per ciascun anno
mese_max_vendite <- vendite_per_mese %>%
group_by(year) %>%
filter(total_sales == max(total_sales)) %>%
ungroup()
print(mese_max_vendite)
## # A tibble: 5 × 4
## city year month total_sales
## <chr> <int> <int> <int>
## 1 Bryan-College Station 2013 7 402
## 2 Tyler 2010 4 316
## 3 Tyler 2011 6 313
## 4 Tyler 2012 7 322
## 5 Tyler 2014 6 423
# I mesi dove si è venduto di più negli anni risultano essere luglio e giugno nella città di tyler
### Il mese dove si è venduto di più negli anni
# Raggruppare i dati per mese e calcolare la media delle vendite
media_vendite_per_mese <- dati_immobiliari_texas %>%
group_by(month) %>%
summarise(media_vendite = mean(sales, na.rm = TRUE),
deviazione_standard = sd(sales, na.rm = TRUE)) %>%
ungroup()
print(media_vendite_per_mese)
## # A tibble: 12 × 3
## month media_vendite deviazione_standard
## <int> <dbl> <dbl>
## 1 1 127. 43.4
## 2 2 141. 51.1
## 3 3 189. 59.2
## 4 4 212. 65.4
## 5 5 239. 83.1
## 6 6 244. 95.0
## 7 7 236. 96.3
## 8 8 231. 79.2
## 9 9 182. 72.5
## 10 10 180. 75.0
## 11 11 157. 55.5
## 12 12 169. 60.7
media_vendite_per_mese <- media_vendite_per_mese %>%
mutate(Legenda = "Deviazione Standard")
ggplot(data = media_vendite_per_mese, aes(x = month, y = media_vendite)) +
geom_line(color = "blue", lwd = 1) +
geom_point(color = "blue", size = 2) +
geom_errorbar(
aes(
ymin = media_vendite - deviazione_standard,
ymax = media_vendite + deviazione_standard,
color = Legenda
),
width = 0.2
) +
labs(
title = "Media delle Vendite Mensili con Deviazione Standard",
x = "Mese",
y = "Media Vendite"
) +
theme_minimal() +
scale_x_continuous(breaks = 1:12, labels = month.abb) +
scale_color_manual(values = c("Deviazione Standard" = "gray")) +
guides(color = guide_legend(
override.aes = list(
shape = NA,
size = 3,
linetype = 1,
color = "gray",
alpha = 1,
linewidth = 2
)
)) +
theme(legend.title = element_blank())
# Identificare il mese con la media di vendite più alta
mese_max_media_vendite <- media_vendite_per_mese %>%
filter(media_vendite == max(media_vendite))
print(mese_max_media_vendite)
## # A tibble: 1 × 4
## month media_vendite deviazione_standard Legenda
## <int> <dbl> <dbl> <chr>
## 1 6 244. 95.0 Deviazione Standard
# Calcolare la media delle vendite per città
media_vendite_citta <- dati_immobiliari_texas %>%
group_by(city) %>%
summarise(media_vendite = mean(sales, na.rm = TRUE), .groups = "keep") %>%
ungroup()
print(media_vendite_citta)
## # A tibble: 4 × 2
## city media_vendite
## <chr> <dbl>
## 1 Beaumont 177.
## 2 Bryan-College Station 206.
## 3 Tyler 270.
## 4 Wichita Falls 116.
media_vendite_citta_anno <- dati_immobiliari_texas %>%
group_by(city, year) %>%
summarise(media_vendite = mean(sales, na.rm = TRUE), .groups = "keep") %>%
ungroup()
ggplot(data = media_vendite_citta_anno, aes(x = as.factor(year), y = media_vendite, fill = city)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Media delle Vendite per Anno e Città",
x = "Anno",
y = "Media Vendite",
fill = "Città") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#Confrontare questo grafico con i valori non pesati
# grafico per comprendere quali città abbiano eseguito delle vendite con valore economico più alto negli anni. Quindi, pesando il numero di vendite totali con il prezzo mediano di ciascuna vendita
weighted_average_sales <- sum(sales * median_price) / sum(sales)
print(weighted_average_sales)
## [1] 138177.6
ggplot(dati_immobiliari_texas, aes(x = factor(year), y = sales, fill = city)) +
geom_bar(stat = "identity", position = "dodge") +
geom_hline(yintercept = weighted_average_sales, linetype="dashed", color = "red", linewidth=1) +
ylim(0, max(sales) * 1.2) +
labs(title = "Numero di Vendite per Città e Anno con Media Ponderata",
x = "Anno",
y = "Numero di Vendite") +
theme_minimal()
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_hline()`).
# Visualizzare la città con la media di vendite più alta
citta_top <- media_vendite_citta %>%
filter(media_vendite == max(media_vendite))
print(citta_top)
## # A tibble: 1 × 2
## city media_vendite
## <chr> <dbl>
## 1 Tyler 270.
# La città che in media ha venduto di più negli anni è stata Tyler
# BoxPlot
ggplot(data = dati_immobiliari_texas, aes(x = city, y = median_price)) +
geom_boxplot(fill = "lightblue") +
labs(title = "Distribuzione del Prezzo Mediano per Città",
x = "Città",
y = "Prezzo Mediano") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Potremmo riassumere l’analisi con le seguenti conclusioni
In sintesi, i dati evidenziano significative differenze tra le città del Texas in termini di performance di vendita, distribuzione temporale e variabilità dei valori di vendita. Tyler emerge come il leader stabile, mentre Bryan-College-Station sta guadagnando terreno, e Wichita Falls presenta la performance più debole.