ENUNCIADO DE LA ACTIVIDAD

Como reto para este foro les proponemos que elijan un conjunto de datos de su preferencia y hagan un pequeño análisis del mismo, indicando los resultados más relevantes encontrados.

Pueden utilizar el dataset de su interés, ejemplo los disponibles en páginas como Kaggle.

Recuerden la importancia de comentar los trabajos de sus compañeros aportando nuevas ideas (siempre de forma constructiva). No es necesario hacer un análisis extenso del conjunto de datos ya que para eso tienen que realizar un trabajo de forma grupal.

Esto les servirá como entrenamiento previo al trabajo. El estudio debe hacerse obligatoriamente con la herramienta RStudio. Por favor, compartan el código utilizado y el conjunto de datos cuando posteen su contribución. Por ejemplo, pueden elegir una variable y realizar test de normalidad, ver cómo se distribuyen los datos, correlación entre variables, ajustes lineales, etc. Todo con RStudio.

INTRODUCCIÓN

Para este estudio me he basado en el siguiente dataset de kaggle.com:

https://www.kaggle.com/datasets/alexracape/lego-sets-and-prices-over-time

que nos proporciona información sobre los juegos de LEGO (nº de piezas, nº de minifiguras incluidas, …) y sus precios de venta a lo largo de los años, entre otros datos.

Aclaración sobre el significado de algunas variables que aparecen en la tabla original, aunque no las he utilizado para mi estudio:

OBJETIVO

El objetivo de este análisis es evaluar la variable USD_MSRP (precio) desde el año 2000 y su posible dependencia respecto del número de piezas contenidas en cada set.

ANÁLISIS

CARGA DE LIBRERIAS

NOTA: Se trata de un chunk genérico que tengo preparado, de ahí que se instalen más librerías de las necesarias para este estudio.

## Warning: package 'tidyverse' was built under R version 4.3.2
## Warning: package 'ggplot2' was built under R version 4.3.2
## Warning: package 'tidyr' was built under R version 4.3.2
## Warning: package 'readr' was built under R version 4.3.2
## Warning: package 'purrr' was built under R version 4.3.2
## Warning: package 'dplyr' was built under R version 4.3.2
## Warning: package 'forcats' was built under R version 4.3.2
## Warning: package 'lubridate' was built under R version 4.3.2
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## Warning: package 'modeest' was built under R version 4.3.2
## 
## Attaching package: 'moments'
## 
## The following object is masked from 'package:modeest':
## 
##     skewness
## Warning: package 'plotrix' was built under R version 4.3.2
## Warning: package 'car' was built under R version 4.3.2
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.3.2
## 
## Attaching package: 'car'
## 
## The following object is masked from 'package:dplyr':
## 
##     recode
## 
## The following object is masked from 'package:purrr':
## 
##     some
## Warning: package 'tidytext' was built under R version 4.3.2
## Warning: package 'naivebayes' was built under R version 4.3.2
## naivebayes 0.9.7 loaded
## Warning: package 'tm' was built under R version 4.3.2
## Loading required package: NLP
## 
## Attaching package: 'NLP'
## 
## The following object is masked from 'package:ggplot2':
## 
##     annotate
## Warning: package 'caret' was built under R version 4.3.2
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following object is masked from 'package:purrr':
## 
##     lift
## Warning: package 'corrplot' was built under R version 4.3.2
## corrplot 0.92 loaded
## Warning: package 'data.table' was built under R version 4.3.2
## 
## Attaching package: 'data.table'
## 
## The following object is masked from 'package:naivebayes':
## 
##     tables
## 
## The following objects are masked from 'package:lubridate':
## 
##     hour, isoweek, mday, minute, month, quarter, second, wday, week,
##     yday, year
## 
## The following objects are masked from 'package:dplyr':
## 
##     between, first, last
## 
## The following object is masked from 'package:purrr':
## 
##     transpose
## Warning: package 'vcd' was built under R version 4.3.2
## Loading required package: grid
## Warning: package 'gplots' was built under R version 4.3.2
## 
## Attaching package: 'gplots'
## 
## The following object is masked from 'package:plotrix':
## 
##     plotCI
## 
## The following object is masked from 'package:stats':
## 
##     lowess

CARGA DE DATOS

