library(knitr)
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(moments)
library(kableExtra)
## Warning: il pacchetto 'kableExtra' è stato creato con R versione 4.5.2
##
## Caricamento pacchetto: 'kableExtra'
## Il seguente oggetto è mascherato da 'package:dplyr':
##
## group_rows
library(ggplot2)
df <- read.csv("C:/Users/alessandro.recchia/Downloads/realestate_texas.csv")
Definiamo le variabili singole per comodità.
median_price <- as.numeric(as.character(df$median_price))
sales <- as.numeric(as.character(df$sales))
volume <- as.numeric(as.character(df$volume))
listings <- as.numeric(as.character(df$listings))
months_inventory <- as.numeric(as.character(df$months_inventory))
str(df)
## '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 ...
Il dataframe presenta 240 osservazioni/righe e 8 colonne/variabili.
La tabella presenta 8 colonne in tutto. “city” qualitativa nominale (char) “year” quantitativa continua “mese” qualitativa nominale (char) “sales” quantitativa discreta “volume” quantitativa discreta “median_price” quantitativa continua “listings” quantitativa discreta “months_inventory” quantitativa continua
Considerate le variabili e la struttura dei dati le analisi possono essere condotte attraverso lo studio di time series.
kable(distinct(df, city)) %>%
kable_styling() %>%
column_spec(1, color = "blue")
| city |
|---|
| Beaumont |
| Bryan-College Station |
| Tyler |
| Wichita Falls |
Nel dataset a nostra disposizione la variabile city present 4 possibili valori.
summary(df)
## city year month sales
## Length:240 Min. :2010 Min. : 1.00 Min. : 79.0
## Class :character 1st Qu.:2011 1st Qu.: 3.75 1st Qu.:127.0
## Mode :character Median :2012 Median : 6.50 Median :175.5
## Mean :2012 Mean : 6.50 Mean :192.3
## 3rd Qu.:2013 3rd Qu.: 9.25 3rd Qu.:247.0
## Max. :2014 Max. :12.00 Max. :423.0
## volume median_price listings months_inventory
## Min. : 8.166 Min. : 73800 Min. : 743 Min. : 3.400
## 1st Qu.:17.660 1st Qu.:117300 1st Qu.:1026 1st Qu.: 7.800
## Median :27.062 Median :134500 Median :1618 Median : 8.950
## Mean :31.005 Mean :132665 Mean :1738 Mean : 9.193
## 3rd Qu.:40.893 3rd Qu.:150050 3rd Qu.:2056 3rd Qu.:10.950
## Max. :83.547 Max. :180000 Max. :3296 Max. :14.900
Da una overview dei dati risulta che la variabile “median_price” riporta una asimmetria negativa con mediana superiore alla media dunque avremo una coda lunga a sinistra della distribuzione. Al contrario le variabili “sales”, “volume”, “listings” e “months_inventory” presentano una asimmetria positiva con mediana inferiore alla media.
L’IQR indica la distanza fra il terzo quartile e il primo quartile della variabile in esame. E’ stato calcolato per median_price e sales.
IQR(median_price)
## [1] 32750
IQR(sales)
## [1] 120
Per misurare la variabilità si è deciso di calcolare il coefficiente di variazione di sales e median_price. Concetto poi esteso e rappresentato graficamente.
n<-length(sales)
mu<-mean(sales)
sd(sales)
## [1] 79.65111
sd(median_price)
## [1] 22662.15
Di seguito la funzione individuata per il calcolo del coefficiente di variazione.
CV<-function(x){
return(sd(x)/mean(x)*100)
}
CV(sales)
## [1] 41.42203
n<-length(median_price)
mu<-mean(median_price)
CV(median_price)
## [1] 17.08218
Il Coefficiente di Variazone consente di paragorare la variabilità fra più variabili includendo deviazione standard e media. La variabilità di “median_price” si attesta al 17% della propria media ed è inferiore a alla variabilità della variabile “sales” al 41% della sua media.
Si procede con lo studio della variabilità sfruttando la libreria moments. Di seguito si riportano i grafici con le densità delle variabili qualitative del dataset.
variabili <- c("sales", "median_price","volume", "months_inventory","listings")
for (var in variabili) {
norm_values <- rnorm(length(get(var)), mean(get(var)), sd(get(var)))
plot(density(norm_values), main = paste("Densità di", var))
abline(v = mean(get(var)), col = 3)
cat("CV -> ", var, ":", CV(get(var)), "\n")
cat("Asimmetria -> ", var, ":", skewness(get(var)), "\n")
cat("Curtosi -> ", var, ":", kurtosis(get(var)) - 3, "\n")
}
## CV -> sales : 41.42203
## Asimmetria -> sales : 0.718104
## Curtosi -> sales : -0.3131764
## CV -> median_price : 17.08218
## Asimmetria -> median_price : -0.3645529
## Curtosi -> median_price : -0.6229618
## CV -> volume : 53.70536
## Asimmetria -> volume : 0.884742
## Curtosi -> volume : 0.176987
## CV -> months_inventory : 25.06031
## Asimmetria -> months_inventory : 0.04097527
## Curtosi -> months_inventory : -0.1744475
## CV -> listings : 43.30833
## Asimmetria -> listings : 0.6494982
## Curtosi -> listings : -0.79179
La variabile che presenta maggiore variabilità risulta essere “volume” col coefficiente di variazione del 54% rispetto alla propria media.
L’asimmetria maggiore si riscontra per la variabile “volume” che ha una leggera asimmetria positiva, come confermato anche dal grafico. Anche la variabile “listings” presenta asimmetria positiva.
Calcolando asimmetria e curtosi si può concludere che in linea generale tutte le variabili mostrano una distribuzione abbastanza vicina ad una normale. Lo si deduce dal grafico e dal fatto che entrambi i valori (asimmetria e curtosi) per tutte le variabili sono infatti molto vicini a 0.
Si procede creando delle classi per la variabile sales dal valore 70 al valore 430 con intervalli di 40 unità.
df$sales_classi<- cut(sales, seq(70,430,40))
ni<-table(df$sales_classi)
fi<-ni/n
Ni<- cumsum(ni)
Fi<- Ni/n
distr_freq_classi_sales<-as.data.frame(cbind(ni, fi, Ni, Fi))
kable(distr_freq_classi_sales) %>%
kable_styling() %>%
column_spec(1, color = "blue")
| ni | fi | Ni | Fi | |
|---|---|---|---|---|
| (70,110] | 35 | 0.1458333 | 35 | 0.1458333 |
| (110,150] | 58 | 0.2416667 | 93 | 0.3875000 |
| (150,190] | 46 | 0.1916667 | 139 | 0.5791667 |
| (190,230] | 29 | 0.1208333 | 168 | 0.7000000 |
| (230,270] | 23 | 0.0958333 | 191 | 0.7958333 |
| (270,310] | 26 | 0.1083333 | 217 | 0.9041667 |
| (310,350] | 11 | 0.0458333 | 228 | 0.9500000 |
| (350,390] | 9 | 0.0375000 | 237 | 0.9875000 |
| (390,430] | 3 | 0.0125000 | 240 | 1.0000000 |
Si riporta come sono distribuiti i valori delle sales/vendite nelle varie city/città e classi appena create.
length(df$city)
## [1] 240
length(df$sales_classi)
## [1] 240
kable(table(df$city, df$sales_classi))%>%
kable_styling() %>%
column_spec(1, color = "blue")
| (70,110] | (110,150] | (150,190] | (190,230] | (230,270] | (270,310] | (310,350] | (350,390] | (390,430] | |
|---|---|---|---|---|---|---|---|---|---|
| Beaumont | 5 | 11 | 24 | 13 | 6 | 1 | 0 | 0 | 0 |
| Bryan-College Station | 6 | 13 | 14 | 6 | 4 | 10 | 2 | 3 | 2 |
| Tyler | 0 | 1 | 5 | 10 | 13 | 15 | 9 | 6 | 1 |
| Wichita Falls | 24 | 33 | 3 | 0 | 0 | 0 | 0 | 0 | 0 |
I valori sono poi normalizzati.
length(df$city)
## [1] 240
length(df$sales_classi)
## [1] 240
kable(table(df$city, df$sales_classi)/n)%>%
kable_styling() %>%
column_spec(1, color = "blue")
| (70,110] | (110,150] | (150,190] | (190,230] | (230,270] | (270,310] | (310,350] | (350,390] | (390,430] | |
|---|---|---|---|---|---|---|---|---|---|
| Beaumont | 0.0208333 | 0.0458333 | 0.1000000 | 0.0541667 | 0.0250000 | 0.0041667 | 0.0000000 | 0.0000 | 0.0000000 |
| Bryan-College Station | 0.0250000 | 0.0541667 | 0.0583333 | 0.0250000 | 0.0166667 | 0.0416667 | 0.0083333 | 0.0125 | 0.0083333 |
| Tyler | 0.0000000 | 0.0041667 | 0.0208333 | 0.0416667 | 0.0541667 | 0.0625000 | 0.0375000 | 0.0250 | 0.0041667 |
| Wichita Falls | 0.1000000 | 0.1375000 | 0.0125000 | 0.0000000 | 0.0000000 | 0.0000000 | 0.0000000 | 0.0000 | 0.0000000 |
barplot(distr_freq_classi_sales$ni,
main = "distribuzione di frequenza delle classi di vendita",
xlab = "classi di vendita",
ylab= "frequenze assolute",
ylim = c(0, 60),
col = "blue",
names.arg = rownames(distr_freq_classi_sales),
cex.names = 0.7)
Distribuendo le vendite in classi si nota come le classi con maggiori
osservazioni sono quelle che rappresentano i valori da 110 a 150 e da
150 a 190.
gini.index<- function(e){
ni= table(e)
fi=ni/length(e)
fi2=fi^2
J=length(table(e))
gini=1 -sum(fi2)
gini.normalizzato = gini/((J-1)/J)
return(gini.normalizzato)
}
gini.index(df$sales_classi)
## [1] 0.9499609
gini.index(df$city)
## [1] 1
La distribuzione di frequenza della variabile sales è molto eterogenea, l’indice di Gini normalizzato risulta vicino ad uno. Provando a calcolare l’indice di Gini per la variabile “city” otteniamo il valore massimo di eterogeneità 1.
Calcolo della probabilità
length(df$month)/12
## [1] 20
kable(table(df$month))%>%
kable_styling() %>%
column_spec(1, color = "blue")
| Var1 | Freq |
|---|---|
| 1 | 20 |
| 2 | 20 |
| 3 | 20 |
| 4 | 20 |
| 5 | 20 |
| 6 | 20 |
| 7 | 20 |
| 8 | 20 |
| 9 | 20 |
| 10 | 20 |
| 11 | 20 |
| 12 | 20 |
prob.luglio<-20/240*100
prob.meseanno<-1/240*100
prob.Beaumont<-60/240*100
prob.luglio
## [1] 8.333333
prob.meseanno
## [1] 0.4166667
prob.Beaumont
## [1] 25
La probabilità che una riga/osservazione presa a caso riporti la città di “Beaumont” è del 25%. La probabilità viene calcolata come il rapporto fra casi favorevoli e il numero di casi possibili.
La probabilità che una riga/osservazione presa a caso riporti il mese di luglio è data dal rapporto fra il numero di osservazioni registrate nel mese di luglio e il numero totale delle osservazioni, risulta essere di 8,3%.
La probabilità che riporti il mese di dicembre 2012 è dello 0,4%.
Creazione di nuove variabili.
df$month_year <- paste(df$month, df$year, sep = "/")
df$price_medium<- (df$volume)/(df$sales)*1000000
df$ad_effectiveness<- (df$listings)/(df$sales)
Il rapporto fra i volumi di vendita mensili e le vendite restituisce il prezzo medio di vendita Il rapporto fra il numero totale di annunci e le vendite effettivamente conseguite indica quanto siano efficaci gli annunci.
summary_table <- df %>%
group_by(city) %>%
summarise(avg_effectivness = mean(ad_effectiveness, na.rm = TRUE))
kable(summary_table)%>%
kable_styling() %>%
column_spec(1, color = "blue")
| city | avg_effectivness |
|---|---|
| Beaumont | 10.049329 |
| Bryan-College Station | 8.356607 |
| Tyler | 11.388303 |
| Wichita Falls | 8.092745 |
La variabile city che presenta la miglior efficacia degli annunci è Wichita Falls, in poco più di 8 mesi in media una abitazione viene venduta.
summary_table <- df %>%
group_by(city) %>%
summarise(avg_price_medium = mean(price_medium, na.rm = TRUE))
kable(summary_table)%>%
kable_styling() %>%
column_spec(1, color = "blue")
| city | avg_price_medium |
|---|---|
| Beaumont | 146640.4 |
| Bryan-College Station | 183534.3 |
| Tyler | 167676.8 |
| Wichita Falls | 119430.0 |
La zona con la media dei prezzi più alta è Byran-College Station con più di 183 mila dollari per abitazione.
Analisi condizionata
kable(df %>%
group_by(city) %>%
summarise(across(c(sales, median_price),
list(media = mean, dev.st = sd))))%>%
kable_styling() %>%
column_spec(1, color = "blue")
| city | sales_media | sales_dev.st | median_price_media | median_price_dev.st |
|---|---|---|---|---|
| Beaumont | 177.3833 | 41.48395 | 129988.3 | 10104.993 |
| Bryan-College Station | 205.9667 | 84.98374 | 157488.3 | 8852.235 |
| Tyler | 269.7500 | 61.96380 | 141441.7 | 9336.538 |
| Wichita Falls | 116.0667 | 22.15192 | 101743.3 | 11320.034 |
boxplot1 <- ggplot(data=df)+
geom_boxplot(aes(x=df$city,
y=df$median_price),
col="black",
fill="blue")+
labs(
title = "Boxplot dei valori medi del prezzo per città",
x = "Città",
y = "Valori misurati")
print(boxplot1)
## Warning: Use of `df$city` is discouraged.
## ℹ Use `city` instead.
## Warning: Use of `df$median_price` is discouraged.
## ℹ Use `median_price` instead.
boxplot2 <- ggplot(data=df)+
geom_boxplot(aes(x=df$city,
y=df$sales),
col="red",
fill="lightblue"
) +
labs(
title = "Boxplot delle vendite per città",
x = "Città",
y = "Valori misurati")
print(boxplot2)
## Warning: Use of `df$city` is discouraged.
## ℹ Use `city` instead.
## Warning: Use of `df$sales` is discouraged.
## ℹ Use `sales` instead.
I grafici presentano media e varianza di “median_price” e “sales” rispetto alla variabile “city”, da questo si può dedurre che:
le vendite medie più alte sono state registrate nella città di Tyler tuttavia Bryan-College Station presenta il prezzo medio più alto.
il calcolo delle deviazioni standard della variabile SALES mostra come la varianza più alta si registri per la città Bryan-College Station mentre la minima varianza si riscontra per la città Wichita Falls.
il calcolo delle deviazioni standard della variabile MEDIAN_PRICE mostra una varianza più alta per la città di Wichita Falls e più bassa per la città Bryan-College Station.
Creazione di visualizzazioni con ggplot2
Sommare le vendite per anno
sales_year_city <- df %>%
group_by(year,city) %>%
summarise(year_sales = sum(sales, na.rm = TRUE))
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
ggplot(data=sales_year_city)+
geom_bar(aes(x=year,y=year_sales,fill=city),
stat ="identity")+
labs(title = "Vendite city per anno",x = "Anno", y = "Vendite", fill = "Città")
Eccezion fatta per l’anno 2011 le vendite generali sono sempre cresciute nel corso dei 5 anni. La città con maggiori vendite è Tyler.
Sommare le vendite per mese
sales_month_city <- df %>%
group_by(month,city) %>%
summarise(monthly_sales = sum(sales, na.rm = TRUE))
## `summarise()` has grouped output by 'month'. You can override using the
## `.groups` argument.
ggplot(data=sales_month_city)+
geom_bar(aes(x=month,y=monthly_sales,fill=city),
stat ="identity")+
labs(title = "Vendite city per anno",x = "Mese", y = "Vendite", fill = "Città")
Dall’osservazione del grafico emerge che le vendite osservano una certa stagionalità con vendite maggiori nei mesi di maggio, giugno, luglio ed agosto. Il mese con meno vendite risulta essere gennaio. Questo fenomeno è meno evidente per la città di Wichita Falls.
Generazione di due nuove colonne utili alle visualizzazioni successive: una con mese-anno ed la data del mese.
df$month_year <- paste(df$month, df$year, sep = "/")
df$dates <- as.Date(paste0("1/", df$month_year), format = "%d/%m/%Y")
ggplot(data=df)+
geom_line(aes(x = dates , y = sales, group = city, color = city))+
labs(title="Numero di unità abitative vendute per città negli anni", x="Periodo",y="Vendite", color = "Città")+
scale_x_date(date_breaks = "12 month", date_labels = "%m/%Y", expand = c(0, 0))
Il grafico a linee evidenzia il livello di vendite/sales nel corso del tempo. Anche qui è evidente la stagionalità che caratterizza questa variabile. La città con il più basso livello di vendite negli anni è Wichita Falls mentre quella che registra il più alto volume di vendite è la città di Tyler. Si nota come la città di Wichita Falls non abbia registrato un significativo incremento di vendite nel tempo.
ggplot(df) +
geom_line(aes(x = dates, y = median_price, group = city, color = city)) +
# RETTE DI TREND:
geom_smooth(
aes(x = dates, y = median_price, group = city, color = city),
method = "lm",
se = FALSE,
linetype = "dashed"
) +
labs(
title = "Prezzo medio di vendita negli anni per città",
x = "Periodo",
y = "Prezzo medio di vendita",
color = "Città"
) +
scale_x_date(
date_breaks = "12 month",
date_labels = "%m/%Y",
expand = c(0, 0)
) +
theme(
panel.background = element_rect(fill = "white", color = NA)
)
## `geom_smooth()` using formula = 'y ~ x'
Il grafico evidenzia una crescita dei prezzi per tutte le città. L’unica città con un trend di crescita meno marcato è Beaumont. La città con il prezzi medi più alti è Byron College Station mentre quella con i prezzi più bassi è Wichita Falls.
Conclusioni
Il dataframe presenta 240 osservazioni/righe e 8 colonne/variabili.
La variabile “median_price” riporta una asimmetria negativa con mediana superiore alla media dunque avremo una coda lunga a sinistra della distribuzione mentre le variabili “sales”, “volume”, “listings” e “months_inventory” presentano una asimmetria positiva con mediana inferiore alla media. L’asimmetria positiva massima si registra per la variabile volume.
La variabile che presenta maggiore variabilità risulta essere “volume” col coefficiente di variazione del 54% rispetto alla propria media.
Analizzando asimmetria e curtosi si può concludere che in linea generale tutte le variabili mostrano una distribuzione abbastanza simile ad una normale. Lo si deduce dal grafico e dal fatto che entrambi i valori (asimmetria e curtosi) per tutte le variabili sono infatti molto vicini a 0.
Distribuendo le vendite in classi si nota come le classi con maggiori osservazioni sono le classi da 110 a 150 e da 150 a 190.
La distribuzione di frequenza della variabile sales è molto eterogenea, l’indice di Gini normalizzato risulta vicino ad uno. Provando a calcolare l’indice di Gini per la variabile “city” otteniamo il valore massimo di eterogeneità 1.
La città con annunci più efficaci nel periodo osservato è Wichita Falls, in poco più di 8 mesi in media una abitazione viene venduta.
La zona con la media dei prezzi più alta è Byran-College Station con più di 183 mila dollari per abitazione.
Dall’osservazione di media e varianza di “median_price” e “sales” rispetto alle città si può dedurre che:
Eccezion fatta per l’anno 2011 le vendite generali sono sempre cresciute nel corso dei 5 anni. La città con maggiori vendite è Tyler.
Le vendite sono soggette ad una certa stagionalità con valori maggiori nei mesi di maggio, giugno, luglio ed agosto contro un mese di gennaio molto ridotto. Questo fenomeno è meno evidente per la città di Wichita Falls.
Dall’analisi temporale con trend si evidenzia una crescita dei prezzi per tutte le città. L’unica città con un trend di crescita meno marcato (vedi coefficiente angolare della regressione) è Beaumont.