Analizzo le variabili presenti nel dataset Real Texas
Estate.csv
L’obiettivo è identificare il tipo di ciascuna variabile, descriverne la
natura statistica e commentare sul tipo di analisi applicabile.
# Carico il dataset
dati <- read.csv("realestate_texas.csv")
#View(realestate_texas) # visuallizzo il dataset per intero
# Visualizzo le prime 5 righe per capire la struttura
head(dati,5)
## 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.690 138200 1586 10.0
## 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
Il data set contiene: 240 osservazioni di 8 variabili.
str(dati) #mostro la struttura dei dati
## '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 : num 14.2 17.7 28.7 26.8 28.8 ...
## $ median_price : num 163800 138200 122400 123200 123100 ...
## $ 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 ...
dim(dati) #mostro la dimensione del dataset n.righe e n.colonne
## [1] 240 8
Nella seguente tabella sono riportate le variabili presenti nel dataset, la loro tipologia statistica e il tipo di analisi che si può eseguire.
Variabile CITY: (città di riferimento)
Eseguirò le frequenze assolute e relative per generare le tabelle di contingenza. Essendo una variabile categorica non ha senso calcolare media, mediana. Valuterò con la moda qual è la città che ha più osservazioni nel database.
Variabili YEAR e MONTHS:
le userò come time series per vedere come si comportano le altre
variabili nel tempo
VARIABILI: SALES , VOLUME e MEDIAN_PRICE :
Valuterò tutti gli indici di posizione. Controllerò il numero totale di
vendite per ogni anno, la media, la vendità maggiore/minore, si potrà
controllare con l’utilizzo di city anche dove è stata registrata la
vendita maggiore e minore e il numero di più alto di vendite. Valutare
l’utilizzo di media geometrica.
VARIABILI: LISTING E MONTHS_INVENTORY:
Valuterò gli indici di posizione per identidicare le zone dove ci sono
più annunci attivi ( percentuali, frequenze). Si può effettuare un
calcolo di probabilità per verificare qual è la probabilità che per una
x città tutte le inserzioni vengano vendute nell’arco di x mesi.
#dataframe con nomi e tipi di variabili
tabella_var <- data.frame(
Variabile = c("city", "year", "month", "sales", "volume",
"median_price", "listings", "months_inventory"),
Tipo = c("Qualitativa nominale (categorica)",
"Quantitativa discreta (temporale)",
"Quantitativa discreta (temporale)",
"Quantitativa discreta",
"Quantitativa continua",
"Quantitativa continua",
"Quantitativa discreta",
"Quantitativa continua"),
Indici_posizione = c("Moda","Media, Mediana, Moda,(pocointerpretabili)","Media, Mediana, Moda (poco interpretabili)","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda","Media, Mediana, Moda"),
Indici_dispersione = c("Frequenze, percentuali",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range",
"Varianza, Deviazione standard, Range"),
Analisi = c("Grafici a barre, tabelle di contingenza","Analisi temporali, trend, serie storiche","Analisi temporali, trend, serie storiche",
"Analisi descrittive, regressione, correlazione","Analisi descrittive, regressione, correlazione","Analisi temporali, regressione, trend di prezzo","Analisi descrittive, correlazione con sales","Analisi temporali, equilibrio domanda/offerta"))
#mostro la tabella
knitr::kable(tabella_var, caption = "Tabella 1: Tipologia, indici e analisi per ciascuna variabile")
| Variabile | Tipo | Indici_posizione | Indici_dispersione | Analisi |
|---|---|---|---|---|
| city | Qualitativa nominale (categorica) | Moda | Frequenze, percentuali | Grafici a barre, tabelle di contingenza |
| year | Quantitativa discreta (temporale) | Media, Mediana, Moda,(pocointerpretabili) | Varianza, Deviazione standard, Range | Analisi temporali, trend, serie storiche |
| month | Quantitativa discreta (temporale) | Media, Mediana, Moda (poco interpretabili) | Varianza, Deviazione standard, Range | Analisi temporali, trend, serie storiche |
| sales | Quantitativa discreta | Media, Mediana, Moda | Varianza, Deviazione standard, Range | Analisi descrittive, regressione, correlazione |
| volume | Quantitativa continua | Media, Mediana, Moda | Varianza, Deviazione standard, Range | Analisi descrittive, regressione, correlazione |
| median_price | Quantitativa continua | Media, Mediana, Moda | Varianza, Deviazione standard, Range | Analisi temporali, regressione, trend di prezzo |
| listings | Quantitativa discreta | Media, Mediana, Moda | Varianza, Deviazione standard, Range | Analisi descrittive, correlazione con sales |
| months_inventory | Quantitativa continua | Media, Mediana, Moda | Varianza, Deviazione standard, Range | Analisi temporali, equilibrio domanda/offerta |
Calcola Indici di posizione, variabilità e forma per tutte le variabili per le quali ha senso farlo, per le altre crea una distribuzione di frequenza. Infine, commenta tutto brevemente.
GLI INDICI DI POSIZIONE VERRANNO CALCOLATI PER LE VARIABILI
:
SALES, VOLUME , MEDIAN_PRICE, LISTING, MONTHS_INVENTORY
LA VARIABILITA’ VERRA’ CALCOLATA PER LE VARIABILI:
SALES, VOLUME, MEDIAN_PRICE, LISTING, MONTHS_INVENTORY E
CITY
ANALIZZERO’ LA FORMA DI DISTRIBUZIONE DELLE VARIABILI:
SALES, VOLUME, MEDIAN_PRICE, LISTING E MONTHS_INVENTORY
La forma di distribuzione ha senso svolgerla per variabili quantitative (discrete o continue).
LA DISTRIBUZIONE DI FREQUENZA VERRA’ FATTA PER LE VARIABILI:
CITY, YEAR. MONTHS.
Potrebbe essere svolta per tutte le variabili. Se le osservazioni sono molte come nel nostro database la distribuzione di frequenze genera tabelle molto lunghe e difficile lettura.
Dal momento che il database contiene numerose osservazioni adotterò due strategie. 1) Valuterei di fare una divisione in classi se le osservazioni dovessero diventare numerose. 2) Passerei al calcolo degli inidici di posizione, variabilità e forma.
Per la variabile city calcolo la distribuzione di frequenza e le relative tabelle di contingenza, la moda e l’indice di Gini.
La variabilie city ha 4 città e tutte le modalità hanno la stessa frequenza assoluta 60 osservazioni per ogni città quindi si dice tetramodale. Ogni modalità ha lo stesso num di asservazioni: 60.
Per le variabili su scala nominale categorica come city non ha senso calcolare le frequenze cumulative. Fossero state variabili ordinali o quantitative allora si.
il valore dell’indice di Gini normalizzato è 1 #Come già visto in precedenza dalle frequenze n.60 per ogni modalita(città), le unità statistiche sono distribuite equamente tra tutte le modalità della variabile qualitativa city. GINI=1 SIGNIFICA ETEROGENEITA’, gruppo ben distribuito.
#preparo il dataset
attach(dati) # uso attach per poter estrarre più facilimente le colonne di riferimento e richiamare le mie variabili
table(city)
## city
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
N<-dim(dati)[1] #corrisponde al n.di osservazioni 240
#distribuzione di frequenze
table(dati["city"]) # oppure table(city) visto che ho usato attach
## city
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
freq_ass_city<-table(dati$city)
freq_rel_city<-table(city)/N
freq_ass_city
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
freq_rel_city #per mostrare le tab di contingenza
## city
## Beaumont Bryan-College Station Tyler
## 0.25 0.25 0.25
## Wichita Falls
## 0.25
#per combiare freq ass e freq rel uso cbind
distr_freq_city<-cbind(freq_ass_city,freq_rel_city)
distr_freq_city
## freq_ass_city freq_rel_city
## Beaumont 60 0.25
## Bryan-College Station 60 0.25
## Tyler 60 0.25
## Wichita Falls 60 0.25
#trasformo il tutto in dataframe per migliore visibilità
distr_freq_city<-as.data.frame(cbind(freq_ass_city,freq_rel_city))
#Indice di Gini: non esiste una funzione specifica. quindi creo la mia funzione
gini_index_city <- function(city){
ni=freq_ass_city
fi=freq_rel_city
fi2=freq_rel_city^2
J=length(table(city))
gini=1-sum(fi2)
gini.norm=gini/((J-1)/J)
return(gini.norm)
}
gini_index_city(city)
## [1] 1
Le variabili temporali year e month possono essere analizzate tramite frequenze assolute e relative per valutare come cambia il dataset nel tempo. Non verranno fatte le frequenze cumulative perchè anni e mesi sono valori di eventi temporali distinti.
Gli indici di posizione e di variabilità possono essere poco informativi. Gli indici di forma non hanno significato per variabili temporali discrete.
attach(dati)
## The following objects are masked from dati (pos = 3):
##
## city, listings, median_price, month, months_inventory, sales,
## volume, year
#Numero totale osservazioni
N<-dim(dati)[1]
table(year)
## year
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
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
#freq assolute
ni_year<-table(year)
ni_month<-table(month)
#freq relative
fi_year<-table(year)/N
fi_month<-table(month)/N
#data frame
distr_year<-as.data.frame(cbind(ni_year,fi_year))
distr_month<-as.data.frame(cbind(ni_month,fi_month))
print(distr_year)
## ni_year fi_year
## 2010 48 0.2
## 2011 48 0.2
## 2012 48 0.2
## 2013 48 0.2
## 2014 48 0.2
print(distr_month)
## ni_month fi_month
## 1 20 0.08333333
## 2 20 0.08333333
## 3 20 0.08333333
## 4 20 0.08333333
## 5 20 0.08333333
## 6 20 0.08333333
## 7 20 0.08333333
## 8 20 0.08333333
## 9 20 0.08333333
## 10 20 0.08333333
## 11 20 0.08333333
## 12 20 0.08333333
View(distr_month)
View(distr_year)
# Frequenze assolute e relative
distr_year <- data.frame(
Year = names(ni_year),
ni_year = as.numeric(ni_year),
fi_year = round(as.numeric(fi_year), 3)
)
distr_month <- data.frame(
Month = names(ni_month),
ni_month = as.numeric(ni_month),
fi_month = round(as.numeric(fi_month), 3)
)
# Visualizzazione in RMarkdown
library(knitr)
kable(distr_year, caption = "Distribuzione frequenze per Year")
| Year | ni_year | fi_year |
|---|---|---|
| 2010 | 48 | 0.2 |
| 2011 | 48 | 0.2 |
| 2012 | 48 | 0.2 |
| 2013 | 48 | 0.2 |
| 2014 | 48 | 0.2 |
kable(distr_month, caption = "Distribuzione frequenze per Month")
| Month | ni_month | fi_month |
|---|---|---|
| 1 | 20 | 0.083 |
| 2 | 20 | 0.083 |
| 3 | 20 | 0.083 |
| 4 | 20 | 0.083 |
| 5 | 20 | 0.083 |
| 6 | 20 | 0.083 |
| 7 | 20 | 0.083 |
| 8 | 20 | 0.083 |
| 9 | 20 | 0.083 |
| 10 | 20 | 0.083 |
| 11 | 20 | 0.083 |
| 12 | 20 | 0.083 |
Sales è una variabile quantitativa discreta.
DISTRIBUZIONE DI FREQUENZE:
INDICI DI POSIZIONE E VARIABILITA’
FORMA DELLA DISTRIBUZIONE:
##### DISTRIBUZIONE DI FREQUENZA #####
mu_sales <- mean(dati$Sales, na.rm = TRUE)
## Warning in mean.default(dati$Sales, na.rm = TRUE): argument is not numeric or
## logical: returning NA
media_sales <- mean(dati$Sales, na.rm = TRUE)
## Warning in mean.default(dati$Sales, na.rm = TRUE): argument is not numeric or
## logical: returning NA
sd_sales <- sd(dati$Sales, na.rm = TRUE)
contingenza_tab <- function(sales, nclass = 5) { #divisione in n.5 classi
# Creazione delle classi
classi_sales <- cut(sales, breaks = nclass, include.lowest = TRUE)
# Frequenze
ni <- table(classi_sales)
fi <- ni / length(sales)
# Frequenze cumulate
Ni <- cumsum(ni)
Fi <- cumsum(fi)
# Tabella finale
tab_sales <- data.frame(
Sales_num_tot = names(ni), # diviso in classe in base al n.tot vendite
Frequenza = as.numeric(ni),
Frequenza_relativa = round(as.numeric(fi), 3),
Frequenza_cumulata = Ni,
Frequenza_rel_cumulata = round(Fi, 3)
)
return(tab_sales)
}
# Esempio di uso:
contingenza_tab(sales)
## Sales_num_tot Frequenza Frequenza_relativa Frequenza_cumulata
## [78.7,148] [78.7,148] 84 0.350 84
## (148,217] (148,217] 77 0.321 161
## (217,285] (217,285] 41 0.171 202
## (285,354] (285,354] 27 0.112 229
## (354,423] (354,423] 11 0.046 240
## Frequenza_rel_cumulata
## [78.7,148] 0.350
## (148,217] 0.671
## (217,285] 0.842
## (285,354] 0.954
## (354,423] 1.000
View(contingenza_tab(sales))
#in Rmarkdown
library(knitr)
kable(contingenza_tab(sales), caption = "Distribuzione frequenze per Sales")
| Sales_num_tot | Frequenza | Frequenza_relativa | Frequenza_cumulata | Frequenza_rel_cumulata | |
|---|---|---|---|---|---|
| [78.7,148] | [78.7,148] | 84 | 0.350 | 84 | 0.350 |
| (148,217] | (148,217] | 77 | 0.321 | 161 | 0.671 |
| (217,285] | (217,285] | 41 | 0.171 | 202 | 0.842 |
| (285,354] | (285,354] | 27 | 0.112 | 229 | 0.954 |
| (354,423] | (354,423] | 11 | 0.046 | 240 | 1.000 |
#BARPLOT
# Barplot delle frequenze relative
barplot(contingenza_tab(sales)$Frequenza_relativa,
names.arg = contingenza_tab(sales)$Sales_num_tot,
main = "Distribuzione delle vendite (Sales)",
xlab = "N totale vendite divisi in classi",
ylab = "Frequenze relative ",
col = "lightgreen",
las = 2) # ruota le etichette verticalmente
############ INDICI DI POSIZIONE E VARIABILITA' ############
# Funzione per calcolare la moda
moda_sales <- function(sales) {
moda <- names(table(sales))[which.max(table(sales))]
return(as.numeric(moda))
}
# Funzione principale per gli indici di posizione
pos_index_sales <- function(sales) {
# Calcoli principali
mu_sales <- mean(sales) # media
me_sales <- median(sales) # mediana
mo_sales <- moda_sales(sales) # moda usando la funzione creata
quant_sales <- quantile(sales) # quantili (0%, 25%, 50%, 75%, 100%)
# Tabella finale
tab_pos_sales <- data.frame(
Media = mu_sales,
Mediana = me_sales,
Moda = mo_sales,
Min = quant_sales[1],
Q1 = quant_sales[2],
Q2 = quant_sales[3],
Q3 = quant_sales[4],
Max = quant_sales[5]
)
return(tab_pos_sales)
}
# Esempio di uso:
View(pos_index_sales(sales))
pos_index_sales(sales)
## Media Mediana Moda Min Q1 Q2 Q3 Max
## 0% 192.2917 175.5 124 79 127 175.5 247 423
library(knitr)
kable(pos_index_sales(sales), caption = "Indici di posizione per variabile Sales")
| Media | Mediana | Moda | Min | Q1 | Q2 | Q3 | Max | |
|---|---|---|---|---|---|---|---|---|
| 0% | 192.2917 | 175.5 | 124 | 79 | 127 | 175.5 | 247 | 423 |
######## VARIABILITA'########
#pacchetti utili
#install.packages("dplyr")
#library(dplyr)
range(sales)
## [1] 79 423
IQR(sales)
## [1] 120
mu_sales
## [1] NA
#creo la funzione per calcolare il coefficiente di variazione
cv<- function(x){
return(sd(x)/mean(x)*100)
}
cv_sales<-cv(sales) # la ds di questa variabile è circa al 40% dalla media
varianza_sales <- var(sales)
dev_std_sales <- sd(sales)
#boxplot - creazione del grafico
# Imposta i margini del grafico per fare più spazio par(mar = c(basso, sinistra, alto, destra))
par(mar = c(5, 5, 5, 2))
boxplot(sales,
main= "Analisi della Variabilità delle Vendite tot (sales)",
ylab = "valore delle vendite",
xlab="variabile sales",
col = "lightblue",
border="darkblue",
notch =TRUE, #stringe al centro per indicare la mediana
horizontal= FALSE #orientamento verticale
)
#informazioni h= oriz v = vert
abline(h=quantile(sales),col="lightblue")
abline(h=IQR(sales),col="red")
# Aggiungi un punto rosso a forma di rombo per indicare la MEDIA
points(1, media_sales, col = "red", pch = 18, cex = 1.5)
# Aggiungi linee di riferimento per la media e la ds
# Linea tratteggiata per la media
abline(h = media_sales, col = "tomato", lty = 2)
# Linee punteggiate per la media +/- 1 deviazione standard
abline(h = media_sales + dev_std_sales, col = "darkgreen", lty = 3)
abline(h = media_sales - dev_std_sales, col = "darkgreen", lty = 3)
#LEGENDA
legend("topright", # Posizione riquadro
legend = c("Mediana", "Media", "Media +/- 1 Dev. Std.", "Quantili"),
col = c("darkblue", "red", "darkgreen","lightblue"),
lty = c(1, 2, 3, 1), # Stile delle linee (1=continua, 2=tratteggiata, 3=punteggiata)
pch = c(NA, 18, NA, NA, NA), # Simbolo del punto (NA = nessuno)
cex = 0.8, # Dimensione del testo della legenda
bty = "n" # Rimuove il bordo dalla legenda
)
######### FORMA ##############
#pacchetti utili
#install.packages("moments")
#install.packages("ggplot2")
library(moments)
library(ggplot2)
#sintesi della variabile sales
summary(sales)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 79.0 127.0 175.5 192.3 247.0 423.0
#asimmetria
skewness(sales) # calcolo dell'asimmetria per la funzione sales gamma 3 > 1 è asimmetrica a sinistra. i valori più bassi sono quelli più frequenti in questa distribuzione.
## [1] 0.718104
plot((density(sales))) #mostro la distribuzione della variabile sales
mu_line=192.3
abline(v=192.3 ,col=2) #mostro la linea della media
#curtosi
kurtosis(sales)-3 #gamma 4 = 0 è più vicino a zero. quindi la curva ha un ampiezza simile a quella di una distribuzione normale. mesocurtica
## [1] -0.3131764
plot((density(sales)))
ggplot()+
geom_density(aes(x=sales),col='black',fill='lightblue')
VARIABILI: VOLUME, MEDIAN_PRICE, LISTINGS, MONTH_INVENTORy
Volume: La variabile volume (vendite totali) mostra una variabilità
alta( Coefficiente di Variazione del 53.7%).La distribuzione è
caratterizzata da una forte asimmetria positiva (a destra), Skewness di
0.885. Infatti la media (31.01) è più alta della mediana (27.06) e della
moda (14.00).Questo significa che la maggior parte delle osservazioni
(il 75%, Q3) si concentra su valori inferiori a 40.89M, con il valore
più frequente (Moda) a soli 14M. I valori che stanno nella porzione
destra della curva (sopra il 75%,Q4,Q5) arrivano fino a 83.54M (max) ,
questi valori spostano la media verso destra, distanziandola dal centro.
La curtosi (0.177) è molto vicina a 0, questo indica che la punta della
forma è simile a quella di una distribuzione normale (mesocurtica).
Median_price: i prezzi medi sembrano stabili
La variabile median_price (quantitativa continua) mostra una variabilità
bassa (CV 17.1%), questo indica che i prezzi sono abbastanza concentrati
attorno alla media. La distribuzione ha una leggera asimmetria negativa,
la coda tende a sinistra. (infatti Skewness = -0.365; media <
mediana), la maggior parte dei prezzi si trova nella fascia alta
(intorno a 130ml-134ml), ma con una coda di pochi valori più bassi. La
forma è platicurtica (Kurtosis = -0.623), la curva è leggermente più
piatta rispetto a una distribuzione normale.
Listing: gli annunci sono disomogenei, non ben equilibrati
In qeusta variabile i osserva una asimmetria positiva (a destra). Questo
è evidenziato sia dal valore di Skewness (0.649) sia dal fatto che la
media (1738.02) è > della mediana (1618.5). Ciò indica che la maggior
parte delle osservazioni si concentra nella parte sinistra della
distribuzione (valori più bassi), ma la presenza di pochi valori molto
elevati sposta la media verso destra. La variabilità è molto alta. il
coef di variabilità (cv) è al 43.3% (superiore al 30%), possiamo
concludere che i dati sono molto dispersi e poco concentrati attorno
alla media. Inoltre, la kurtosi indica una distribuzione platicurtica,
con una forma più schiacciata e piatta rispetto alla distribuzione
normale.
Months_inventory: distribuzione simile a una distr. normale, osservazioni sufficientemente ben distribuite.
Dall’analisi descrittiva di questa variabile possiamo notare che in media (mean = 9.19) le inserzioni attive vengono vendute in 9 mesi.La media è leggermente maggiore della mediana e della moda, questo dato indica che la maggior parte dei lavori è concentrata nella porzione sinistra della curva. quindi ci sono molte più osservazioni con valori più bassi ( min 3.4 = in 3 mesi sono state vendute tutte le inserzioni). Sembra che la distribuzione ha comunque un asimmetria positiva perchè ci sono pochi valori alti ( Q3 10,95 e Max 14.9) che spostano la media verso la parte destra della distribuzione (significa che in alcuni periodi o luoghi il totale delle inserzioni ci hanno messo quasi più di 1 anno per esser vendute tutte). Concludiamo che la distribuzione ha una leggerissima asimmetria positiva (0.041). Però 0.041 è un valore molto vicino a 0 quindi a una distribuzione normale (media=mediana=moda). Possiamo concludere che i dati sono omogenei e distrubuiti quasi perfettamente simmetrica .I n generale le inserzioni vengono vendute abbastanza rapidamente, possiamo notarlo dalla varianza e dal CV perchè è relativamente bassa (CV 25%, <30%). Similmente la deviazione standard, non è elevata e rispetto alla media i dati sembrano non essere molto dispersi. Infine la curtosi , con un valore vicino allo 0 ci indica che è leggermente platicurtica ma assomiglia molto alla distribuzione mesocurtica della tipica distribuzione normale. In conclusione, le inserzioni totali (in base al periodo o luogo) sono abbastanza distribuite e vengono vendute entro 1 anno dalla pubblicazione dell’annuncio.
# INIDICI DI POSIZIONE
# FUNZIONE MODA
calcola_moda <- function(x) {
x_pulito <- x[!is.na(x)]
if (length(x_pulito) == 0) return(NA_real_)
tabella_freq <- table(x_pulito)
moda <- names(tabella_freq)[which.max(tabella_freq)]
return(as.numeric(moda))
}
# --- funzione calcolo indici di posizione
indici_posizione <- function(x) {
mu <- round(mean(x, na.rm = TRUE), digits = 2)
sdev <-round(sd(x,na.rm = TRUE), digits = 2)
me <- median(x, na.rm = TRUE)
mo <- calcola_moda(x)
quant <- quantile(x, probs = c(0, 0.25, 0.5, 0.75, 1), na.rm = TRUE)
# Crea un VETTORE
results <- data.frame(
Media = mu,
St.dev= sdev,
Mediana = me,
Moda = mo,
Min = quant[1],
Q1 = quant[2],
Q2 = quant[3],
Q3 = quant[4],
Max = quant[5]
)
return(results)
}
# creo vettore contentente le variabili restanti
other_variables <- c("volume", "median_price", "listings", "months_inventory")
# Seleziono solo quelle colonne specifiche del dataset
dati_subset <- dati[, other_variables]
# invece di un ciclo for, uso sapply per applicare la mia funzione a ciascun elemento del vettore c other_variable.
matrice_results <- sapply(dati_subset, indici_posizione)
# uso trasponi (t) per avere le variabili sulle righe
final_tab <- t(matrice_results)
print(final_tab)
## Media St.dev Mediana Moda Min Q1 Q2 Q3
## volume 31.01 16.65 27.0625 14.003 8.166 17.6595 27.0625 40.893
## median_price 132665.4 22662.15 134500 130000 73800 117300 134500 150050
## listings 1738.02 752.71 1618.5 1581 743 1026.5 1618.5 2056
## months_inventory 9.19 2.3 8.95 8.1 3.4 7.8 8.95 10.95
## Max
## volume 83.547
## median_price 180000
## listings 3296
## months_inventory 14.9
library(knitr)
kable(final_tab, caption = "Indici posizioni altre variabili")
| Media | St.dev | Mediana | Moda | Min | Q1 | Q2 | Q3 | Max | |
|---|---|---|---|---|---|---|---|---|---|
| volume | 31.01 | 16.65 | 27.0625 | 14.003 | 8.166 | 17.6595 | 27.0625 | 40.893 | 83.547 |
| median_price | 132665.42 | 22662.15 | 134500 | 130000 | 73800 | 117300 | 134500 | 150050 | 180000 |
| listings | 1738.02 | 752.71 | 1618.5 | 1581 | 743 | 1026.5 | 1618.5 | 2056 | 3296 |
| months_inventory | 9.19 | 2.3 | 8.95 | 8.1 | 3.4 | 7.8 | 8.95 | 10.95 | 14.9 |
#### Variabilità per tutte le variabili restanti
cv_var<- function(x, na.rm = TRUE) {
return(sd(x)/mean(x)*100)
}
all_variability <- function(x) {
range_vals <- range(x, na.rm = TRUE)
range_diff <- range_vals[2] - range_vals[1]
iqr_var <- IQR(x, na.rm = TRUE)
varianza <- var(x, na.rm = TRUE)
sdev <- round(sd(x, na.rm = TRUE), digits = 2)
coef_var <- cv_var(x, na.rm = TRUE)
results_var <- c(
Range = range_diff,
IQR = iqr_var,
Varianza = varianza,
SD = sdev,
CV = coef_var
)
return(results_var)
}
other_variables <- c("volume", "median_price", "listings", "months_inventory")
dati_subset <- dati[, other_variables]
matrice_results_var <- sapply(dati_subset, all_variability)
final_tab_var <- t(matrice_results_var)
print(final_tab_var)
## Range IQR Varianza SD CV
## volume 75.381 23.2335 2.772707e+02 16.65 53.70536
## median_price 106200.000 32750.0000 5.135730e+08 22662.15 17.08218
## listings 2553.000 1029.5000 5.665690e+05 752.71 43.30833
## months_inventory 11.500 3.1500 5.306889e+00 2.30 25.06031
library(knitr)
kable(final_tab_var, caption = "Variabilità altre variabili")
| Range | IQR | Varianza | SD | CV | |
|---|---|---|---|---|---|
| volume | 75.381 | 23.2335 | 2.772707e+02 | 16.65 | 53.70536 |
| median_price | 106200.000 | 32750.0000 | 5.135730e+08 | 22662.15 | 17.08218 |
| listings | 2553.000 | 1029.5000 | 5.665690e+05 | 752.71 | 43.30833 |
| months_inventory | 11.500 | 3.1500 | 5.306889e+00 | 2.30 | 25.06031 |
## indici di FORMA per le variabili restanti
#pacchetti utili
library(moments)
library(ggplot2)
#funzione calcolo asimmetria
asimmetry<- function(x, na.rm=TRUE){
sk <- round(skewness(x, na.rm=na.rm), digits = 3)
kurt_ex <- round(kurtosis(x, na.rm=na.rm)-3, digits =3)
results_form <-c(
Skewness = sk,
Kurtosis_Excess= kurt_ex
)
return(results_form)
}
other_variables <- c("volume", "median_price", "listings", "months_inventory")
dati_subset <- dati[, other_variables]
matrice_results_form <- sapply(dati_subset, asimmetry)
final_tab_form <- t(matrice_results_form)
print(final_tab_form)
## Skewness Kurtosis_Excess
## volume 0.885 0.177
## median_price -0.365 -0.623
## listings 0.649 -0.792
## months_inventory 0.041 -0.174
library(knitr)
kable(final_tab_form, caption = "Indici di forma: asimmetria e kurtosi")
| Skewness | Kurtosis_Excess | |
|---|---|---|
| volume | 0.885 | 0.177 |
| median_price | -0.365 | -0.623 |
| listings | 0.649 | -0.792 |
| months_inventory | 0.041 | -0.174 |
#per i grafici non posso usare supply( opera su vettori e semplifica risultati in 1 vettore) perciò utilizzo direttamente ggplo e creo il ciclo for per le variabili contenute in "other_variables".
library(ggplot2)
# ciclo for per creare i plot
for (var in other_variables) {
# Calcola la media per quella colonna
media_val <- mean(dati_subset[[var]], na.rm = TRUE)
# Crea il ggplot
plot_var <- ggplot(dati_subset, aes(x = dati[[var]])) +
geom_density(col = 'black', fill = 'lightblue', alpha = 0.7) +
# Agg la linea della media
geom_vline(xintercept = media_val,
col = "red",
linetype = "dashed",
size = 1) +
# Titolo
ggtitle(paste("Densità e Media di:", var)) +
theme_minimal()
# STAMPA il grafico
print(plot_var)
}
## 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.
La variabile con la più alta variabilità è Volume. Per confrontare la
variabilità tra variabili che hanno unità di misura diverse (es. milioni
di dollari, numero di annunci), ho osservato il coefficiente di
variazione.
Volume ha un CV di 53.7% , un valore alto che indica un’elevata
dispersione dei dati intorno alla media. Infatti, questa alta
dispersione è visibile anche negli altri indici. Se consideriamo IQR
(23.23) è un valore simile alla mediana (27.06), quindi il 50% dei dati
centrali è molto sparso.
Confronto con altre variabili: Listing ha un CV del 43.3% (moderatamente variabile) mentre Median_price (17.1%) e months_inventory(25.1%) sono molto più stabili.
La variabile con la distribuzione più asimmetrica è sempre
volume.
Per studiare l’asimmetria ho prima osservato gli indici di posizione
(media>mediana>moda) e successivamente ho osservato se il valore
di skewness fosse lontano da 0.Valori lontani da 0 indicano una forte
asimmetria.
Volume, rispetto alle altre variabili, mostra un’evidente asimmetria
positiva (a destra), con la media (31.01) più alta della mediana
(27.06). La Skewness è 0.885, ed è il valore più alto tra tutte le
variabili. Questi dati confermano che la distribuzione ha una marcata
pendenza a destra. Questo significa che la maggior parte dei volumi di
vendita è bassa, ma ci sono poche osservazioni con valori alti che
spostano la media verso l’alto, verso la parte destra della curva.
Infine ho carcato di capire anche la forma della punta della curca
attraverso l’analisi della Kurtosi (0.177), che, essendo vicina a 0,
indica una forma mesocurtica (simile quindi alla distribuzione
normale).
Ho selezionato la variabile quantitativa “sales” e l’ho suddivisa in 5 classi. Ho creato una distribuzione di frequenze includendo nella tabella il calcolo dell’indice di Gini. Infine, ho rappresentato i dati con un barbox.
Discussione: la distribuzione di frequenza relativa mostra che in generale il campione di n tot vendite è fortemente sbilanciato. Infatti il maggior numero di vendite totali è distribuito nelle classi più piccole. Dalle frequenze relative possiamo osservare che quindi la prima e la seconda classe hanno un maggior numero di vendite. Infatti, se osserviamo le frequenze relative cumulate, la prima e la seconda classe rappresentano più del 50 % delle vendite (67%). Poi ancora, si nota che la prima classe è la classe modale (quella con la frequenza più alta, 35%).Dalle precedenti analisi abbiamo visto che la forma della distribuzione è asimmetrica con pendenza a destra (skewness positiva: 0.71).Questo dato è rafforzato dall’indice di gini che è vicino all’1. ciò signfica che le unità statistiche sono eterogenee, c’è massima concentrazione nelle prime classi e quindi esiste una forte disuguaglianza nel campione. Il 67% delle unità sta nelle prime due classi (valori bassi) mentre solo il 4.6% delle unità sta nell’ultima classe (valori alti).
contingenza_tab <- function(sales, nclass = 5) {
# Creazione delle classi
classi <- cut(sales, breaks = nclass, include.lowest = TRUE)
# Frequenze assolute e relative
ni <- table(classi)
fi <- ni / length(sales)
# Frequenze cumulate
Ni <- cumsum(ni)
Fi <- cumsum(fi)
# Calcolo del Gini index (normalizzato)
gini_index <- 1 - sum((fi)^2)
J <- length(ni) # numero di classi
gini_norm <- gini_index / ((J - 1) / J)
# Tabella finale
tabella <- data.frame(
Classe = names(ni),
Frequenza = as.numeric(ni),
Frequenza_relativa = round(as.numeric(fi), 3),
Frequenza_cumulata = as.numeric(Ni),
Frequenza_rel_cumulata = round(as.numeric(Fi), 3)
)
# Aggiungo indice di Gini alla tabella
tabella <- rbind(tabella,
data.frame(
Classe = "Indice di Gini (norm.)",
Frequenza = NA,
Frequenza_relativa = round(gini_norm, 3),
Frequenza_cumulata = NA,
Frequenza_rel_cumulata = NA
))
return(tabella)
}
# Esempio di uso:
contingenza_tab(sales)
## Classe Frequenza Frequenza_relativa Frequenza_cumulata
## 1 [78.7,148] 84 0.350 84
## 2 (148,217] 77 0.321 161
## 3 (217,285] 41 0.171 202
## 4 (285,354] 27 0.112 229
## 5 (354,423] 11 0.046 240
## 6 Indice di Gini (norm.) NA 0.913 NA
## Frequenza_rel_cumulata
## 1 0.350
## 2 0.671
## 3 0.842
## 4 0.954
## 5 1.000
## 6 NA
#BARPLOT SALES
# Seleziona tutto tranne l'ultima riga
tab_dati <- contingenza_tab(sales)
dati_per_plot <- head(tab_dati, 5)
# Barplot delle frequenze relative
etichette_asse_x = c("1","2","3","4","5")
colori_barre= c("darkblue", "lightblue","purple","pink","lavender")
barplot(dati_per_plot$Frequenza_relativa,
names.arg = etichette_asse_x, #num da 1 a 5 (indicano le classi)
main = "Distribuzione delle vendite (Sales)",
xlab = "N totale vendite divisi in classi",
ylab = "Frequenze relative (%) ",
col = colori_barre,
las = 1) # ruota le etichette orizz
testo_legenda <- paste(etichette_asse_x, "=", dati_per_plot$Classe)
legend("topright", # Posizione riquadro
legend = testo_legenda, #usa i numeri e i valori delle classi
title= "Legenda Classi",
fill= colori_barre,
cex = 0.8, # Dimensione del testo della legenda
bty = "n" # Rimuove il bordo dalla legenda
)
Qual è la probabilità che, presa una riga a caso di questo dataset, essa riporti la città “Beaumont”? E la probabilità che riporti il mese di Luglio? E la probabilità che riporti il mese di dicembre 2012?
Estraggo i dati totali (240 osservazioni) e i casi favorevoli per le condizioni richieste. Calcolo la probabilità come: Probabilità = Casi Favorevoli / Casi Totali. 1) 240/60= 25% 2) 240/20 = 0.083% 3) 0.016%
#install.packages("dplyr")
#library(dplyr)
table(city)
## city
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
sum(dati$city == "Beaumont", na.rm = TRUE) # 60
## [1] 60
#Casi Favorevoli
conteggio_beaumont <- sum(dati$city == "Beaumont", na.rm = TRUE)
#Casi Totali
conteggio_totale <- nrow(dati)
# Calcolo della probabilità
probabilità <- conteggio_beaumont / conteggio_totale
print(probabilità)
## [1] 0.25
#funzione per estrarre 1 riga dalla variabile city e calcolare probabilità
prob_cities <- function(dati, var_city ="city") {
rand_city <- sample((dati[[var_city]]), 1) #Estrae una città a caso
conteggio_fav <- sum(dati[[var_city]] == rand_city, na.rm = TRUE) #casi favorevoli
conteggio_tot <- nrow(dati) # casi totali
prob<- conteggio_fav / conteggio_tot # Calcolo probabilità
return(list(
città = rand_city,
probability = prob
))
}
results_cities <- prob_cities(dati)
print(results_cities)
## $città
## [1] "Bryan-College Station"
##
## $probability
## [1] 0.25
#probabilità mese luglio:
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
sum(dati$month == "7", na.rm = TRUE) #
## [1] 20
calcola_prob_categ <- function(vettore_categorico) {
#useNA = "ifany" include i valori NA nel conteggio, se esistono
conteggi <- table(vettore_categorico, useNA = "ifany")
probabilita <- prop.table(conteggi)#probabilità
return(probabilita)
}
# Calcolo probabilità
prob_month <- calcola_prob_categ(dati$month)
print(prob_month)
## vettore_categorico
## 1 2 3 4 5 6 7
## 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333
## 8 9 10 11 12
## 0.08333333 0.08333333 0.08333333 0.08333333 0.08333333
prob_city <- calcola_prob_categ(dati$city)
print(prob_city)
## vettore_categorico
## Beaumont Bryan-College Station Tyler
## 0.25 0.25 0.25
## Wichita Falls
## 0.25
#probabilità dicembre 2012
# Casi favorevoli
month_year <- sum(dati$month == 12 & dati$year == 2012, na.rm = TRUE)
#Casi Totali
conteggio_totale <- nrow(dati)
#Probabilità
prob_month_year <- month_year/ conteggio_totale
print(prob_month_year)
## [1] 0.01666667
#BARPLOT
library(ggplot2)
library(scales)
# Grafico a barre per le probabilità (frequenze relative)
ggplot(dati, aes(x = city)) +
#group = 1 serve per calcolare la proporzione sul totale
geom_bar(aes(y = after_stat(prop), group=1 ),
fill = "lightblue", col = "black") +
# Aggiunge etichette in % sopra le barre
geom_text(aes(y = after_stat(prop),
label = percent(after_stat(prop), accuracy = 1)),
group = 1,
stat = "count",
vjust = -0.5) +
# Formatta l'asse Y come percentuale
ggtitle("Probabilità (Frequenza Relativa) per Città") +
xlab("Città") +
ylab("Probabilità")
# Grafico a barre per le probabilità (frequenze relative) dei mesi
ggplot(dati, aes(x = month)) +
geom_bar(aes(y = after_stat(prop), group = 1),
fill = "lightgreen", col = "black") +
scale_y_continuous(labels = percent) +
ggtitle("Probabilità (Frequenza Relativa) per Mese") +
xlab("Mese") +
ylab("Probabilità") +
theme_minimal()
Abbiamo già a disposizione la variabile median_price(prezzo mediano).
Ho deciso di aggiungere una nuova variabile chiamata mean_price che
calcola il prezzo medio delle case vendute per città e volendo anche per
mese.
Abbiamo a disposizione le variabili, “volume” che contiene il valore
totale delle vendite (in milioni di dollari) e “sales” che contiene il
numero totale di vendite. Se dividiamo “volume” valore totale delle
vendite per il n. totale di vendite (come se fosse il n. delle nostre
osservazioni) possiamo trovare il prezzo medio degli immobili per ogni
città. mean_price=volume/sales Ho notato che volume è in milioni
di dollari. Riportare il prezzo medio in
milioni può essere poco comprensibile o in generale
difficile da analizzare a colpo d’occhio. Per semplificare moltiplico
per 10^6 e ottengo il valore medio in dollari.
Calcolo dell’efficaciia: Per calcolare l’efficacia ho pensato di creare un indice da 0 a 1 che indica quante vendite vengono effettuate in base al numero di annunci (listing) e il tempo mensile che ci impiegano gli annunci ad essere completati ( month_inventory). Valori più elevati indicano città o mesi in cui gli immobili si vendono più rapidamente, espressione un mercato che è più attivo e vendite efficaci.
si può usare per confrontrare le città in cui ci sono più vendite (es. max(efficacy)). o per vedere se nel tempo gli immobili vengono venduti meglio o peggio. oppure per vedere se ci sono mesi in cui si vende di più o di meno. (es. quando il mercato è dinamico o saturo).
nel 2014 nella città di Bryan College c’è stato il maggior numero di efficienza nell vendite nel mese di luglio. 1041 annunci sono stati esauriti in 4 mesi circa (vedi: max(efficacy). il mercato sembra dinamico.
Andando più a fondo a questa analisi, ho creato un boxplot per vedere
qual è la città che effettivamente ha livelli di efficacy maggiori, e
che quindi ha un mercato più attivo. Senza questa analisi sarei potuto
andare andato incontro ad un errore. Ovvero: inizialmente non avevo
considerato gli outliers!. Infatti, come si può notare dal boxplot, è
verò che il valore massimo di efficacia è stato registrato nella città
di BC nel 2014, però questè è un valore unico e molto lontano dalla
media per la stessa città di BC!. Da notare inoltre che, in media anche
la città di Wichita Falls mostra di avere un mercato abbastanza
dinamico. Wichita Falls ha meno variabilità nelle vendite rispetto a
Brayan College e sono abbastanza efficaci nel tempo. Quindi rispetto a
tutte le altre città, a BC si registrano delle vendite efficaci da
record ( efficacy 0.23) , a Wichita Falls mediamente le vendite sono
comunque efficaci ( efficacy 0.16) e guadagna il secondo posto.
mean_price <- mean(dati$Price, na.rm = TRUE)
## Warning in mean.default(dati$Price, na.rm = TRUE): argument is not numeric or
## logical: returning NA
attach(dati)
## The following objects are masked from dati (pos = 7):
##
## city, listings, median_price, month, months_inventory, sales,
## volume, year
## The following objects are masked from dati (pos = 8):
##
## city, listings, median_price, month, months_inventory, sales,
## volume, year
#creare una nuova variabile
dati$mean_price <- (volume * 1e6) / sales
summary(mean_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## NA NA NA NaN NA NA 1
head(mean_price,5)
## [1] NA
#efficacy: creo la variabile efficacia
dati$efficacy <- dati$sales / (dati$listings * dati$months_inventory)
View(dati)
# esempio: riga dove efficacy ha il valore maggiore
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
dati %>%
filter(efficacy == max(efficacy))
## city year month sales volume median_price listings
## 1 Bryan-College Station 2014 7 403 83.547 172600 1041
## months_inventory mean_price efficacy
## 1 4.1 207312.7 0.09442141
#grafico 1 come
library(ggplot2)
ggplot(dati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = mean_price, color = city)) +
geom_line() +
labs(title = "Andamento del prezzo medio degli immobili in Texas",
x = "Data", y = "Prezzo medio ($)") +
theme_minimal()
#grafico 2 città con valore più alto di efficacia nel tempo.
ggplot(dati,aes(x=city,y=efficacy, fill= city)) +
geom_boxplot()+
labs(title = "Efficacia del mercato immobiliare per città",
x= "città", y="indice efficacia")+
theme_minimal()
library(ggplot2)
library(dplyr)
# Calcola la media generale di efficacy
media_generale <- mean(dati$efficacy, na.rm = TRUE)
# Calcola la media per ogni città
medie_città <- dati %>%
group_by(city) %>%
summarise(media_city = mean(efficacy, na.rm = TRUE))
# Grafico
ggplot(dati, aes(x = reorder(city, efficacy), y = efficacy, fill = city)) +
geom_boxplot(alpha = 0.7) + # boxplot semi-trasparenti
# Linea rossa della media generale
geom_hline(yintercept = media_generale, linetype = "dashed", color = "red", linewidth = 1) +
# Punti neri per la media di ogni città
geom_point(data = medie_città,
aes(x = reorder(city, media_city), y = media_city),
color = "black", size = 2.5) +
labs(
title = "Efficacia del mercato immobiliare per città",
subtitle = paste("Linea rossa = media generale (", round(media_generale, 2), ")", sep = ""),
x = "Città (ordinate per efficacia media)",
y = "Indice di efficacia"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none" # rimuove la legenda
)
mean(dati$efficacy[dati$city == "Wichita Falls"], na.rm = TRUE)
## [1] 0.01664188
mean(dati$efficacy[dati$city=="Bryan-College Station"], na.rm = TRUE)
## [1] 0.02389662
Ho iniziato raggruppando i dati nel mio nuovo dataset, e generando dei summary: summary_mydati, summary city, season_summary).Questi summary contengono alcune nuove variabili ( totally sales, totally listings , mean_price e sd_price) rispetto al dataset originale.
city: città di riferimento
year: anno di riferimento
month: mese di riferimento
totally_sales: numero totale di vendite
totally_listings: numero totale di annunci attivi
mean_price media dei prezzi (volume/sales)
sd_price: restituisce N/A perche l’osservazione è singola. per questo ho generato summary_city
Summary_city è stato usato per creare una tabella markdown per mostrare il prezzo medio e la variabilità (deviazione standard).
Grafici: Ho usato dei boxplot, lineplot e barplot per analizzare e visualizzare l’anndamento nel tempo (mesi e anni) per valutare per le varie città il cambio del prezzo medio, il numero di vendite, le vendite stagionali e l’andamento del numero di annunci.
library(dplyr)
library(ggplot2)
#_____SUMMARY________________________________________
#Raggruppo i dati per citta, mese e anno in un nuovo dataset
#con nuove variabili utili per i miei grafici.
summary_mydati <- dati %>% # concatenare le funzioni in dplyr "pipe"
group_by(city,year,month) %>% #raggruppo per città, anno e mese
summarise(
mean_price = mean((volume * 1e6) / sales, na.rm=TRUE),
sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
totally_sales =sum(sales, na.rm = TRUE),
totally_listings = sum(listings, na.rm = TRUE),
.groups = "drop"
)
View(summary_mydati)
#Summary per raggruppare le 4 città
summary_city <- dati %>%
group_by(city) %>% # raggruppo solo per città
summarise(
mean_price = mean((volume * 1e6) / sales, na.rm = TRUE),
sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
totally_sales = sum(sales, na.rm = TRUE),
totally_listings = sum(listings, na.rm = TRUE),
.groups = "drop"
)
summary_city
## # A tibble: 4 × 5
## city mean_price sd_price totally_sales totally_listings
## <chr> <dbl> <dbl> <int> <int>
## 1 Beaumont 146640. 11232. 10643 100759
## 2 Bryan-College Station 183534. 15149. 12358 87488
## 3 Tyler 167677. 12351. 16185 174303
## 4 Wichita Falls 119430. 11398. 6964 54575
#creo la tabella in Rmarkdown
summary_city %>%
arrange(desc(mean_price)) %>%
knitr::kable(caption = "Sintesi per città: media, deviazione standard")
| city | mean_price | sd_price | totally_sales | totally_listings |
|---|---|---|---|---|
| Bryan-College Station | 183534.3 | 15149.35 | 12358 | 87488 |
| Tyler | 167676.8 | 12350.51 | 16185 | 174303 |
| Beaumont | 146640.4 | 11232.13 | 10643 | 100759 |
| Wichita Falls | 119430.0 | 11398.48 | 6964 | 54575 |
#____________________________________________________________________________
# GRAFICI
#1) PREZZO MEDIO
# confronto tra le città: come cambia il prezzo medio per città nei mesi tra il 2010 e il 2014
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = mean_price, color = city)) +
geom_line() +
labs(title = "Prezzo medio per città (2010-2014)",
x = "Data", y = "Prezzo medio ($)") +
theme_minimal()
# prezzo medio nei mesi e negli anni con linea di tendenza:
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
y = mean_price)) +
geom_line(color = "steelblue", alpha = 0.7, size = 1) +
geom_point(size = 1) +
geom_smooth(method = "lm", color = "orange", se = FALSE, linewidth = 1.2) +
facet_wrap(~ city, ncol = 2, scales = "free_y") +
scale_x_date(
date_breaks = "3 months",
date_labels = "%b-%Y"
) +
labs(
title = "Andamento del prezzo medio per città (2010–2014)",
subtitle = "Linea arancione = trend line (retta di regressione)",
x = "Mese e anno",
y = "Prezzo medio in dollari ($)"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
strip.text = element_text(face = "bold")
)
## `geom_smooth()` using formula = 'y ~ x'
# Calcolo ledia generale di tutte le città utile per il boxplot per le città
media_generale <- mean(summary_city$mean_price, na.rm = TRUE)
# Grafico boxplot prezzi medi per città
ggplot(summary_mydati, aes(x = city, y = mean_price, fill = city)) +
geom_boxplot(alpha = 0.7) +
# Linea rossa della media generale
geom_hline(yintercept = media_generale, linetype = "dashed", color = "red", linewidth = 1) +
# Punti neri per la media di ciascuna città
geom_point(data = summary_city,
aes(x = city, y = mean_price),
color = "black", size = 3) +
labs(
title = "Prezzo medio degli immobili per città",
subtitle = paste("Linea rossa = media generale (", round(media_generale,2), ")", sep=""),
x = "Città",
y = "Prezzo medio (€)"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none"
)
#2) VENDITE
# confronto tra le città: come cambia il numero di vendite per città nei mesi tra il 2010 e il 2014
# in più la linea di tendenza per vedere il trend nel tempo.
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
y = totally_sales)) +
geom_line(color = "steelblue", alpha = 0.7, size = 1) +
geom_point(size = 1) +
geom_smooth(method = "lm", color = "red", se = FALSE, linewidth = 1.2) +
facet_wrap(~ city, ncol = 2, scales = "free_y") +
scale_x_date(
date_breaks = "3 months",
date_labels = "%b-%Y"
) +
labs(
title = "Andamento mensile delle vendite per città (2010–2014)",
subtitle = "Linea rossa = trend line (retta di regressione)",
x = "Mese e anno",
y = "Numero totale di vendite"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
strip.text = element_text(face = "bold")
)
## `geom_smooth()` using formula = 'y ~ x'
# ANALISI VENDITE STAGIONALI
#barplot vendite nei mesi estivi vs mesi invernali
# creare la variabile "season" che contiene i mesi estivi o invernali
summary_mydati2 <- summary_mydati %>% #con mutate creo la nuova variab season
mutate(season = case_when(
month %in% c(6, 7, 8) ~ "Estate", # case_when come ifelse se in month c'è il vet. c allora
month %in% c(12, 1, 2) ~ "Inverno",TRUE ~ NA_character_)) #gli altri sono NA.
#Calcola vendite totali per città e stagione
season_summary <- summary_mydati2 %>%
filter(!is.na(season)) %>% #rimuove i NA da season
group_by(city, season) %>% #raggruppa per città e stagione
summarise(
total_sales_season = sum(totally_sales, na.rm = TRUE),
.groups = "drop"
) #scioglie il raggruppamento
# Crea il barplot, facet per città
ggplot(season_summary, aes(x = season, y = total_sales_season, fill = season)) +
geom_col(width = 0.6) +
facet_wrap(~ city, ncol = 2, scales = "free_y") + #intervalli diversi su asse y
labs(
title = "Confronto vendite tra mesi estivi e invernali (2010–2014)",
x = "Stagione",
y = "Totale vendite"
) +
scale_fill_manual(values = c("Inverno" = "steelblue", "Estate" = "orange")) +
theme_minimal() +
theme(
strip.text = element_text(face = "bold", size = 10),
axis.text.x = element_text(angle = 0, size = 9),
legend.position = "none"
)
#3 ANNUNCI
#confronto tra le città: come cambia il numero di annunci per città nei mesi tra il 2010 e il 2014
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")), y = totally_listings, color = city)) +
geom_line() +
labs(title = "annunci per città (2010-2014)",
x = "Data", y = " numero totale di annunci") +
theme_minimal()
La città di Bryan-College Station ha una mediana più alta rispetto a tutte le altre. Se notiamo la grandezza dei box (IQR), la variabilità del 50% centrale dei dati per questa città è ridotta. I valori non sono molto dispersi attorno alla mediana (box IQR stretto) e possiamo immaginare un tipo di mercato piuttosto omogeneo; in generale i prezzi rimangono simili. Però allo stesso tempo i whiskers (baffi) allungati verso l’alto, e la media (pallino blu) posizionata sopra la mediana, ci informano che c’è una tendenza a prezzi più elevati. Questo dato è confermato anche dalla presenza di outliers, informandoci così che in questa città si registrano i prezzi più alti rispetto a tutte le altre. Deduco così che è l’area in cui le case sono mediamente più costose.
A seguire, in ordine dal più costoso al più economico, troviamo le città di Tyler e Beaumont. I loro prezzi mediani sono più bassi rispetto a Bryan-College Station. Nonostante qualche valore eccezionale a Beaumont (outlier alto), nella città di Tyler i prezzi mediani si mantengono più elevati. È importante notare che a Beaumont i prezzi hanno la maggiore variabilità centrale (la scatola IQR è visibilmente più larga delle altre), suggerendo un mercato più eterogeneo in quella fascia di prezzo.
Infine, la città che ha un prezzo mediano più economico di tutte è Wichita Falls. I valori degli immobili qui mostrano una chiara tendenza ad assumere prezzi più economici, come indicato dal baffo inferiore molto lungo (forte asimmetria negativa).
Riepilogo :Bryan-College Station ha la mediana più alta (prezzo mediano più alto) e una tendenza verso prezzi costosi (asimmetria positiva)
Beaumont ha la maggiore dispersione nella fascia centrale dei prezzi (IQR più largo), indicando un mercato eterogeneo
Wichita Falls ha il prezzo mediano più basso e una forte asimmetria verso prezzi economici (baffo inferiore lungo)
Tyler si posiziona come seconda città più costosa, con una distribuzione piuttosto simmetrica attorno alla sua mediana
library(dplyr)
library(ggplot2)
#summary city
summary_median_city <- dati %>%
group_by(city) %>%
summarize(
median_prezzo = median(median_price, na.rm=TRUE),
mean_price = mean((volume * 1e6) / sales, na.rm=TRUE),
sd_price = sd((volume * 1e6) / sales, na.rm = TRUE),
.groups = "drop"
)
summary_median_city
## # A tibble: 4 × 4
## city median_prezzo mean_price sd_price
## <chr> <dbl> <dbl> <dbl>
## 1 Beaumont 130750 146640. 11232.
## 2 Bryan-College Station 155400 183534. 15149.
## 3 Tyler 142200 167677. 12351.
## 4 Wichita Falls 102300 119430. 11398.
#boxplot confronto città
ggplot(dati, aes(x=city, y=median_price,fill=city))+
geom_boxplot(alpha= 0.5) + #trasparenza
geom_point(data=summary_median_city, aes(x=city,y=median_prezzo),
color="blue",size=3)+
labs( title="Confronto della distribuzione del prezzo mediano tra le città",
x= "città",
y=" prezzo mediano ($)")+
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none")
Commento: Dall’analisi del confronto della distribuzione del valore totale delle vendite tra le varie città nel periodo di tempo compreso dal 2010 al 2014 si può osservare che tutte le cittè eccetto Wichita Falls,la quale rimane costante nel tempo, mostrano un aumento del valore totale delle vendite. In particolare, il valore mediano delle vendite come visto precedentemente aumenta anno dopo anno. Un esempio è la città di Bryan College che dal 2013 al 2014 registra un aumento notevole superando ampiamente Beaumont. Nella città di Tyler si registra un valore totale di vendite mediano costantemente più alto rispetto a tutte le altre città e in tutti i 5 anni. Anche la città di Bryan College Station mostra un numero elevato di vendite totali (raggiungendo quasi Tyler). però si distingue per avere una variabilità dei valori molto elevata (i suoi box e baffi sono spesso i più lunghi, ad esempio nel 2013 e 2014).
library(dplyr)
library(ggplot2)
#summary city
summary_vendite <- dati %>%
group_by(city,year,month) %>%
summarize(
totally_sales =sum(sales, na.rm = TRUE),
.groups = "drop"
)
summary_vendite
## # A tibble: 240 × 4
## city year month totally_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
#boxplot confronto città e anno
ggplot(dati, aes(x=city, y=sales,fill= factor(year)))+ #factor discreta non continua
geom_boxplot(alpha= 0.6, position= position_dodge(width=0.8)) + #trasparenza e sovrapposizione boxplot
labs(
title="Distribuzione delle vendite per città e anno",
x= "città",
y=" valore totale ($)",
fill="Anno")+
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1))
1)barplot vendite totali per città e trend
2)barplot a barre sovraimposte
3)barplot a barre sovraimposte normalizzato
Commento:
1)il grafico a barre 1 mostra il confronto totale delle vendite tra le città dell’arco di tempo dal 2010 al 2014. La città che mostra il numero di elevato di vendite è Tyler(max=423, mean=269). A seguire troviamo le città di Bryan College Station e Beaumont. Per la città di Bryan College le vendite sono molto fluttuanti durante i 5 anni e si può notare come aumentano e diminuiscono: all’inizio e alla fine di ogni anno si notano dei picchi positivi e negativi. Nonostante ciò, le vendite hanno avuto un trend in aumento, specialmente nell’ultimo anno (2014). Similmente possiamo osservare a Beaumont, dove la variabilità di vendite è più bassa e il trend di n.di vendite negli anni è in lieve ma costante aumento positivo. Infine all’ultimo posto troviamo Wichita Falls dove il numero di vendite è rimasto costante negli anni, senza variazioni trend di crescita e registra i valori di vendite più bassi rispetto alle altre città (max 167, mean 116).
2)Il grafico 2 a barre sovrapposte mostra e conferma il contributo maggiore della città di Tyler nel n.totale di vendite nel tempo. Le vendite sembrano seguire un pattern stagionale, con picchi di vendite di mesi primaverili/estivi e un calo nei mesi autunnali/invernali, creando così un’onda sinusoidale che mostra l’andamento oscillatorio delle vendite durante l’anno. Questo andamento oscillatorio però è caratterizzato dall’ un trend di crescita positivo dal 2010 al 2014 per tuttè le cittè tranne che per Wichita Falls.
3) Il grafico 3 mostra le stesse informazioni del precedente, ma in forma percentuale. Si nota che Tyler e Bryan College Station sono le città che contribuiscono in modo più consistente alle vendite totali (ciascuna con circa il 30–35%), seguite da Beaumont e infine Wichita Falls, che mantiene una quota intorno al 10–15%. Le proporzioni restano abbastanza stabili nel tempo, indicando che la distribuzione delle vendite tra le città non è cambiata in modo significativo tra il 2010 e il 2014.
library(dplyr)
library(ggplot2)
summary_vendite <- dati %>%
group_by(city,year,month) %>%
summarize(
totally_sales =sum(sales, na.rm = TRUE),
.groups = "drop"
)
summary_vendite
## # A tibble: 240 × 4
## city year month totally_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
#grafico 1) Barplot vendite per città e trend
ggplot(dati,aes(x = as.Date(paste(year, month, "01", sep="-")), y = sales, color = city)) +
geom_col(width= 0.5)+
geom_smooth(method = "lm", color = "tomato", se = FALSE, linewidth = 1) +
facet_wrap(~ city, ncol=2)+ #città tutte sulla stessa scala
#facet_wrap(~city,ncol=2, scales="free_y")+ #scales="free_y da usare per vedere la scala propria di ogni città
labs(title= "confronto totale vendite tra le città",
x= "Mesi/Anni",
y=" N.tot Vendite")+
theme_minimal() +
theme(
strip.text = element_text(face = "bold", size = 10),
axis.text.x = element_text(angle = 0, size = 9),
legend.position = "none")
## `geom_smooth()` using formula = 'y ~ x'
#grafico 2) barre sovrapposte non normalizzato
# creo nuova variabile "periodo" che rappresenta mese/anno - per evitare date doppie
summary_mydati <- summary_mydati %>%
mutate(periodo = paste(year, month, sep = "-")) #nuova variabile periodo
# grafico a barre sovrapposte
ggplot(summary_mydati, aes(x = periodo, y = totally_sales, fill = city)) +
geom_col(position = "stack") +
labs(
title = "Confronto totale vendite mensili tra città (2010–2014)",
subtitle = "Le barre sovrapposte mostrano il contributo di ogni città al totale mensile",
x = "Mese e anno",
y = "Totale vendite",
fill = "Città"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 80, hjust = 1, size = 6),
plot.title = element_text(face = "bold"),
legend.position = "right"
)
#grafico 3) grafico a barre normalizzato (per mostrare le percentuali)
#creo nuovo summary e aggiungo una nuova variabile con dati vendite normalizzati
normalize_sales <-summary_mydati %>%
group_by(year,month) %>%
mutate(sales_norm= totally_sales/sum(totally_sales)) #percentuale
#grafico normalizzato
ggplot(normalize_sales,aes(x= as.Date(paste(year,month,"01",sep="-")),
y=sales_norm, fill=city))+
geom_col(position="stack")+
scale_y_continuous(labels = scales::percent)+ #Mostra i numeri come percentuali asse y
labs(
title= "Vendite per città con valori in percentuale",
x= "Anni (2010-2014)",
y="percentuale di vendite",
fill="Città")+
theme_minimal()+
theme( axis.text.x=element_text(angle=45,hjust=1,size=8))
linechart per confrontare l’andamento delle vendite in periodi storici differenti.
Prova a creare un line chart di una variabile a tua scelta per fare confronti commentati fra città e periodi storici. Ho scelto la variabile listings: numero totale di annunci.
Commento:
Linechart 1) : Dall’analisi della linechart si può osservare che il numerodi vendite nel tempo è fluttuante. Però si può notare per ttutte le città tranne Wichita Falls, un trend di aumento delle vendite nei 5 anni. Il trend sembra crescere in maniera oscillatoria: ci sono periodi di basse vendite all’inizio dell’anno corrispondenti ai mesi invernali, i quali sono seguiti da picchi positivi nei mesi estivi. Questo pattern stagionale si ripete negli anni ed è accompagnato da un aumento del numero di vendite mediano i tutte le città tranne Wichita Falls.In quest’ultima città, questo trend di crescita non è visibile e al contrario si nota una situzione di stazionarietà (mercato fermo). Sebbene siano presenti anche qui delle oscillazioni stagionali come le altre città, queste avvengono attorno a un numero di vendite medio che rimane basso e costante nel tempo (linea di regressione piatta).
Linechart 2): come nel grafico precedente, possiamo assistere ad un pattern con andamento oscillatorio. il numero di annunci per città nel tempo è sottoposto a un incremento nei mesi estivi e un decremento nei mesi invernali. questo pattern si può sovrapporre a quello precedente del numero delle vendite e si potrebbe avanzare un ipotesi di correlazione: ” l’aumento del numero di vendite potrebbe essere correlato all’aumentare del numero di annunci”. Diversamente dall’altro grafico, però , è evidente un trend negativo negli anni. Anno dopo anno ,nelle varie città ,si registrano minori numeri di annunci. In particolare nelle città di Tyler e Bryan College station, le quali sono le città con il maggior numero di vendite. Questo dato potrebbe essere giustificato dall numero elevato di vendite, e quindi un mercato che sta andando incontro a saturazione ( poche vendite di immobili disponibili) e quindi minore inserimento di annunci. anche qui si potrebbe ipotizzare una possibile correlazione tra l’aumentare del numero di vendite e la riduzione del numero di annunci. Per una possibile conferma di queste ipotesi torna utile osservare l’andamento a Wichita Falls. il numero delle vendite è piatto e lo è anche quello degli annunci. Non c’è la dinamica “vendite in crescita vs. annunci in calo” delle altre città.
library(ggplot2)
library(dplyr)
# 1) Linechart per confronto vendite in periodi storici differenti:
# confronto tra le città: come cambia il numero di vendite per città nei mesi tra il 2010 e il 2014. la linea di tendenza per vedere il trend nel tempo.
ggplot(summary_mydati, aes(x = as.Date(paste(year, month, "01", sep="-")),
y = totally_sales)) +
geom_line(color = "black", alpha = 0.7, size = 1) +
geom_point(size = 0.5, color="tomato") +
geom_smooth(method = "lm", color = "orange", se = FALSE, linewidth = 1) +
facet_wrap(~ city, ncol = 2) +
scale_x_date(
date_breaks = "3 months",
date_labels = "%b-%Y"
) +
labs(
title = "Andamento mensile delle vendite per città (2010–2014)",
subtitle = "Linea rossa = trend line (retta di regressione)",
x = "Mese e anno",
y = "Numero totale di vendite"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
strip.text = element_text(face = "bold")
)
## `geom_smooth()` using formula = 'y ~ x'
#2)linechart variabile a scelta:
#confronto tra le città: come cambia il numero di annunci per città nei mesi tra il 2010 e il #2014
#creo summary
summary_list <- dati %>%
group_by(city,year,month,listings)%>%
summarize(tot_list=sum(listings, na.rm = TRUE),
.group="drop")
## `summarise()` has grouped output by 'city', 'year', 'month'. You can override
## using the `.groups` argument.
summary_list
## # A tibble: 240 × 6
## # Groups: city, year, month [240]
## city year month listings tot_list .group
## <chr> <int> <int> <int> <int> <chr>
## 1 Beaumont 2010 1 1533 1533 drop
## 2 Beaumont 2010 2 1586 1586 drop
## 3 Beaumont 2010 3 1689 1689 drop
## 4 Beaumont 2010 4 1708 1708 drop
## 5 Beaumont 2010 5 1771 1771 drop
## 6 Beaumont 2010 6 1803 1803 drop
## 7 Beaumont 2010 7 1857 1857 drop
## 8 Beaumont 2010 8 1830 1830 drop
## 9 Beaumont 2010 9 1829 1829 drop
## 10 Beaumont 2010 10 1779 1779 drop
## # ℹ 230 more rows
#grafico
ggplot(summary_list, aes(x= as.Date(paste(year,month,"01",sep = "-")),
y=tot_list, color=city))+
geom_line()+
geom_smooth(method = "lm", color = "black", se = FALSE, linewidth = 0.5) +
facet_wrap(~ city, ncol = 2) +
labs(title="N. annunci per città dal 2010 al 2014",
x="anni / mesi ", y=" n.tot annunci")+
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'