setwd("C:/Users/Usuario/Documents/Beatriz/CV cursos y ofertas/2_cursos/20231010 master BIG DATA/modulo 2/z_mis pruebas con R/lego")
lego = read.csv(file="LEGO.csv", header = TRUE, sep = ",")
str(lego)
## 'data.frame':    14936 obs. of  17 variables:
##  $ Set_ID          : chr  "75-1" "77-1" "077-1" "78-1" ...
##  $ Name            : chr  "PreSchool Set" "PreSchool Set" "Pre-School Set" "PreSchool Set" ...
##  $ Year            : int  1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 ...
##  $ Theme           : chr  "PreSchool" "PreSchool" "Duplo" "PreSchool" ...
##  $ Theme_Group     : chr  "Pre-school" "Pre-school" "Pre-school" "Pre-school" ...
##  $ Subtheme        : chr  "" "" "" "" ...
##  $ Category        : chr  "Normal" "Normal" "Normal" "Normal" ...
##  $ Packaging       : chr  "{Not specified}" "{Not specified}" "{Not specified}" "{Not specified}" ...
##  $ Num_Instructions: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Availability    : chr  "{Not specified}" "{Not specified}" "{Not specified}" "{Not specified}" ...
##  $ Pieces          : num  16 20 21 32 330 87 86 83 82 293 ...
##  $ Minifigures     : num  NA NA NA NA NA NA NA NA NA 5 ...
##  $ Owned           : num  10 11 10 8 10 279 252 404 299 479 ...
##  $ Rating          : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ USD_MSRP        : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ Total_Quantity  : num  NA NA 0 NA 0 0 0 0 0 0 ...
##  $ Current_Price   : num  NA NA NA NA NA NA NA NA NA NA ...

PREPARACIÓN DE LOS DATOS

En primer lugar, como hay muchos datos, voy a convertirlo a data.table para que trabaje más rápido y voy a seleccionar solo algunas variables (columnas).

lego_dt = as.data.table(lego)
str(lego_dt)
## Classes 'data.table' and 'data.frame':   14936 obs. of  17 variables:
##  $ Set_ID          : chr  "75-1" "77-1" "077-1" "78-1" ...
##  $ Name            : chr  "PreSchool Set" "PreSchool Set" "Pre-School Set" "PreSchool Set" ...
##  $ Year            : int  1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 ...
##  $ Theme           : chr  "PreSchool" "PreSchool" "Duplo" "PreSchool" ...
##  $ Theme_Group     : chr  "Pre-school" "Pre-school" "Pre-school" "Pre-school" ...
##  $ Subtheme        : chr  "" "" "" "" ...
##  $ Category        : chr  "Normal" "Normal" "Normal" "Normal" ...
##  $ Packaging       : chr  "{Not specified}" "{Not specified}" "{Not specified}" "{Not specified}" ...
##  $ Num_Instructions: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Availability    : chr  "{Not specified}" "{Not specified}" "{Not specified}" "{Not specified}" ...
##  $ Pieces          : num  16 20 21 32 330 87 86 83 82 293 ...
##  $ Minifigures     : num  NA NA NA NA NA NA NA NA NA 5 ...
##  $ Owned           : num  10 11 10 8 10 279 252 404 299 479 ...
##  $ Rating          : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ USD_MSRP        : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ Total_Quantity  : num  NA NA 0 NA 0 0 0 0 0 0 ...
##  $ Current_Price   : num  NA NA NA NA NA NA NA NA NA NA ...
##  - attr(*, ".internal.selfref")=<externalptr>
lego_red = select(lego_dt, Set_ID, Name, Year, Pieces, Minifigures, Rating, USD_MSRP, Current_Price)
str(lego_red)
## Classes 'data.table' and 'data.frame':   14936 obs. of  8 variables:
##  $ Set_ID       : chr  "75-1" "77-1" "077-1" "78-1" ...
##  $ Name         : chr  "PreSchool Set" "PreSchool Set" "Pre-School Set" "PreSchool Set" ...
##  $ Year         : int  1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 ...
##  $ Pieces       : num  16 20 21 32 330 87 86 83 82 293 ...
##  $ Minifigures  : num  NA NA NA NA NA NA NA NA NA 5 ...
##  $ Rating       : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ USD_MSRP     : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ Current_Price: num  NA NA NA NA NA NA NA NA NA NA ...
##  - attr(*, ".internal.selfref")=<externalptr>

Para reducir el número de observaciones y teniendo en cuenta que no se dispone de información de precios de venta (USD_MSRP) durante gran parte de los años iniciales, voy a centrar el análisis a partir del año 2000.

Para ello, creo un subconjunto, dentro del cual me quedo solo con aquellos casos en que el precio es conocido (descarto NAs):

unique(lego_red$Year)
##  [1] 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
## [16] 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
## [31] 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
## [46] 2020 2021 2022 2023
lego_red_2000 = lego_red %>%
 subset(Year>1999) %>%
 filter(!is.na(USD_MSRP)) 

