I dati presenti in questa analisi sono valori quantitativi relativi al mercato immobiliare del Texas raggruppati per città, mese e anno. Questi tre parametri raggruppano i dati grezzi e possono essere utilizzate per svolgere delle analisi in grado di confrontare tra loro diverse città (parametro qualitativo) o i diversi anni/mesi (parametri quantitativi-qualitativi). In particolare le variabili quantitative sono tutte in scala di rapporti, in particolare di tipo intero per quanto riuarda “sales” e “listings”, a valori continui per quanto riguarda “months_inventory”, “volume” e “median_price”. Su “city”, “month” e “year” è possibile fare una distribuzione di frequenze, anche se emo in seguito ha senso farla sulla somma dei valori di “sales” più che sul numero di record.
Cominciamo concentrandoci su “sales”:
summary(sales)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 79.0 127.0 175.5 192.3 247.0 423.0
dati %>% summarize(media = mean(sales),
dev.sd = sd(sales), IQR = IQR(sales),CV = sd(sales)/mean(sales)*100,
indice.Fisher = skewness(sales), curtosi = kurtosis(sales)-3)
## media dev.sd IQR CV indice.Fisher curtosi
## 1 192.2917 79.65111 120 41.42203 0.718104 -0.3131764
Analogamente possiamo studiare “volume”:
summary(volume)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8.166 17.660 27.062 31.005 40.893 83.547
dati %>% summarize(media = mean(volume),
dev.sd = sd(volume), IQR = IQR(volume), CV = sd(volume)/mean(volume)*100,
indice.Fisher = skewness(volume), curtosi = kurtosis(volume)-3)
## media dev.sd IQR CV indice.Fisher curtosi
## 1 31.00519 16.65145 23.2335 53.70536 0.884742 0.176987
Proseguiamo con “median_price”, “listings” e “months_inventory”:
summary(median_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 73800 117300 134500 132665 150050 180000
dati %>% summarize(media = mean(median_price),
dev.sd = sd(median_price), IQR = IQR(median_price),
CV = sd(median_price)/mean(median_price)*100,
indice.Fisher = skewness(median_price), curtosi = kurtosis(median_price)-3)
## media dev.sd IQR CV indice.Fisher curtosi
## 1 132665.4 22662.15 32750 17.08218 -0.3645529 -0.6229618
summary(listings)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 743 1026 1618 1738 2056 3296
dati %>% summarize(media = mean(listings),
dev.sd = sd(listings), IQR = IQR(listings),
CV = sd(listings)/mean(listings)*100,
indice.Fisher = skewness(listings), curtosi = kurtosis(listings)-3)
## media dev.sd IQR CV indice.Fisher curtosi
## 1 1738.021 752.7078 1029.5 43.30833 0.6494982 -0.79179
summary(months_inventory)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 3.400 7.800 8.950 9.193 10.950 14.900
dati %>% summarize(media = mean(months_inventory),
dev.sd = sd(months_inventory), IQR = IQR(months_inventory),
CV = sd(months_inventory)/mean(months_inventory)*100,
indice.Fisher = skewness(months_inventory), curtosi = kurtosis(months_inventory)-3)
## media dev.sd IQR CV indice.Fisher curtosi
## 1 9.1925 2.303669 3.15 25.06031 0.04097527 -0.1744475
Per “city”, “year” e “month” ha meno senso un analisi di questo tipo, perciò daremo una distribuzione di frequenza:
N = sum(table(city))
ni = table(city)
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(ni, fi, Ni, Fi)
## ni fi Ni Fi
## Beaumont 60 0.25 60 0.25
## Bryan-College Station 60 0.25 120 0.50
## Tyler 60 0.25 180 0.75
## Wichita Falls 60 0.25 240 1.00
N = sum(table(year))
ni = table(year)
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(ni, fi, Ni, Fi)
## 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
N = sum(table(month))
ni = table(month)
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(ni, fi, Ni, Fi)
## 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
Commenti: notiamo come le distribuzioni di frequenza non ci danno alcun dato rilevante. Infatti le rilevazioni sono dati già raggruppati e in particolare ne abbiamo uno per ogni mese per quattro anni, in ciascune delle 4 città analizzate. Per avere dei dati significativi conviene trattare le distribuzioni di frequenza utilizzando il valore “sales” e non il numero di records:
dc = dati %>% group_by(city) %>% summarise(tot_vendite = sum(sales))
N = sum(dc$tot_vendite)
ni = dc$tot_vendite
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(city=dc$city,ni, fi, Ni, Fi)
## city ni fi Ni
## [1,] "Beaumont" "10643" "0.230617551462622" "10643"
## [2,] "Bryan-College Station" "12358" "0.267778981581798" "23001"
## [3,] "Tyler" "16185" "0.350704225352113" "39186"
## [4,] "Wichita Falls" "6964" "0.150899241603467" "46150"
## Fi
## [1,] "0.230617551462622"
## [2,] "0.49839653304442"
## [3,] "0.849100758396533"
## [4,] "1"
dy = dati %>% group_by(year) %>% summarise(tot_vendite = sum(year))
N = sum(dy$tot_vendite)
ni = dy$tot_vendite
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(year = dy$year, ni, fi, Ni, Fi)
## year ni fi Ni Fi
## [1,] 2010 96480 0.1998012 96480 0.1998012
## [2,] 2011 96528 0.1999006 193008 0.3997018
## [3,] 2012 96576 0.2000000 289584 0.5997018
## [4,] 2013 96624 0.2000994 386208 0.7998012
## [5,] 2014 96672 0.2001988 482880 1.0000000
dm = dati %>% group_by(month) %>% summarise(tot_vendite = sum(month))
N = sum(dm$tot_vendite)
ni = dm$tot_vendite
fi = ni/N
Ni = cumsum(ni)
Fi = Ni/N
cbind(month = dm$month, ni, fi, Ni, Fi)
## month ni fi Ni Fi
## [1,] 1 20 0.01282051 20 0.01282051
## [2,] 2 40 0.02564103 60 0.03846154
## [3,] 3 60 0.03846154 120 0.07692308
## [4,] 4 80 0.05128205 200 0.12820513
## [5,] 5 100 0.06410256 300 0.19230769
## [6,] 6 120 0.07692308 420 0.26923077
## [7,] 7 140 0.08974359 560 0.35897436
## [8,] 8 160 0.10256410 720 0.46153846
## [9,] 9 180 0.11538462 900 0.57692308
## [10,] 10 200 0.12820513 1100 0.70512821
## [11,] 11 220 0.14102564 1320 0.84615385
## [12,] 12 240 0.15384615 1560 1.00000000
Possiamo identificare la variabile “volume” come quella con la variabilità più alta in quanto possiede il coefficiente di variazione (CV) più elevalto. Questo criterio risulta efficace perché ogni variabile è strettamente positiva e in scala di rapporti. Inoltre la distribuzione più asimmetrica può essere determinata guardando la variabile con indice di asimmetria di Fisher più alto in valore assoluto, ovvero ancora “volume”. In particolare è a distribuzione asimmetrica positiva. Creiamo ora delle classi per la variabile “sales”. Considerando il valore minimo e massimo creiamo un passo adatto ad avere un numero adeguato di classi (che scegliamo essere 8).
interval = (max(sales)-min(sales))/8
breaks = seq(from = min(sales), to = max(sales), by = interval)
classi = cut(sales,breaks = breaks)
freq = table(classi)
barplot(freq)
Calcoliamo ora l’indice di eterogeneità di Gini su queste classi
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)}
gini.index(classi)
## [1] 0.9472619
Dato che l’indice di eterogeneità assume valori prossimi all’1 possiamo dire che siamo nel caso di elevata eterogeneità. Calcoliamo ora la probabilità che presa una riga a caso di questo dataset, essa riporti la città di “Beaumont”. Nota che è sufficente considerare la frequenza relativa associata ma qui ripresentiamo il calcolo
x = sum(table(city))
table(city)["Beaumont"]/x
## Beaumont
## 0.25
Ora facciamo lo stesso con il mese di Luglio
table(month)["7"]/x
## 7
## 0.08333333
Infine per dicembre 2012
table(month, year)["12", "2012"]/x
## [1] 0.01666667
Creiamo ora due nuove colonne: una con i prezzi medi degli immobili e una che misuri l’efficacia degli annunci di vendita
dati$avg_price = volume*1000000/sales
dati$sell_rate = sales/listings
Questo ultimo dato misura il rapporto tra immobili venduti e immobili listati tramite annunci attivi. Più è alto e più ci sono state vendite in proporzione agli annunci, misurando così l’efficacia di essi. Passiamo ora alle visualizzazione utilizzando ggplot2
ggplot(data= dati)+
geom_boxplot(aes(x = city, y = median_price))+
labs(title = "Boxplot per città", x = "città", y = "prezzo mediano (in dollari)")
ggplot(data= dati)+
geom_col(aes(x=city,y = sales), fill = "blue")+
labs(title = "Vendite per città", x = "città", y = "numero totale vendite")+
theme_classic()
ggplot(data= dati)+
geom_col(aes(x=month,y = sales), fill = "red")+
labs(title = "Vendite per mese", x = "mesi", y = "numero totale vendite")+
theme_classic()
dati$month <- factor(dati$month, levels = 1:12)
ggplot(data= dati)+
geom_col(aes(x=city,y = sales, fill = month), position="stack")+
labs(title = "Vendite per città", x = "Città", y = "numero totale vendite")+
scale_fill_manual(values = c("1" = "#353436",
"2" = "#1b98e0",
"3" = "orange",
"4" = "red",
"5" = "green",
"6" = "blue",
"7" = "pink",
"8" = "yellow",
"9" = "purple",
"10" = "violet",
"11" = "brown",
"12" = "grey"))
ggplot(data= dati)+
geom_col(aes(x=city,y = sales, fill = month), position = "fill")+
labs(title = "Vendite per città(percentuali)", x = "Città", y = "numero totale vendite")+
scale_fill_manual(values = c("1" = "#353436",
"2" = "#1b98e0",
"3" = "orange",
"4" = "red",
"5" = "green",
"6" = "blue",
"7" = "pink",
"8" = "yellow",
"9" = "purple",
"10" = "violet",
"11" = "brown",
"12" = "grey"))+
scale_y_continuous(labels = scales::percent)
dati_aggregati = dati %>%
group_by(year) %>%
summarise(sales = sum(sales, na.rm = TRUE), volume = sum(volume, na.rm = TRUE))
ggplot(data=dati_aggregati)+
geom_line(aes(x = year, y = sales), col = "green", lwd = 1)+
geom_point(aes(x = year, y = sales), col = "green4")+
labs(x = "Anni", y = "Numero vendite", title = "Andamento vendite")
ggplot(data=dati_aggregati)+
geom_line(aes(x = year, y = volume), col = "cyan", lwd = 1)+
geom_point(aes(x = year, y = volume), col = "blue")+
labs(x = "Anni", y = "Ricavi (in milioni di dollari)", title = "Andamento ricavi")
dati_2 = dati %>%
group_by(year, city) %>%
summarise(sales = sum(sales, na.rm = TRUE))
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
ggplot(data = dati_2) +
geom_line(aes(x = year, y = sales, color = city), size = 1) +
geom_point(aes(x = year, y = sales, color = city), size = 2) +
labs(title = "Andamento vendite per anno per città",
x = "Anno", y = "Vendite totali", color = "Città") +
theme_minimal()
## 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.
detach(dati)
Commenti finali: dall’analisi dei boxplot per le città emerge come il prezzo mediano sia differente in maniera significativa nelle diverse città. Questo ci permette di avere un’idea chiara di come il costo degli immobili sia differente da città in città. Non solo: l’analisi finale con i line chart ci permette di osservare una crescita costante dopo la diminuzione nel 2011 se aggreghiamo i dati. Se invece li dividiamo per città notiamo che questo non è più vero: Tyler ha una crescita costante e a numeri elevati, Beaumont e Bryan-Collage Station seguono il trend generale e infine Wichita Falls ha un andamento più piatto e addirittura in descrescita rispetto ai dati iniziali. Come periodo di vendita principale possiamo identificare il periodo da Maggio ad agosto grazie ai bar chart.