Estructura de los datos y variables

#load("/Volumes/SP UFD U2/ProbyEst(I)-17/1617/PrimerDía/Pokemon.RData")
load("/Users/arminda/ownCloud/Prob_y_Estad/ProbyEst(I)-17/1617/PrimerDía/Pokemon.RData")
head(pokemon1)
##         Name Type.1 Type.2 Total HP Attack Defense Sp..Atk Sp..Def Speed
## 1  Bulbasaur  Grass Poison   318 45     49      49      65      65    45
## 2    Ivysaur  Grass Poison   405 60     62      63      80      80    60
## 3   Venusaur  Grass Poison   525 80     82      83     100     100    80
## 4 Charmander   Fire   none   309 39     52      43      60      50    65
## 5 Charmeleon   Fire   none   405 58     64      58      80      65    80
## 6  Charizard   Fire Flying   534 78     84      78     109      85   100
##   Generation Legendary
## 1          1     False
## 2          1     False
## 3          1     False
## 4          1     False
## 5          1     False
## 6          1     False
dim(pokemon1)
## [1] 721  12
str(pokemon1)
## 'data.frame':    721 obs. of  12 variables:
##  $ Name      : Factor w/ 800 levels "Abomasnow","AbomasnowMega Abomasnow",..: 81 330 746 103 104 100 666 765 65 96 ...
##  $ Type.1    : Factor w/ 18 levels "Bug","Dark","Dragon",..: 10 10 10 7 7 7 18 18 18 1 ...
##  $ Type.2    : Factor w/ 19 levels "none","Bug","Dark",..: 15 15 15 1 1 9 1 1 1 1 ...
##  $ Total     : int  318 405 525 309 405 534 314 405 530 195 ...
##  $ HP        : int  45 60 80 39 58 78 44 59 79 45 ...
##  $ Attack    : int  49 62 82 52 64 84 48 63 83 30 ...
##  $ Defense   : int  49 63 83 43 58 78 65 80 100 35 ...
##  $ Sp..Atk   : int  65 80 100 60 80 109 50 65 85 20 ...
##  $ Sp..Def   : int  65 80 100 50 65 85 64 80 105 20 ...
##  $ Speed     : int  45 60 80 65 80 100 43 58 78 45 ...
##  $ Generation: Factor w/ 6 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ Legendary : Factor w/ 2 levels "False","True": 1 1 1 1 1 1 1 1 1 1 ...

Vemos que disponemos de 721 filas (pokemon diferentes) y 12 columnas (variables). ¿Cuáles de estas variables son nominales, ordinales, cuantitativas discretas y cuantitativas continuas?

Por ejemplo, la variable Type.1 es nominal, indica el tipo principal del Pokemon. Además, vemos en la salida de str() que es un factor con 18 niveles. Veamos cuáles son y cuántos pokemons hay de cada uno.

table(pokemon1$Type.1)
## 
##      Bug     Dark   Dragon Electric    Fairy Fighting     Fire   Flying 
##       63       28       24       36       17       25       47        3 
##    Ghost    Grass   Ground      Ice   Normal   Poison  Psychic     Rock 
##       23       66       30       23       93       28       47       41 
##    Steel    Water 
##       22      105

Vemos que el tipo más abundante es Agua, seguido de Normal. Veamos cuántos pokemon hay de cada generación.

table(pokemon1$Generation)
## 
##   1   2   3   4   5   6 
## 151 100 135 107 156  72

Analizamos la 5ª Generación

Hay más pokemon de la quinta generación. Analicemos un poco más esta generación. Voy a crear otro conjunto de datos (llamado quinta) con solo los pokemon de la quinta generación y hacemos un diagrama de barras para ver los tipos que hay.

library(dplyr)
quinta=filter(pokemon1, Generation==5)
library(ggplot2)
ggplot(quinta, aes(x=Type.1))+geom_bar(color="blue", fill="blue", alpha=0.6)+theme(axis.text.x=element_text(size=6))

Tabla de frecuencias y diagrama de barras de los Tipos

Vemos que aquí los más abundantes son de tipo Bicho, seguido de Normal y Agua. Vamos a hacer una tabla de frecuencias de la variable Tipo para estos pokemon. Por defecto, los ordena por orden alfabético.