summary(is.na(lego_red_2000)) #vemos que variables tienen NAs
##    Set_ID           Name            Year           Pieces       
##  Mode :logical   Mode :logical   Mode :logical   Mode :logical  
##  FALSE:5822      FALSE:5822      FALSE:5822      FALSE:5215     
##                                                  TRUE :607      
##  Minifigures       Rating         USD_MSRP       Current_Price  
##  Mode :logical   Mode :logical   Mode :logical   Mode :logical  
##  FALSE:3560      FALSE:5822      FALSE:5822      FALSE:3604     
##  TRUE :2262                                      TRUE :2218
str(lego_red_2000)
## Classes 'data.table' and 'data.frame':   5822 obs. of  8 variables:
##  $ Set_ID       : chr  "3458-1" "3461-1" "3462-1" "3470-1" ...
##  $ Name         : chr  "2x4 Black Bricks" "2x4 Dark Green Bricks" "2x4 Red Bricks" "1x4 White Bricks" ...
##  $ Year         : int  2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 ...
##  $ Pieces       : num  50 50 50 50 100 25 87 24 20 NA ...
##  $ Minifigures  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ Rating       : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ USD_MSRP     : num  6.99 6.99 6.99 5.99 8.99 4.99 9.99 4.99 5.99 4.99 ...
##  $ Current_Price: num  NA NA NA NA NA NA NA 10 NA NA ...
##  - attr(*, ".internal.selfref")=<externalptr>

ESTUDIO DE LA VARIABLE USD_MSRP

Paso a estudiar la variable USD_MSRP, que es cuantitativa contínua:

summary(lego_red_2000$USD_MSRP)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.49    9.99   19.99   40.03   49.99  849.99

Se observa que el rango de precios es muy amplio (entre 1.49USD y 849.99USD) y además, teniendo en cuenta los valores de los cuantiles, media y mediana, queda claro que hay mucha más densidad en el rango de precios bajos, lo cual es lógico por otra parte, ya que gran parte de estos set están dirigidos a niños y por lo tanto, tienen que tener precios asequibles, mientras que los modelos más caros corresponden a series especiales y/o de coleccionista, con mucha probabilidad.

Compruebo la normalidad gráficamente:

hist(lego_red_2000$USD_MSRP, freq=FALSE, main = "Histograma de Precios de venta en USD", col="cyan")
lines(density(lego_red_2000$USD_MSRP), col="red")

y si lo hago desde un punto de vista analítico:

g1=skewness(lego_red_2000$USD_MSRP)
paste ("Asimetría (g1)=", g1)
## [1] "Asimetría (g1)= 4.6628312942893"
g2=kurtosis(lego_red_2000$USD_MSRP)
paste ("Curtosis (g2) =", g2)
## [1] "Curtosis (g2) = 37.6750948245125"

Aquí se confirma lo ya visto gráficamente de manera muy evidente: - g1>0 –> Asimetría positiva (cola a la derecha) - g2>0 –> Leptocúrtica. Además, como es >2 no podemos asumir el supuesto de normalidad de los residuos.

ANÁLISIS DE DEPENDENCIA ENTRE VARIABLES

Voy a intentar ahora analizar si hay alguna dependencia entre el precio y el número de piezas

En primer lugar, preparo una matriz de correlación de todas las variables numéricas, donde confirmo que la elección de dichas variables cuya dependencia quiero analizar es correcta:

M_cor_total = cor(lego_red_2000[,3:8], use = "complete.obs")
corrplot(M_cor_total,title="Matriz de correlación LEGO")

Efectivamente, parecen ser buenas candidatas, así que profundizamos en el análisis:

plot(lego_red_2000$Pieces,lego_red_2000$USD_MSRP)
abline()

Aunque hay cierta dispersión, sí parece haber relación de dependencia en el gráfico anterior.

Creo la matriz de correlación:

M_cor = cor(lego_red_2000[ ,c("USD_MSRP", "Pieces")], use = "complete.obs")
M_cor
##           USD_MSRP    Pieces
## USD_MSRP 1.0000000 0.8766067
## Pieces   0.8766067 1.0000000

Para tener el valor de r guardado:

r=cor(lego_red_2000$USD_MSRP,lego_red_2000$Pieces,use = "complete.obs")
r
## [1] 0.8766067

A continuación paso a calcular los coeficiones de la línea de regresión:

regresion_lego = lm(USD_MSRP~Pieces, data=lego_red_2000)
summary(regresion_lego)
## 
## Call:
## lm(formula = USD_MSRP ~ Pieces, data = lego_red_2000)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -655.21  -10.53   -5.38    4.61  346.32 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 1.337e+01  4.411e-01   30.31   <2e-16 ***
## Pieces      7.626e-02  5.798e-04  131.53   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 27.42 on 5213 degrees of freedom
##   (607 observations deleted due to missingness)
## Multiple R-squared:  0.7684, Adjusted R-squared:  0.7684 
## F-statistic: 1.73e+04 on 1 and 5213 DF,  p-value: < 2.2e-16

Con los datos obtenidos, quedaría la fórmula:

USD_MSRP = 0.07626 * Pieces + 13.37

Como datos significativos:

  • El coeficiente de determinación R^2 = 0.7684 es decir, el número de piezas explica en un 76,84% de los casos cómo varía el precio de venta (PVP en USD) (R^2 coincide con el valor de r^2 = 0.8766067^2=0.7684 como era de esperar)

  • Además p-value < nivel de significación (α), es decir, se confirma que el predictor sí que explica el modelo.

CONCLUSIONES

A modo de resumen, éstas son las conclusiones que he obtenido del presente estudio respecto a los juegos de LEGO: