setwd("C:/Users/guido/Desktop/Python/R/Dataset")
df_texas = read.csv("realestate_texas.csv", sep = ",")
head(df_texas,4)
## 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
Il dataset si compone di 8 variabili:
1 di tipo qualitativo nominale: city
2 di tipo quantitativo discreto / qualitativo ordinale: year e month.
Nota: essendo definite in questo data frame come numeri interi potrebbe essere più corretto considerarle come quantitative, anche se logicamente preferisco considerarle di tipo qualitativo.
3 di tipo quantitativo continuo: volume, median_price, e months_inventory
2 di tipo quantitativo discreto: sales e listings
Le variabili year e month sottointendono una dimensione temporale. Esse possono essere concatenate in un’unica variabile date da utilizzare per la rappresentazione di serie storiche.
La nuova variabile date sarà di tipo data e composta da anno + mese + 01(valore sempre fisso):
library(lubridate)
df_texas$date = make_date(year = df_texas$year,
month =df_texas$month,
day = 1)
head(df_texas,4)
## 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
## date
## 1 2010-01-01
## 2 2010-02-01
## 3 2010-03-01
## 4 2010-04-01
Per capire che tipo di analisi possa essere fatta sulle 8 variabili le istruzioni summary e table risultano utili.
Variabile city:
summary(df_texas$city)
## Length Class Mode
## 240 character character
table(df_texas$city)
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
è una variabile di tipo carattere che contiene il nome di 4 città del Texas. Per ogni città il data frame contiene 60 record. Su questo tipo di variabile non è possibile calcolare indici di posizione, variabilità o forma. Unica eccezione potrebbe essere il calcolo della moda che però risulta poco significativa (ogni città ha lo stesso numero di record).
Variabili year e month:
summary(df_texas$year)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2010 2011 2012 2012 2013 2014
table(df_texas$year)
##
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
summary(df_texas$month)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 3.75 6.50 6.50 9.25 12.00
table(df_texas$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
Sulle variabili year e month può essere fatto un ragionamento molto simile alla variabile city. Pur essendo tecnicamente possibile calcolare degli indici di posizione variabilità e forma, visto che sono di tipo int, essi non hanno molto senso. Per esempio il minimo dei mesi è 1 il massimo è 12 e la media è 6.5 … non sono numeri che portano a del valore aggiunto.
Anche un’analisi delle frequenze non è particolarmente significativa visto che per ogni anno / mese il data frame contiene lo stesso numero di record.
In conclusione le variabili city, year e month saranno importantissime come dimensioni di analisi del data frame, ma analizzate singolarmente non sono di particolare interesse.
Variabili di tipo quantitativo:
Sulle 5 variabili di tipo quantitativo sales, volume, median_price, months_inventory e listings possono essere essere calcolati indici di posizione, variabilità e forma.
Prendiamo, per esempio, la variabile sales:
Alcuni indici di posizione: minimo, 1°quartile, mediana, media, 3° quartile e massimo.
summary(df_texas$sales)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 79.0 127.0 175.5 192.3 247.0 423.0
Alcuni indici di variabilità: range interquartile, varianza e deviazione standard
IQR(df_texas$sales)
## [1] 120
var(df_texas$sales)
## [1] 6344.3
sd(df_texas$sales)
## [1] 79.65111
Un indice di forma: simmetria di fisher
library(moments)
skewness(df_texas$sales)
## [1] 0.718104
Come già detto nel precedente capitolo ha senso calcolare gli indici di posizione, variabilità e forma solo per alcune variabili, che vengono inserite nel vettore variables:
# Variabili sulle quali calcolare gli indici
variables <- c("sales", "volume","median_price","listings","months_inventory")
# Lista vuota che conterrà tutti gli indici per tutte le variabili
stats_list <- list()
Per ogni variabile costrusco un vettore (stats) formato da tutti gli indici:
Nome indice | Significato | Tipo |
---|---|---|
min | Minimo | Posizione |
q1 | Primo quartile | Posizione |
mean | Media | Posizione |
median | Mediana | Posizione |
q3 | Terzo quartile | Posizione |
max | Massimo | Posizione |
range | Range | Variabilità |
iqr | Range interquartile | Variabilità |
variance | Varianza | Variabilità |
sd | Deviazione standard | Variabilità |
cv | Coefficiente di variazione | Variabilità |
skewness | Assimmetria | Forma |
kurtosis | Curtosi | Forma |
library(dplyr)
library(moments)
for (var in variables) {
stats <- df_texas %>%
summarise(across(all_of(var), list(
min = ~ round(min(.),0),
q1 = ~ quantile(., probs = 0.25),
mean = ~ mean(.),
median = ~ median(.),
q3 = ~ quantile(., probs = 0.75),
max = ~ max(.),
range = ~ max(.) - min(.),
iqr = ~ IQR(.),
variance = ~ var(.),
sd = ~ sd(.),
cv = ~ (sd(.) / mean(.)) * 100,
skewness = ~ skewness(.),
kurtosis = ~ kurtosis(.)
), .names = "{fn}")) %>%
mutate(across(everything(), ~ round(., 1)))
# Memorizzo il risultato nella lista
stats_list[[var]] <- stats
}
Costruisco e visualizzo un data frame (df_stats) con tutti i risultati per tutte le variabili:
df_stats <- bind_rows(stats_list, .id = "variable")
library(DT)
datatable(df_stats)
Per le rimanenti variabili viene chiesto di calcolare una distribuzione di frequenza:
table(df_texas$city)
##
## Beaumont Bryan-College Station Tyler
## 60 60 60
## Wichita Falls
## 60
table(df_texas$year)
##
## 2010 2011 2012 2013 2014
## 48 48 48 48 48
table(df_texas$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
Ogni variabile ha una distrubuzione di frequenze uniforme: 60 record per ogni città, 48 record per ogni anno e 20 record per ogni mese.
Per identificare le variabili con maggior variabilità ed assimmetria è possibile utilizzare il data frame df_stats precedentemente calcolato focalizzandosi sulle variabili cv e skewness.
library(dplyr)
df_stats_rid <- df_stats %>% select("variable", "cv", "skewness")
library(DT)
datatable(df_stats_rid)
Per determinare la variabile con maggior variabilità si è utilizzato il coefficiente di variazione perchè permette di raffrontare variabili differenti che utilizzano unità di misura differenti.
Da quanto si può vedere la variabile volume è quella con la maggior variabilità: 53,7%
La variabile con maggior assimmetria è sempre volume con un indice di simmetria di 0.9
Visivamente la densità della variabile volume con simmetria uguale a 0.9 appare così:
library(ggplot2)
ggplot(data=df_texas)+
geom_density(aes(x=volume), col="black",fill="green")+
theme_light()+
labs(title="Densità del volume di vendite",
x="Milioni di $",
y="Densità")
Considero la variabile quantitativa median_price e la suddivido il 21 classi da -10 a 10. In questo modo sarà facile individuare i prezzi più bassi (vicini a -10) quelli intermedi (nell’intorno dello 0) e quelli molto alti (vicini a 10). La nuova variabile si chiamerà median_price_cl:
min_median = min(df_texas$median_price)
max_median = max(df_texas$median_price)
delta_median = max_median - min_median
df_texas$median_price_cl = 10*round((df_texas$median_price-min_median-delta_median/2) / (delta_median/2), digits=1)
La distribuzione di frequenze della nuova variabile è la seguente:
table(df_texas$median_price_cl)
##
## -10 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10
## 1 4 10 7 13 10 9 10 15 11 32 19 19 22 25 16 6 5 5 1
che può essere visivamente rappresentata con ggplot:
ggplot(data=df_texas)+
geom_bar(aes(x=median_price_cl,
fill=city),
position="stack",
stat="count",
col="black")+
labs(title="Distribuzione del prezzo mediano",
x="Classi di prezzo",
y="Frequenze assolute")+
theme_light()
Da questo grafico si può chiaramente vedere che la classe modale è la 1 e che i prezzi mediani sono maggiormente distribuiti nella classi centrali / centro alte.
Calcolando i quantili e la media della nuova variabile si riscontra anche numericamente quanto detto:
quantile(df_texas$median_price_cl)
## 0% 25% 50% 75% 100%
## -10 -2 1 4 10
mean(df_texas$median_price_cl)
## [1] 1.05
Molto interessante è la rappresentazione della variabile city con i colori all’interno dell’istogramma. Si può chiaramente vedere dove vengono venduti gli immobili più cari e quelli meno cari:
Per il calcolo dell’indice di Gini creo una nuova funzione chiamata gini.index:
n_rec = dim(df_texas)[1]
gini.index <- function(x){
ni=table(x)
fi=ni/n_rec
fi2=fi^2
j=length(table(x))
gini=1-sum(fi2)
gini.norm=gini/((j-1)/j)
return(gini.norm)
}
gini.index(df_texas$median_price_cl)
## [1] 0.9766082
Per la variabile median_price_cl si ottiene un valore di circa 0.98, che indica una variabile molto eterogenea.
Ci si poteva aspettare un valore simile anche guardando l’istogramma delle classi che sono tutte rappresentatate tranne la -9.
Come detto nel capitolo 1 le variabili city, year e month hanno una distribuzione di frequenze uniforme. Ciò significa che, prendendo una riga caso del data frame, la probilità di prendere la città Beaumont è identica a quella di prendere le altre città. Essendoci 4 città la probabilità è quindi 0.25. Lo stesso valore poteva essere ottenuto considerando la frequenza assoluta di Beaumont ed il numero totale di record: 60/240=0.25
La probabilità che la riga presa a caso riporti il mese di luglio oppure di dicembre è 1/12 (mesi totali). Anche in questo caso lo stesso valore poteva essere ottenuto considerando la frequenza assoluta del mese ed il numero totale di record: 20/240
Creo una nuova variabile chiamata mean_price che rappresenta il prezzo medio degli immobili in dollari calcolata come rapporto fra il volume di vendite ed il n° di vendite
df_texas$mean_price = 1000000 * df_texas$volume / df_texas$sales
head(df_texas,4)
## 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
## date median_price_cl mean_price
## 1 2010-01-01 7 170626.5
## 2 2010-02-01 2 163796.3
## 3 2010-03-01 -1 157697.8
## 4 2010-04-01 -1 134095.0
L’efficacia degli annunci di vendita può essere calcolata come rapporto percentuale fra il n° di vendite ed il n° di annunci. La massima efficacia sarà rappresentata dal valore 100%, cioè tutti gli annunci si sono concretizzati in una vendita.
Creo innanzitutto, per una migliore leggibilità dei dati, un data frame più compatto, eliminando la variabile mese: df_perf
df_perf = df_texas %>%
group_by(city,year) %>%
summarise(sales=sum(sales),listings=sum(listings))
Aggiungo a questo nuovo data frame una colonna per calcolare l’efficacia degli annunci chiamata perf (performance):
df_perf$perf = 100 * df_perf$sales / df_perf$listings
Rappresento con ggplot il i risultati:
ggplot(data=df_perf)+
geom_col(aes(x=year,y=perf,fill=city), position="dodge")+
theme_light()+
labs(title="Rendimento degli annunci",
x="Anno",
y="Rendimento")
Osservando l’istogramma è possibile fare le seguenti osservazioni:
Wichita Falls risulta la contea con il miglior rendimento negli anni 2010, 2011 e 2012
Bryan-College Station nel 2013 e 2014 ha aumentato decisamente l’efficacia degli annunci superando Wichita Falls
Tyler rimane sempre la città con il rendimento più basso, pur essendo la città con volumi di vendita più alti
Per meglio analizzare il punto 3 è possibile creare un data frame relativo al volume delle vedite per anni & città:
df_volume = df_texas %>%
group_by(city,year) %>%
summarise(volume=sum(volume))
e rappresentarlo in forma di istogramma:
ggplot(data=df_volume)+
geom_col(aes(x=year,y=volume,fill=city),
position="dodge",)+
theme_light()+
labs(title="Volumi di vendita per anni & città",
x="Anno",
y="Milioni di $")
Tyler quindi pur avendo un rendimento degli annunci basso ha dei volumi di vendita molto alti. Viceversa Wichita Falls pur avendo un buon rendimento ha dei volumi di vendita bassi.
Le stesse informazioni possono essere visualizzate in forma diversa mediante un grafico di tipo boxplot:
# Rappresento l'anno come una fattore in modo da poterlo inserire nel campo fill
df_texas$year_cl = factor(df_texas$year)
ggplot(data=df_texas)+
geom_boxplot(aes(x=city,
y=volume,
fill=year_cl))+
theme_light()+
labs(title="Volumi delle vendite mensili per città ed anno",
x="Città",
y="Volume in milioni di $",
fill="Anno")
Questo comportamento è causato da un numero di annunci decisamente differente fra le varie città:
df_listings = df_texas %>%
group_by(city) %>%
summarise(listings=sum(listings))
library(DT)
datatable(df_listings,caption="Totale annunci per città")
Come varia il volume delle vendite nel tempo e per città? Utilizzando la variabile date creata nel primo capitolo è possibile visualizzare la serie storica dei volumi per le 4 città:
ggplot(data=df_texas)+
geom_line(aes(x=date,y=volume,color=city),
lwd=1)+
geom_smooth(aes(x=date,y=volume,color="Tendenza"), method = "lm", se=FALSE,lwd=0.5,linetype = "dashed")+
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months")+
theme_light()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
labs(title="Serie storica dei volumi di vendita",
x="Anno-mese",
y="Milioni di $")
Visivamente forse ancor più chiara la rappresentazione con un istograma a colonne impilate:
ggplot(data=df_texas)+
geom_col(aes(x=date,y=volume,fill=city),
position="stack",)+
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months")+
ylim(0,225)+
theme_light()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
labs(title="Serie storica dei volumi di vendita",
x="Anno-mese",
y="Milioni di $")
Si può concludere che:
I volumi di vendita nei 5 anni analizzati sono in crescita (linea tratteggiata “Tendenza”)
I volumi di vendita fra le 4 città sono decisamente differenti
I volumi di vendita hanno una forte stagionalità
Il punto 2 può essere ancor meglio rappresentato con un grafico a barre normalizzato
ggplot(data=df_texas)+
geom_col(aes(x=date,y=volume,fill=city),
position="fill",)+
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months")+
theme_light()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
labs(title="Volumi di vendita normalizzati",
x="Anno-mese",
y="")
Si può chiaramente vedere per ogni mese quali siano le città con maggiori e minori volumi di vendita.
Per quantificare chiaramente quanto rilevato dai grafici creo dei data frame aggregati per anno, città e mese contenenti il volumi medi delle vendite.
df_volume_by_year = df_texas %>%
group_by(year) %>%
summarise(mean_volume=mean(volume))
df_volume_by_city = df_texas %>%
group_by(city) %>%
summarise(mean_volume=mean(volume))
df_volume_by_month = df_texas %>%
group_by(month) %>%
summarise(mean_volume=mean(volume))
ggplot(data=df_volume_by_year)+
geom_col(aes(x=year,y=mean_volume),fill="green",color="black")+
theme_light()+
geom_text(aes(x=year,y=mean_volume,label=round(mean_volume,1)),
vjust=-1, size=3)+
expand_limits(y=41)+
labs(title="Volumi di vendita medi per anno",
x="Anno",
y="Milioni di $")
L’istogramma conferma quanto detto nel punto 1, anche se il 2011 è stato in leggerissimo calo rispetto al 2010.
ggplot(data=df_volume_by_city)+
geom_col(aes(x=city,y=mean_volume),fill="cyan",color="black")+
theme_light()+
geom_text(aes(x=city,y=mean_volume,label=round(mean_volume,1)),
vjust=-1, size=3)+
expand_limits(y=47)+
labs(title="Volumi di vendita medi per città",
x="Città",
y="Milioni di $")
L’istogramma conferma quanto detto nel punto 2: la città con i maggiori volumi di vendita media è Tyler seguita da Bryan-College Station, Beaumont e Wichita Falls.
ggplot(data=df_volume_by_month)+
geom_col(aes(x=month,y=mean_volume),fill="yellow",color="black")+
theme_light()+
geom_text(aes(x=month,y=mean_volume,label=round(mean_volume,1)),
vjust=-1, size=3)+
expand_limits(y=43)+
scale_x_continuous(breaks=seq(1,12,1))+
labs(title="Volumi di vendita medi per mese",
x="Mese",
y="Milioni di $")
L’istogramma conferma quanto detto nel punto 3: i maggiori volumi di vendita media si hanno nel periodo estivo, in particolare a Giugno.
Mediante dei grafici a barre verrà analizzato il numero totale delle vendite (variabile sales) in maggior dettaglio.
ggplot(data=df_texas)+
geom_col(aes(x=date,y=sales,fill=city),
position="stack",)+
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months")+
theme_light()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
labs(title="Serie storica del n° di vendite",
x="Anno-mese",
y="N° totale di vendite")
Aggregando i dati per anno:
df_sales = df_texas %>%
group_by(city,year) %>%
summarise(sales=sum(sales))
Si ottiene il seguente istogramma:
ggplot(data=df_sales)+
geom_col(aes(x=year,y=sales,fill=city),
position="dodge",)+
theme_light()+
labs(title="N° di vendite per anni & città",
x="Anno",
y="N° totale di vendite")
Si può concludere che la variabile sales ha un comportamento molto simile alla variabile volume, il che è sensato in quanto il volume di vendite è linearmente dipendente dal numero di vendite.
E’ quindi possibile osservare quanto già notato nel capitolo precedente per la variabile volume:
Il numero di vendite nei 5 anni analizzati è in crescita
Il numero di vendite fra le 4 città è decisamente differente e mantiene lo stesso ordinamento visto in precedenza:
Il numero di vendite ha una forte stagionalità
Le differenze che si possono notare fra la variabile volume e la variabile sales dipendono dal prezzo degli immobili, che viene esaminato mediante un grafico di tipo boxplot:
ggplot(data=df_texas)+
geom_boxplot(aes(x=city,
y=median_price,
fill=year_cl))+
theme_light()+
labs(title="Prezzo mediano per città ed anno",
x="Città",
y="Prezzo mediano in $",
fill="Anno")
Viene confermato quanto già detto nel capitolo 1: gli immobili più cari sono a Bryan-College Station, poi Tyler, Beaumont ed infine Wichita Falls.
Wichita Falls è in svantaggio anche per quanto riguarda l’andamento del trend di crescita, meno rilevante rispetto alle altre città.
L’andamento delle vendite può essere analizzato anche mediante un grafico a linee:
ggplot(data=df_texas)+
geom_line(aes(x=date,y=sales,color=city),
lwd=1)+
geom_smooth(aes(x=date,y=sales,color="Tendenza"), method = "lm", se=FALSE,lwd=0.5,linetype = "dashed")+
scale_x_date(date_labels = "%Y-%m", date_breaks = "4 months")+
theme_light()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+
labs(title="Serie storica delle vendite",
x="Anno-mese",
y="N° di vendite")
che conferma quanto già detto in precedenza.
Molto interessante è aggregare i dati per città e mese:
df_sales_by_month = df_texas %>%
group_by(city,month) %>%
summarise(sales=sum(sales))
ggplot(data=df_sales_by_month)+
geom_line(aes(x=month,y=sales,color=city),
lwd=1)+
scale_x_continuous(breaks=seq(1,12,1))+
theme_light()+
labs(title="Vendite per mese & città",
x="Mese",
y="N° di vendite")
Si può notare ancor più chiaramente
la stagionalità delle vendite, in particolar modo per Bryan-College Station e Tyler
il numero di vendite che segue per quasi tutti i mesi l’ordinamento
L’azienda Texas Realty Insights ha un volume di affari che nel periodo 2010 - 2014 è in crescita: da 25.7 milioni di $ del 2010 a 39.8 milioni di $ del 2014.
Per le future scelte strategiche della Texas Realty Insights questi sono i principali risultati ottenuti nelle analisi dei precedenti capitoli:
Le 4 città prese in esame nel data set hanno dei volumi di vendita molto diversi, in ordine decrescente:
Quindi Tyler e Bryan-College Station sono le città più importanti per volumi di vendite, mentre Wichita Falls è quella meno significativa.
Anche i prezzi degli immobili si differenziano molto, sempre partendo dai più elevati:
Il prezzo degli immobili è abbastanza variabile, si va da un prezzo mediano minimo di 73800 $ ad un massimo di 180000 $. I più venduti hanno però un prezzo nella fascia medio alta che è quindi la più redditizia per la Texas Realty Insights.
I volumi di vendita hanno una marcata stagionalità e sono decisamente superiori nel periodo estivo, questo potrebbe essere un utile indicazione per la pianificazione delle risorse aziendali durante l’anno oppure per concentrare maggiormente le proprie campagne di marketing e le inserzioni immobiliari durante questo periodo.
Il rendimento degli annunci di Bryan-College Station è decisamente aumentato negli anni 2013 e 2014 ed ha superato quello di Wichita Falls, che risulta essera la migliore città negli anni 2010, 2011 e 2012. Sarebbe molto importante quindi per la Texas Realty Insights capire le ragioni di questo miglioramento, per magari aumentare il rendimento anche di Tyler, la città con il maggior volume di affari (e rendimento peggiore).
Wichita Falls ha un trend di crescita delle vendite inferiore rispetto alle altre città, sarebbe quindi importante per la Texas Realty Insights capire se è possibile invertire questa tendenza.