# con el siguiente comando, quito el Tipo 'Fairy' porque no hay ningún pokemon de este
# tipo en la Generación 5, pero sí en el resto de generaciones.
quinta = quinta %>% filter(Type.1!='Fairy') %>% droplevels()
quintat=table(quinta$Type.1)
Tabla1=as.data.frame(cbind(FrecuenciaAbsoluta=quintat, FrecuenciaRelativa=round(prop.table(quintat),3)))
Tabla1$Tipo=rownames(Tabla1)
# ordenamos los tipos en orden decreciente de frecuencia
Tabla1=Tabla1[order(Tabla1$FrecuenciaRelativa, decreasing=TRUE),]
Tabla1$Tipo <- factor(Tabla1$Tipo, levels = Tabla1$Tipo[order(Tabla1$FrecuenciaAbsoluta, decreasing=TRUE)])
Tabla1[,-3]
##          FrecuenciaAbsoluta FrecuenciaRelativa
## Bug                      18              0.115
## Normal                   17              0.109
## Water                    17              0.109
## Grass                    15              0.096
## Psychic                  14              0.090
## Dark                     13              0.083
## Ground                    9              0.058
## Fire                      8              0.051
## Dragon                    7              0.045
## Electric                  7              0.045
## Fighting                  7              0.045
## Ice                       6              0.038
## Rock                      6              0.038
## Ghost                     5              0.032
## Steel                     4              0.026
## Poison                    2              0.013
## Flying                    1              0.006
ggplot(Tabla1, aes(x=Tipo, y=FrecuenciaAbsoluta))+geom_bar(color="blue", fill="blue", alpha=0.6, stat='identity')+theme(axis.text.x=element_text(size=7)) 

Por curiosidad, veamos cuál es el pokemon tipo Volador y los dos tipo Veneno:

library(knitr)
kable(quinta[quinta$Type.1=="Flying",])
Name Type.1 Type.2 Total HP Attack Defense Sp..Atk Sp..Def Speed Generation Legendary
148 TornadusIncarnate Forme Flying none 580 79 115 70 125 80 111 5 True
kable(quinta[quinta$Type.1=="Poison",])
Name Type.1 Type.2 Total HP Attack Defense Sp..Atk Sp..Def Speed Generation Legendary
75 Trubbish Poison none 329 50 50 62 40 62 65 5 False
76 Garbodor Poison none 474 80 95 82 60 82 75 5 False

HitPoints: variable cuantitativa.

HP: Tabla de Frecuencias.

Vamos a estudiar ahora la variable HP de la 5ª Generación. Para hacer una tabla de frecuencias, vemos el rango de los datos:

summary(quinta$HP)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   30.00   55.00   70.00   70.19   80.00  165.00

El mínimo es \(30\) y el máximo es \(165\). Voy a crear \(7\) intervalos comenzando en \(25\) y terminando en \(175\), (\([25,50),[50,75),\dots\)). La amplitud de cada intervalo será de \(25\) unidades.

hp_cut=cut(quinta$HP, breaks=seq(25,175,by=25),right=F)
table_hp=table(hp_cut)
table_hp=as.data.frame(table_hp)
colnames(table_hp)=c("Clase","FrecAbs")
Tabla_HP=table_hp %>% mutate(FrecAbsAc=cumsum(FrecAbs),FrecRel=round(prop.table(table_hp$FrecAbs),5), FreRelAc=cumsum(FrecRel))
Tabla_HP
##       Clase FrecAbs FrecAbsAc FrecRel FreRelAc
## 1   [25,50)      21        21 0.13462  0.13462
## 2   [50,75)      73        94 0.46795  0.60257
## 3  [75,100)      42       136 0.26923  0.87180
## 4 [100,125)      18       154 0.11538  0.98718
## 5 [125,150)       1       155 0.00641  0.99359
## 6 [150,175)       1       156 0.00641  1.00000

En la tabla vemos que el \(87\%\) de los pokemon de la 5ª generación tienen menos de \(100\) HP y el \(98.7\%\) menos de \(125\). También, el \(60\%\) tienen menos de \(65\) HP. Podríamos pensar que son Pokemon debiluchos, pero como veremos después, la distribución de HP es similar para todas las generaciones.

HP: Histograma

Para obtener un histograma de una variable cuantitativa tecleamos lo siguiente. Por defecto, el programa elige el número de intervalos o clases a dibujar. Si queremos especificar nosotros el número, usamos el parámetro bins.

ggplot(quinta, aes(x=HP))+geom_histogram(fill="blue", colour="white",closed="left", bins=12)

Si queremos usar las mismas clases que usamos antes en la tabla de frecuencias, las definimos expresamente de la siguiente forma:

ggplot(quinta, aes(x=HP))+geom_histogram(breaks=seq(25,175,by=25), closed="left", colour="white", fill="blue")

Vemos que la mayor parte de pokemon tienen un HP menor que \(75\) (un \(60\%\)) o menor que \(100\) (un \(87\%\)). La distribución de frecuencias tiene la joroba un poco hacia la izquierda, con lo que presenta una muy ligera asimetría a la derecha (o positiva). Veamos cuáles son los pokemon con más \(HP\):

library(knitr)
kable(quinta[quinta$HP>=125,])
Name Type.1 Type.2 Total HP Attack Defense Sp..Atk Sp..Def Speed Generation Legendary
101 Alomomola Water none 470 165 75 80 40 45 65 5 False
153 Kyurem Dragon Ice 660 125 130 90 130 90 95 5 True

Son Alomomola (No Legendario) y Kyuren (Legendario).

HP: Stem plot

Con el diagrama de tallo-hojas recuperamos la forma del histograma pero, a la vez, vemos los datos individuales.

stem(quinta$HP)
## 
##   The decimal point is 1 digit(s) to the right of the |
## 
##    3 | 0568
##    4 | 00001455555555556
##    5 | 000000000000012455555555555889
##    6 | 00000000000002245555555679
##    7 | 0000000000011224455555555555555566799
##    8 | 000055555599
##    9 | 0111125555
##   10 | 00000035559
##   11 | 000046
##   12 | 05
##   13 | 
##   14 | 
##   15 | 
##   16 | 5

HP: Boxplot

ggplot(quinta, aes(x=HP, y=HP))+geom_boxplot(outlier.colour = "red", outlier.shape = 1)

Vemos los tres datos atípicos que identificamos antes, los pokemon con más valor de HP y la leve asimetría. También vemos que la anchura de la caja es pequeña (\(Q_3-Q_1=80-55=25\)) comparado con el rango de los datos \(\min-\max=165-30=135\), con lo que la distribución es más picuda que la Normal, es Leptocúrtica.

Comparando HP en las distintas generaciones

pokemon1$Generation=as.factor(pokemon1$Generation)
ggplot(pokemon1, aes(x=Generation, y=HP))+geom_boxplot(outlier.colour = "red", outlier.shape = 1)

A priori no hay razones para creer que la mediana de HP es distinta a través de las distintas Generaciones de pokemon. Eso sí, los pokemon con mayor valor de HP están en la primera y segunda generación y el que tiene menor valor de HP es de la tercera. En el siguiente gráfico hemos añadido los datos encima de los boxplot y los hemos coloreado según sean o no legendarios. Así vemos que ninguno de los pokemon con mayor o menor valor de HP son Legendarios.

pokemon1$Generation=as.factor(pokemon1$Generation)
ggplot(pokemon1, aes(x=Generation, y=HP))+geom_boxplot(outlier.colour = "red", outlier.shape = 1)+geom_jitter(aes(color=Legendary), alpha=0.6)

Tabla Bivariante: Generación vs. Legendario.

library(kableExtra)
prueba=addmargins(table(pokemon1$Generation,pokemon1$Legendary))
rownames(prueba)=c("Gen 1","Gen 2","Gen 3", "Gen 4", "Gen 5", "Gen 6", "Suma")
colnames(prueba)=c("NoLeg.", "Leg.", "Suma")
prueba %>% kable("html") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width=F)
NoLeg. Leg. Suma
Gen 1 147 4 151
Gen 2 95 5 100
Gen 3 125 10 135
Gen 4 96 11 107
Gen 5 146 10 156
Gen 6 66 6 72
Suma 675 46 721

A partir de esta tabla, es fácil estudiar las distribuciones marginales y condicionadas, ya que vuelven a ser distribuciones univariantes.