Nel dataset presentato possiamo trovare questi tipi di variabili:
Cities : Variabile Qualitativa Nominale
Year: Variabile Qualitativa Ordinale (continua);
Months: Variabile Qualitativa Nominale;
Sales: Variabile Quantitativa Discreta;
Volume: Variabile Quantitativa Continua;
Median price: Variabile Quantitativa Continua;
Listings: Variabile Quantitativa Discreta;
Months Inventory: Variabile Quantitativa Continua.
Abbiamo come variabili del tempo: year, month, e months_inventory, che possiamo utilizzare per avere una rappresentazione più specifica nel tempo delle azioni immobiliari delle varie città.
Parto dal creare un summary delle variabili un pò più generali, quindi year, month e sales, a mio avviso.
Qui creo delle funzioni che possono essere utili:
library(ggplot2)
library(dplyr)
##
## Caricamento pacchetto: 'dplyr'
## I seguenti oggetti sono mascherati da 'package:stats':
##
## filter, lag
## I seguenti oggetti sono mascherati da 'package:base':
##
## intersect, setdiff, setequal, union
library(knitr)
library(moments)
options(scipen = 999)
df = read.csv("realestate_texas.csv")
cv = function(x){
return(sd(x)/mean(x)*100)
}
geometric.mean = function(x){
return(prod(x)**(1/length(x)))
}
armonic.mean = function(x){
return(1/sum(1/x)/length(x))
}
gini.idx = function(x){
ni = table(x)
fi = ni / length(x)
fi2 = fi ** 2
J = length(ni)
gini = 1 - sum(fi2)
gini.norm = gini / ((J - 1) / J)
return(gini.norm)
}
Qui ho calcolato per ogni variabile quei valori che possono risultare utili secondo me per capire meglio la loro distribuzione e la loro varianza.
)
# Year
summary(df$year)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2010 2011 2012 2012 2013 2014
iqr_year = (max(df$year) - min(df$year))
cv_year = cv(df$year)
kur_year = kurtosis(df$year)
kable(cbind(iqr_year, cv_year, kur_year))# cv = Variabilità Moderata - kur = Distribuzione Leptocurtica
| iqr_year | cv_year | kur_year |
|---|---|---|
| 4 | 0.0704358 | 1.7 |
#Month
summary(df$month)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 3.75 6.50 6.50 9.25 12.00
iqr_month = (max(df$month) - min(df$month))
kur_month = kurtosis(df$month) - 3
kable(cbind(iqr_month, kur_month)) # kur = Distribuzione Platicurtica
| iqr_month | kur_month |
|---|---|
| 11 | -1.216783 |
# Sales
summary(df$sales)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 79.0 127.0 175.5 192.3 247.0 423.0
weigh.mean_sales = weighted.mean(df$sales)
arm.mean_sales = armonic.mean(df$sales)
var_sales = var(df$sales)
cv_sales = cv(df$sales)
iqr_sales = IQR(df$sales)
gini_sales = gini.idx(df$sales)
skew_sales = skewness(df$sales)
kur_sales = kurtosis(df$sales) - 3
kable(cbind(weigh.mean_sales, arm.mean_sales, var_sales, cv_sales, iqr_sales, gini_sales, skew_sales, kur_sales))
| weigh.mean_sales | arm.mean_sales | var_sales | cv_sales | iqr_sales | gini_sales | skew_sales | kur_sales |
|---|---|---|---|---|---|---|---|
| 192.2917 | 0.002829 | 6344.3 | 41.42203 | 120 | 0.998379 | 0.718104 | -0.3131764 |
# var = Alta varianza, cv = variabilità molto alta, gini = l'eterogeneità quasi massima, skew = leggera distribuzione asimmetrica positiva, kur = distribuzione platicurtica
# Volume
summary(df$volume)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8.166 17.660 27.062 31.005 40.893 83.547
weigh.mean_volume = weighted.mean(df$volume)
arm.mean_volume = armonic.mean(df$volume)
var_volume = var(df$volume)
cv_volume = cv(df$volume)
iqr_volume = IQR(df$volume)
gini_volume = gini.idx(df$volume)
skew_volume = skewness(df$volume)
kur_volume = kurtosis(df$volume) - 3
kable(cbind(weigh.mean_volume, arm.mean_volume, var_volume, cv_volume, iqr_volume, gini_volume, skew_volume, kur_volume))
| weigh.mean_volume | arm.mean_volume | var_volume | cv_volume | iqr_volume | gini_volume | skew_volume | kur_volume |
|---|---|---|---|---|---|---|---|
| 31.00519 | 0.0004026 | 277.2707 | 53.70536 | 23.2335 | 0.9999484 | 0.884742 | 0.176987 |
# var = alta varianza, cv = variabilità molto alta, gini = eterogeneità quasi massima, skew = leggera distribuzione asimmetrica positiva, kur = distribuzione leptocurtica
# Median Price
summary(df$median_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 73800 117300 134500 132665 150050 180000
weigh.mean_median_price = weighted.mean(df$median_price)
arm.mean_median_price = armonic.mean(df$median_price)
cv_median_price = cv(df$median_price)
iqr_median_price = IQR(df$median_price)
gini_median_price = gini.idx(df$median_price)
skew_median_price = skewness(df$median_price)
kur_median_price = kurtosis(df$median_price) - 3
kable(cbind(weigh.mean_median_price, arm.mean_median_price, iqr_median_price, gini_median_price, skew_median_price, kur_median_price))
| weigh.mean_median_price | arm.mean_median_price | iqr_median_price | gini_median_price | skew_median_price | kur_median_price |
|---|---|---|---|---|---|
| 132665.4 | 2.228808 | 32750 | 0.9992672 | -0.3645529 | -0.6229618 |
# cv = variabilità molto alta, gini = eterogeneità quasi massima, skew = leggera distribuzione asimetrica negativa, kur = distribuzione platicurtica
# Listings
summary(df$listings)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 743 1026 1618 1738 2056 3296
weigh.mean_listings = weighted.mean(df$listings)
arm.mean_listings = armonic.mean(df$listings)
var_listings = var(df$listings)
cv_listings = cv(df$listings)
iqr_listings = IQR(df$listings)
gini_listings = gini.idx(df$listings)
skew_listings = skewness(df$listings)
kur_listings = kurtosis(df$listings) - 3
kable(cbind(weigh.mean_listings, arm.mean_listings, var_listings, cv_listings, iqr_listings, gini_listings, skew_listings, kur_listings))
| weigh.mean_listings | arm.mean_listings | var_listings | cv_listings | iqr_listings | gini_listings | skew_listings | kur_listings |
|---|---|---|---|---|---|---|---|
| 1738.021 | 0.0251666 | 566569 | 43.30833 | 1029.5 | 0.9996201 | 0.6494982 | -0.79179 |
# var = alta varianza, cv = varaibiità molto alta, gini = eterogeneità quasi massima, skew = leggera distribuzione asimmetrica positiva, kur = distribuzione platicurtica
# Months Inventory
summary(df$months_inventory)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 3.400 7.800 8.950 9.193 10.950 14.900
iqr_months_inventory = (max(df$months_inventory) - min(df$months_inventory))
var_months_inventory = var(df$months_inventory)
kur_months_inventory = kurtosis(df$months_inventory) - 3
kable(cbind(iqr_months_inventory, var_months_inventory, kur_months_inventory))
| iqr_months_inventory | var_months_inventory | kur_months_inventory |
|---|---|---|
| 11.5 | 5.306889 | -0.1744475 |
distr_freq = cbind(city = df$city, median_price = df$median_price, listings = df$listings, months_inv = df$months_inventory)
Possiamo notare come spesso ci ritroviamo che l’indice di gini punta alla eterogeneità quasi massima, questo è molto probabilmente perchè questi tipi di variabili hanno alta varianza, che porta l’indice di gini ad aumentare sempre di più fino all’eterogeneità massima.
per la skewness e la kurtosis, possiamo notare che l’unica variabile che porta ad una distribuzione asimmetrica negativa è la mediana dei prezzi, questo porterà la sua distribuzione ad avere una coda più lunga verso la sinistra. Così come la variabile volume che è l’unica con la kurtosis leptocurtica, ovvero ha distribuzione con il picco più alto e stretta ai lati rispetto ad una distribuzione normale.
Ora cerchiamo di capire quale sia la variabile con la più alta variabilità. Per farlo, ho creato un piccolo data frame da utilizzare in ggplot, così da avere una rappresentazione grafica delle variabilità calcolate sopra.
# Variabile con più alta variabilità
df_var = data.frame(variabile = c("volume", "median_price", "sales", "listings"), variabilità = c(var_volume, var_months_inventory, var_sales, var_listings))
ggplot(data = df_var)+
geom_bar(aes(x = variabile, y = variabilità, fill = variabile), stat = "identity")+
scale_y_log10()+
theme_minimal()+
labs(
title = "Variabilità delle variabili",
x = "Variabili",
y = "Variabilità",
fill = "Variabili"
)
Notiamo quindi che, come avevamo potuto intuire dai risultati stampati precedentemente, la variabile con variabilità più alta è la variabile “listings”, con a secondo posto sales.
Per questo punto, ho deciso di fare una distribuzione di classi utilizzando la variabile sales
df$sales_classes = cut(df$sales, breaks = 5)
sales_classes_table = table(df$sales_classes)
kable(sales_classes_table)
| Var1 | Freq |
|---|---|
| (78.7,148] | 84 |
| (148,217] | 77 |
| (217,285] | 41 |
| (285,354] | 27 |
| (354,423] | 11 |
ggplot(data = df)+
geom_bar(aes(x = sales_classes, fill = city),
col = "black")+
theme_minimal()+
labs(
title = "Variabile sales in classi per città",
x = "Sales",
y = "Conteggio",
fill = "Città"
)
kable(gini_sales)
| x |
|---|
| 0.998379 |
Dal grafico notiamo come la variabile delle sales della classe più bassa è molto più alta delle altre, sopratutto per la città di Beaumont mentre nelle ultime due classi, per le zone con più vendita, il range di città è diminuito a solamente Bryan-College Station e Tyler.
Possiamo notare finalmente che l’indice di gini della variabilità sales porta a pensare che ci sia un indice di eterogeneità quasi massima e quindi equidistribuzione.
Per fare questo calcolo abbiamo bisogno di solamente una formula, ovvero il numero del numero di osservazioni per città ed il numero totale di osservazioni, quindi la length del dataset.
Ottenuti questi due dobbiamo semplicemente dividerli, così possiamo ottenere i nostri risultati. L’unica differenza sta nel calcolo del mese di dicembre nell’anno del 2012, in cui alla fine dopo aver ottenuto le probabilità per l’anno e mese singolarmente, dobbiamo moltiplicarli tra loro.
get_probs = function(x){
sample = sample(x, 1000000, replace = TRUE)
table = table(x)
n = length(x)
probs = table[1] / n
return(probs)
}
prob_city = get_probs(df$city)
prob_month = get_probs(df$month)
prob_year = get_probs(df$year)
prob_year_month = prob_month * prob_year
kable(cbind(prob_city, prob_month, prob_year_month))
| prob_city | prob_month | prob_year_month | |
|---|---|---|---|
| Beaumont | 0.25 | 0.0833333 | 0.0166667 |
Per il calcolo del prezzo medio possiamo semplicemente moltiplicare la colonna del volume per l’unità di misura del prezzo mediano, che per noi è in milioni. quindi una volta ottenuto il volume in milioni possiamo dividerlo al prezzo mediano ed ottenere la media.
Per ottenere l’efficienza degli annunci invece basta dividere il numero degli immobili venduti con successo quindi sales, al listings degli immobili, poi moltiplicarlo per 100 così da ottenere la percentuale.
Di seguito possiamo vedere il grafico della densità di questi, dove possiamo notare una buona differenza tra tutte le città.
df$mean_price = (df$volume * 1000000) / df$median_price
summary(df$mean_price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 86.46 146.62 201.71 224.45 285.14 519.04
df$effectiveness = (df$sales / df$listings) * 100
ggplot(data = df)+
geom_density(aes(x = effectiveness, col = city))+
theme_minimal()+
xlab("Efficenza in %")+
ylab("Densità")+
labs(
title = "Efficenza degli annunci per città",
col = "Città"
)
Per fare delle analisi variate basate sull’anno, città e mese, ho deciso di rendere la funzione group by di dyplir in una funzione, dove poter customizzare a seconda dei casi i vari raggruppamenti per sales e volume. In seguito, ho anche creato una funzione per creare grafici simili per ognuna di queste combinazioni.
group.by = function(x, group, group2){
group = x %>%
group_by({{group}},{{group2}}) %>%
summarise(mean_sales = mean(sales),
mean_volume = mean(volume), .groups = "keep")
return(group)
}
year_city = group.by(df, city, year)
city_group = group.by(df, city, NULL)
year_group = group.by(df, year, NULL)
month_group = group.by(df, month, NULL)
month_year = group.by(df, month, year)
bar_plot = function(data, x, x2, y, y2, title, xlabs, ylabs, legend_lab){
ggplot(data = data, aes(x = interaction({{x}}, {{x2}}), y = {{y}}, fill = {{y}}))+
geom_bar(stat = "identity", position = "dodge")+
geom_bar(aes(y = {{y2}}, fill = {{y2}}), stat = "identity", position = "dodge")+
theme_minimal()+
theme(axis.text.x = element_text(angle = 45, hjust = 1))+
labs(title = title,
x = xlabs,
y = ylabs,
fill = legend_lab)
}
bar_plot(year_city, city, year, mean_sales, mean_volume, "Media Sales e Volume negli Anni nelle Città", "Città/Anno", "Medie", "Medie")
bar_plot(month_year, month, year, mean_sales, mean_volume, "Media Sales e Volume nel tempo", "Tempo", "Medie", "Medie")
bar_plot(city_group, city, city, mean_sales, mean_volume, "Media Sales e Volume per città", "Città", "Medie", "Medie")
bar_plot(year_group, year, year, mean_sales, mean_volume, "Media Sales negli anni", "Anni", "Medie", "Medie")
bar_plot(month_group, month, month, mean_sales, mean_volume, "Media Sales nei mesi", "Mesi", "Medie", "Medie")
kable(summary(year_city))
| city | year | mean_sales | mean_volume | |
|---|---|---|---|---|
| Length:20 | Min. :2010 | Min. :106.2 | Min. :12.05 | |
| Class :character | 1st Qu.:2011 | 1st Qu.:138.9 | 1st Qu.:19.56 | |
| Mode :character | Median :2012 | Median :184.3 | Median :29.62 | |
| NA | Mean :2012 | Mean :192.3 | Mean :31.01 | |
| NA | 3rd Qu.:2013 | 3rd Qu.:238.1 | 3rd Qu.:39.92 | |
| NA | Max. :2014 | Max. :331.5 | Max. :59.60 |
kable(summary(month_year))
| month | year | mean_sales | mean_volume | |
|---|---|---|---|---|
| Min. : 1.00 | Min. :2010 | Min. :105.2 | Min. :15.16 | |
| 1st Qu.: 3.75 | 1st Qu.:2011 | 1st Qu.:155.3 | 1st Qu.:23.39 | |
| Median : 6.50 | Median :2012 | Median :185.9 | Median :29.37 | |
| Mean : 6.50 | Mean :2012 | Mean :192.3 | Mean :31.01 | |
| 3rd Qu.: 9.25 | 3rd Qu.:2013 | 3rd Qu.:224.6 | 3rd Qu.:36.98 | |
| Max. :12.00 | Max. :2014 | Max. :294.2 | Max. :53.81 |
kable(summary(city_group))
| city | mean_sales | mean_volume | |
|---|---|---|---|
| Length:4 | Min. :116.1 | Min. :13.93 | |
| Class :character | 1st Qu.:162.1 | 1st Qu.:23.08 | |
| Mode :character | Median :191.7 | Median :32.16 | |
| NA | Mean :192.3 | Mean :31.01 | |
| NA | 3rd Qu.:221.9 | 3rd Qu.:40.09 | |
| NA | Max. :269.8 | Max. :45.77 |
kable(summary(year_group))
| year | mean_sales | mean_volume | |
|---|---|---|---|
| Min. :2010 | Min. :164.1 | Min. :25.16 | |
| 1st Qu.:2011 | 1st Qu.:168.7 | 1st Qu.:25.68 | |
| Median :2012 | Median :186.1 | Median :29.27 | |
| Mean :2012 | Mean :192.3 | Mean :31.01 | |
| 3rd Qu.:2013 | 3rd Qu.:211.9 | 3rd Qu.:35.15 | |
| Max. :2014 | Max. :230.6 | Max. :39.77 |
kable(summary(month_group))
| month | mean_sales | mean_volume | |
|---|---|---|---|
| Min. : 1.00 | Min. :127.4 | Min. :19.00 | |
| 1st Qu.: 3.75 | 1st Qu.:166.3 | 1st Qu.:26.52 | |
| Median : 6.50 | Median :185.9 | Median :29.49 | |
| Mean : 6.50 | Mean :192.3 | Mean :31.01 | |
| 3rd Qu.: 9.25 | 3rd Qu.:232.5 | 3rd Qu.:38.29 | |
| Max. :12.00 | Max. :243.6 | Max. :41.30 |
Per il passaggio 8 ho deciso di esplorare semplicemente un paio di grafici in maniera che potessi confrontare bene le parti più importanti del dataset. Ad esempio nel primo ho voluto controllare per ogni anno la quantità di vendite effettuate per ogni città, notando che le vendite più grandi ci sono state nella città di Beaumont, e che ogni anno, circa lo stesso periodo, le vendite aumentano generalmente per tutte le città. Nel secondo invece, il volume per ogni mese ogni anno, dove possiamo vedere che la città di Beaumont è sempre in cima, e che se guardiamo bene in confronto con il primo grafico, anche questa variabile è strettamente collegata al periodo dell’anno, infatti, nello stesso periodo del primo grafico dove le vendite aumentavano, c’è un aumento anche per il valore delle vendite totali. Nell’ultimo ho voluto esplorare come si comporta il prezzo mediano con le sue distribuzioni dei valori, notiamo che nel corso degli anni non cambiano troppo, e che nonostante tutto, la città di Beaumont sembra essere quella con circa la stessa grandezza, mentre Wichita Falls, che è la città con minore prezzo mediano, comprende anche un range più alto dello stesso.
ggplot(data = df)+
geom_bar(aes(x = month, y = sales, fill = city),
stat = "identity")+
scale_x_continuous(breaks = seq(1, 12, 1))+
scale_y_continuous(breaks = seq(0, 1300, 100))+
ylab("Sales")+
xlab("Month")+
facet_wrap(~ year)+
theme_minimal()+
labs(
title = "Sales ogni mese per città nel corso degli anni",
x = "Mesi",
y = "Sales",
fill = "Città"
)
ggplot(data = df)+
geom_bar(aes(x = month, y = volume, fill = city),
stat = "identity")+
scale_x_continuous(breaks = seq(1, 12, 1))+
scale_y_continuous(breaks = seq(0, 300, 20))+
ylab("Volume")+
xlab("Month")+
facet_wrap(~ year)+
theme_minimal()+
labs(
title = "Valore vendite totali ogni mesi per città nel corso degli anni",
x = "Mesi",
y = "Valore totale vendite",
fill = "Città"
)
ggplot(data = df)+
geom_boxplot(aes(x = median_price, fill = city))+
theme_minimal()+
facet_wrap(~ df$year)+
labs(
title = "Prezzo mediano degli immobili nelle città ogni anno",
x = "Prezzo mediano",
y = "Distribuzione del Valore"
)
Per concludere, in questa analisi del dataset, abbiamo scoperto che in media, le persone hanno preferito comprare immobili più grandi, nonostante il prezzo, nei periodi centrali dell’anno, ovvero tra Maggio e Luglio, e specificatamente che siano nelle città di Beaumont e Bryan College Station.
Abbiamo scoperto che gli annunci che hanno portato a più vendite si possono ritrovare nelle città di Tyler e Whichita Falls, che riportano la percentuale più alta di vendite effettuate nel totale.
Infine, scopriamo con i dati in questo dataset che se dovessimo cercare un immobile in un periodo randomico dell’anno, avremmo una distribuzione di possibilità molto equilibrata in generale, per ogni città.