Una volta installati i pacchetti, importo i pacchetti necessari all’analisi:

library(ggplot2)
library(dplyr)
library(moments)
library(stringr)
library(rstudioapi)

Importo il database e verifico se le prime righe del dataset sono state caricate correttamente

texas <- read.csv("Real Estate Texas.csv")
head(texas, 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

1. Indica il tipo di variabili contenute nel dataset

Il dataframe è composto da 8 variabili e 240 osservazioni:

  • city: (Character) Qualitativa nominale. Rappresenta le città in cui sono stati raccolti i dati;
  • year: (Integer) Variabile quantitativa, ma in questo caso qualitativa ordinale. Si riferisce all’anno;
  • month: (Integer) Qualitativa nominale ciclica Poché presenta 12 livelli. Si riferisce ai mesi;
  • sales: (Integer) Quantitativa discreta. Mostra il numero di vendite immobiliari effettuate in un determinato mese/anno;
  • volume: (Integer) Quantitativa continua. Rappresenta il volume totale delle vendite in milioni di dollari (in M$);
  • median_price: (Numeric) Quantitativa continua. Indica il prezzo mediano delle proprietà vendute in un determinato mese/anno (in $);
  • listings: (Numeric) Quantitativa discreta. Rappresenta il numero di annunci immobiliari attivi in un determinato mese/anno;
  • months_inventory: (Numeric) Quantitativa continua. Mostra nei mesi e anni il tempo che intercorre tra la vendita e l’inserzione pertanto è un indicatore temporale.

2. 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

Per poter analiizare gli indici di posizione,variazione, forma e distribuzione di frequenza devo scegliere delle variabili quantitative pertanto le variabili sono: sales, volume, median_price, listings e months_inventory.

Per prima cosa definisco v.coeff per calcolare il coefficiente di variazione:

v.coeff <- function(x){
  return(sd(x)/mean(x)*100)
}

Definisco quindi un nuovo dataframe newdata.df dove vi sono gli indici. La funzione attach() mi permette di accedere facilmente alle variabili:

attach(texas)

texas.colnames <- colnames(texas)[4:8]
indexes = c("min", "1st quartile", "median", "3rd quartile", "max", "range",
            "IQR", "mean", "std.dev", "var.coeff", "skewness", "kurtosis")
newdata.df <- data.frame(matrix(nrow = 0, ncol = length(indexes)))
colnames(newdata.df) = indexes
for (obj.name in texas.colnames) {
  obj <- pull(texas,obj.name)
  quartiles = as.numeric(quantile(obj))
  df <- texas %>%
    summarise(range=max(obj)-min(obj),
              IQR=IQR(obj),
              mean=mean(obj),
              dev.st=sd(obj),
              var.coeff=v.coeff(obj),
              skewness=skewness(obj),
              kurtosis=kurtosis(obj)-3)
  row = c(quartiles,as.numeric(df))
  newdata.df <- rbind(newdata.df, row)
}
newdata.df <- cbind(texas.colnames,newdata.df)
colnames(newdata.df) = c("variable", indexes)
newdata.df
##           variable       min 1st quartile      median 3rd quartile        max
## 1            sales    79.000     127.0000    175.5000      247.000    423.000
## 2           volume     8.166      17.6595     27.0625       40.893     83.547
## 3     median_price 73800.000  117300.0000 134500.0000   150050.000 180000.000
## 4         listings   743.000    1026.5000   1618.5000     2056.000   3296.000
## 5 months_inventory     3.400       7.8000      8.9500       10.950     14.900
##        range        IQR         mean      std.dev var.coeff    skewness
## 1    344.000   120.0000    192.29167    79.651111  41.42203  0.71810402
## 2     75.381    23.2335     31.00519    16.651447  53.70536  0.88474203
## 3 106200.000 32750.0000 132665.41667 22662.148687  17.08218 -0.36455288
## 4   2553.000  1029.5000   1738.02083   752.707756  43.30833  0.64949823
## 5     11.500     3.1500      9.19250     2.303669  25.06031  0.04097527
##     kurtosis
## 1 -0.3131764
## 2  0.1769870
## 3 -0.6229618
## 4 -0.7917900
## 5 -0.1744475

Scelgo la variabile city e mi determino la distribuzione di frequenza

N=dim(texas)[1]
table(texas["city"])
## city
##              Beaumont Bryan-College Station                 Tyler 
##                    60                    60                    60 
##         Wichita Falls 
##                    60
freq_ass=table(texas$city)
freq_rel=table(texas$city)/N
distr_freq_CITY=cbind(freq_ass,freq_rel) 
distr_freq_CITY
##                       freq_ass freq_rel
## Beaumont                    60     0.25
## Bryan-College Station       60     0.25
## Tyler                       60     0.25
## Wichita Falls               60     0.25

Possiamo dedurre che ci troviamo davanti ad una distribuzione quadrimodale, poiché le frequenze sono le stesse per tutte le città. Le osservazioni sono perfettamente distribuite sulle 4 categorie e quindi ci si aspetta che l’indice di gini per la variabile city sia pari a 1.

3. Qual è la variabile con variabilità più elevata? Come ci sei arrivato? E quale quella più asimmetrica?

Esprimo alcune considerazioni:

  • volume ha il coefficiente di variazione più alto, il che significa che ha la maggiore variazione;

  • volume ha anche una curtosi positiva, il che significa che è leptocurtico;

  • Le altre variabili analizzate hanno una curtosi negativa, pertanto sono platicurtiche;

  • median_price ha una asimmetria negativa, visibile come una coda sinistra più lunga;

  • Tutte le altre variabili hanno una asimmetria positiva, visibile come una coda destra più lunga;

  • volume ha la maggiore asimmetria.

4. Dividi una delle variabili quantitative in classi, scegli tu quale e come, costruisci la distribuzione di frequenze, il grafico a barre corrispondente e infine calcola l’indice di Gini.

Definisco la funzione gini.index e verifichiamo se è vero cià che abbiamo detto nel punto 2:

gini.index <- function(x){
  J <- length(table(x))
  fi2 <- (table(x)/length(x))^2
  G <- 1 - sum(fi2)
  gini <- G / ((J-1)/J)
  return(gini)
}

gini.index(city)
## [1] 1

##5 5. “Indovina” l’indice di gini per la variabile city.

Come ipotizzato in precedenza (punto 2) sulla variabile city l’indice di Gini è pari ad 1.

Dividiamo la variabile volume in classi, quindi determino la distribuzione di frequenza e l’indice di Gini:

volume_classes <- cut(volume,
                      breaks = seq(min(volume), max(volume),
                                   (max(volume)-min(volume))/15))

ni <- table(volume_classes)
fi <- ni/N
Ni <- cumsum(ni)
Fi <- Ni/N
volume_freq_distr <- as.data.frame(cbind(ni,fi,Ni,Fi))
volume_freq_distr
##             ni          fi  Ni        Fi
## (8.17,13.2] 24 0.100000000  24 0.1000000
## (13.2,18.2] 42 0.175000000  66 0.2750000
## (18.2,23.2] 26 0.108333333  92 0.3833333
## (23.2,28.3] 30 0.125000000 122 0.5083333
## (28.3,33.3] 27 0.112500000 149 0.6208333
## (33.3,38.3] 22 0.091666667 171 0.7125000
## (38.3,43.3] 17 0.070833333 188 0.7833333
## (43.3,48.4]  9 0.037500000 197 0.8208333
## (48.4,53.4] 17 0.070833333 214 0.8916667
## (53.4,58.4]  5 0.020833333 219 0.9125000
## (58.4,63.4]  7 0.029166667 226 0.9416667
## (63.4,68.5]  5 0.020833333 231 0.9625000
## (68.5,73.5]  4 0.016666667 235 0.9791667
## (73.5,78.5]  2 0.008333333 237 0.9875000
## (78.5,83.5]  2 0.008333333 239 0.9958333
gini.index(volume_classes)
## [1] 0.9614769

Effettuo un plotting mediante un istogramma delle volume_classes:

barplot(volume_freq_distr$ni,
        xlab = "",
        ylab = "",
        ylim = c(0,50),
        main = "Volume classes frequencies",
        col = "blue",
        space = 0.1,
        names.arg = rownames(volume_freq_distr),
        las = 2)

##6. 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?

Facciamo alcuni test di probabilità. Prima possiamo indagare le probabilità di occorrenze di Beaumont. Poiché la distribuzione è quadrimodale, possiamo prevedere un risultato di 0,25:

Beaumont_ext = filter(texas, city == "Beaumont")
Beaumont_N = dim(Beaumont_ext)[1]
Beaumont_prob = Beaumont_N/N
Beaumont_prob
## [1] 0.25

Adesso possiamo fare lo stesso con un mese, ad esempio Luglio, che è rappresentato da 7 nella variabile month:

July_ext = filter(texas, month == 7)
July_N = dim(July_ext)[1]
July_prob = July_N/N
July_prob
## [1] 0.08333333

Combino ora due variabili come come da traccia dicembre e 2012 rispettivamente per le variabili month e year:

Dec12_ext = filter(texas, year == 2012, month == 12)
Dec12_N = dim(Dec12_ext)[1]
Dec12_prob = Dec12_N/N
Dec12_prob
## [1] 0.01666667

7. Esiste una colonna col prezzo mediano, creane una che indica invece il prezzo medio, utilizzando le altre variabili che hai a disposizione

Rendiamo il nostro dataframe più completo con nuove variabili:

  • avg_price: prezzo medio, definito con il rapporto tra volume (in $) e sales;

  • sales_eff: fficienza delle vendite, che mostra l’efficacia delle offerte di vendita, definita come il rapporto tra sales e listings.

Creiamo un nuovo Dataframe texas_complete:

avg_price <- (volume*1000000)/sales
sales_eff <- sales/listings
texas_complete <- cbind(texas, avg_price, sales_eff)
head(texas_complete, 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
##   avg_price  sales_eff
## 1  170626.5 0.05414220
## 2  163796.3 0.06809584
## 3  157697.8 0.10775607
## 4  134095.0 0.11709602
## 5  142737.6 0.11405985

8. Prova a creare un’altra colonna che dia un’idea di “efficacia” degli annunci di vendita. Riesci a fare qualche considerazione?

Per l’ultima variabile, 1 rappresenta la massima efficienza delle vendite, 0 la minima; La massima efficienza delle vendite è stata osservata in:

  • 2014
  • Bryan-College Station
  • Estate (giugno, luglio, agosto)

Possiamo anche utilizzare il pacchetto dplyr per riassumere alcune informazioni dal Dataframe. Proviamolo

texas_complete %>%
  group_by(city) %>%
  summarise(year = 2014, mean = mean(sales_eff),
            std.dev = sd(sales_eff))
## # A tibble: 4 × 4
##   city                   year   mean std.dev
##   <chr>                 <dbl>  <dbl>   <dbl>
## 1 Beaumont               2014 0.106   0.0267
## 2 Bryan-College Station  2014 0.147   0.0729
## 3 Tyler                  2014 0.0935  0.0235
## 4 Wichita Falls          2014 0.128   0.0247

La visualizzazione può essere molto utile durante l’analisi statistica, in particolare per fare confronti. Possiamo confrontare il median_price tra le città utilizzando un boxplot:

cities = unique(city)

ggplot(data = texas_complete)+
  geom_boxplot(aes(x=median_price/1000,
                   y=city),
               fill = "orange",
               colour = "red",
               outlier.colour = "red",
               outlier.shape = 1,
               outlier.size = 2.5,
               linewidth = 0.75,
               outlier.stroke = 0.75,
  )+
  scale_y_discrete(labels = cities)+
  scale_x_continuous(breaks = seq(70,180,10), 
                     guide = guide_axis(angle = 45))+
  labs(x="Median sale price (k$)",
       y="City",
       title = "Median sale price per city")+
  theme_minimal()+
  theme(plot.title = element_text(hjust = 0.5))

Possiamo osservare che Bryan-College Station ha il prezzo mediano di vendita più alto, mentre Wichita Falls il più basso. Tutte le città hanno una distribuzione asimmetrica per il median_price. Tyler è l’unica senza outlier.

Possiamo utilizzare il boxplot anche per confrontare il volume tra le città:

ggplot(data = texas_complete)+
  geom_boxplot(aes(x=volume,
                   y=city,
                   fill=factor(year)),)+
  scale_fill_manual(
    name = "Year",
    breaks = factor(unique(year)),
    values = c("lightblue", "lightblue1", "lightblue2",
               "lightblue3", "lightblue4"),
    labels = as.character(unique(year))
  )+
  scale_y_discrete(labels=cities)+
  scale_x_continuous(breaks = seq(10,100,10))+
  labs(x="Total value of sales (M$)",
       y="City",
       title = "Total value of sales per year")+
  theme_minimal()+
  theme(plot.title = element_text(hjust = 0.5))

Dal grafico possiamo dedurre che:

  • Tyler ha la mediana più alta del valore totale delle vendite;

  • Wichita Falls ha la mediana più bassa del valore totale delle vendite;

  • Wichita Falls è anche quasi costante, a differenza delle altre città.

L’istogramma può essere utilizzato per confrontare il Volumera le città per mese. Per prima cosa, utilizziamo un istogramma stacked (ossia impilato):

ggplot(data = texas_complete)+
  geom_col(aes(x = factor(month.abb[month], levels = month.abb),
               y = volume,
               fill = city))+
  labs(x = "Month",
       y = "Total value of sales (M$)",
       title = "Total value of sales per month")+
  facet_wrap(~year,nrow = 1)+
  scale_x_discrete(guide = guide_axis(angle = 90))+
  scale_fill_discrete(name = "City",
                      labels = cities)+
  theme_minimal()+
  theme(legend.position = "bottom",
        axis.text.x = element_text(size = 6),
        plot.title = element_text(hjust = 0.5))

Effettuo una normalizzazione:

ggplot(data = texas_complete)+
  geom_col(aes(x = factor(month.abb[month], levels = month.abb),
               y = volume,
               fill = city),
           position = "fill")+
  labs(x = "Month",
       y = "Total value of sales (M$)",
       title = "Total value of sales per month")+
  facet_wrap(~year,nrow = 1)+
  scale_x_discrete(guide = guide_axis(angle = 90))+
  scale_fill_discrete(name = "City",
                      labels = cities)+
  theme_minimal()+
  theme(legend.position = "bottom",
        axis.text.x = element_text(size = 6),
        plot.title = element_text(hjust = 0.5))

Il valore totale delle vendite aumenta nel corso degli anni, principalmente grazie al contributo del valore totale delle vendite di Tyler e del prezzo mediano di Bryan-College Station, come visto in precedenza.

L’ultimo confronto che possiamo effettuare riguarda il median_price per mese tra le città durante l’anno. In questo caso, utilizzeremo un grafico a linee:

ggplot(data = texas_complete)+
  geom_line(aes(x = factor(month.abb[month], levels = month.abb),
                y=median_price/1000,
                group=city,
                col=city),
            lwd=1
  )+
  facet_wrap(~year, nrow = 1)+
  scale_x_discrete(guide = guide_axis(angle = 90))+
  scale_color_discrete(name = "City")+
  labs(x="Month",
       y="Median sale price (k$)",
       title = "Median sale price per month")+
  theme_minimal()+
  theme(legend.position = "bottom",
        axis.text.x = element_text(size = 6),
        plot.title = element_text(hjust = 0.5))

Ne risulta che il median_price è rimasto quasi costante a Beaumont e Wichita Falls, mentre c’è stato un aumento a Bryan-College Station e Tyler, il che contribuisce ai risultati visti in precedenza:

ggplot(data = texas_complete)+
  geom_line(aes(x = factor(month.abb[month], levels = month.abb),
                y=sales,
                group=city,
                col=city),
            lwd=1
  )+
  facet_wrap(~year, nrow = 1)+
  scale_x_discrete(guide = guide_axis(angle = 90))+
  scale_color_discrete(name = "City")+
  labs(x="Month",
       y="Sales",
       title = "Sales per month")+
  theme_minimal()+
  theme(legend.position = "bottom",
        axis.text.x = element_text(size = 6),
        plot.title = element_text(hjust = 0.5))