library(tidyverse)
## -- Attaching packages ----------------------------------------------------------------------------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.1.0 v purrr 0.2.5
## v tibble 1.4.2 v dplyr 0.7.8
## v tidyr 0.8.2 v stringr 1.3.1
## v readr 1.1.1 v forcats 0.3.0
## -- Conflicts -------------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
data <- read.csv("../DataSets/auto-mpg.csv")
Podemos formatear los vectores dentro del dataset para dar formatos diferentes, con la función factor
data$cylinders <- factor(data$cylinders,
levels = c(3,4,5,6,8), #seleccionamos el número de niveles que hay dentro de la columna del df
labels = c("3cil", "4cil", "5cil", "6cil", "8cil")) # etiquetas que damos a cada uno de los niveles
Usando la función summary podemos sacar diferentes estadísticas para variables numéricas y para variables factores nos da el conteo.
Junto con esta función también contamos con la función str(), que nos dice el tipo de objetos que contiene la estructura, y el tipo de dato de cada uno. Recordar que podemos bajar mucho más nivel con summary() para cada una de las columnas.
summary(data)
## No mpg cylinders displacement
## Min. : 1.0 Min. : 9.00 3cil: 4 Min. : 68.0
## 1st Qu.:100.2 1st Qu.:17.50 4cil:204 1st Qu.:104.2
## Median :199.5 Median :23.00 5cil: 3 Median :148.5
## Mean :199.5 Mean :23.51 6cil: 84 Mean :193.4
## 3rd Qu.:298.8 3rd Qu.:29.00 8cil:103 3rd Qu.:262.0
## Max. :398.0 Max. :46.60 Max. :455.0
##
## horsepower weight acceleration model_year
## Min. : 46.0 Min. :1613 Min. : 8.00 Min. :70.00
## 1st Qu.: 76.0 1st Qu.:2224 1st Qu.:13.82 1st Qu.:73.00
## Median : 92.0 Median :2804 Median :15.50 Median :76.00
## Mean :104.1 Mean :2970 Mean :15.57 Mean :76.01
## 3rd Qu.:125.0 3rd Qu.:3608 3rd Qu.:17.18 3rd Qu.:79.00
## Max. :230.0 Max. :5140 Max. :24.80 Max. :82.00
##
## car_name
## ford pinto : 6
## amc matador : 5
## ford maverick : 5
## toyota corolla: 5
## amc gremlin : 4
## amc hornet : 4
## (Other) :369
str(data)
## 'data.frame': 398 obs. of 9 variables:
## $ No : int 1 2 3 4 5 6 7 8 9 10 ...
## $ mpg : num 28 19 36 28 21 23 15.5 32.9 16 13 ...
## $ cylinders : Factor w/ 5 levels "3cil","4cil",..: 2 1 2 2 4 2 5 2 4 5 ...
## $ displacement: num 140 70 107 97 199 115 304 119 250 318 ...
## $ horsepower : int 90 97 75 92 90 95 120 100 105 150 ...
## $ weight : int 2264 2330 2205 2288 2648 2694 3962 2615 3897 3755 ...
## $ acceleration: num 15.5 13.5 14.5 17 15 15 13.9 14.8 18.5 14 ...
## $ model_year : int 71 72 82 72 70 75 76 81 75 76 ...
## $ car_name : Factor w/ 305 levels "amc ambassador brougham",..: 66 184 165 86 8 18 11 79 42 112 ...
Podemos analizar variables concretas también:
summary(data$cylinders)
## 3cil 4cil 5cil 6cil 8cil
## 4 204 3 84 103
summary(data$mpg)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 9.00 17.50 23.00 23.51 29.00 46.60
str(data$cylinders)
## Factor w/ 5 levels "3cil","4cil",..: 2 1 2 2 4 2 5 2 4 5 ...
Instalamos tres paquetes distintos para hacer los análisis estastísicos:
library(raster) #quantiles, cv
library(moments) # asimetría, curtosis
Crearemos una variable con la que aplicaremos todos los análisis estadísticos:
X = data$mpg
A continuación usaremos las siguientes medidas estadísticas:
Estadísticos para evaluar como de centrados estan los vectores.
mean(X) #sum(X)/length(X)
## [1] 23.51457
median(X) # valor central
## [1] 23
# Create the function.
getmode <- function(v) {
uniqv <- unique(v)
uniqv[which.max(tabulate(match(v, uniqv)))]
}
getmode(X)
## [1] 13
quantile(X)
## 0% 25% 50% 75% 100%
## 9.0 17.5 23.0 29.0 46.6
Ver si los datos estan muy dispersos o muy concentrados.
#### Medidas de Dispersión
var(X) # varianza, siempre será un valor positivo, Si hay números muy iguales dentro del vector, la varianza será muy pequeña.
## [1] 61.08961
sd(X) # desviación típica, raíz cuadrada de la varianza
## [1] 7.815984
La varianza eleva los valores al cuadrado, dando una nueva dimensión a los valores y puede no tener ningún significado. Con la desviación típica se vuelve a la dimensión original, dándole sentido a los datos.
cv(X) #(sd(X)/mean(X))*100, libreria raster
## [1] 33.2389
moments::skewness(X)
## [1] 0.4553419
En el caso que sea un valor positivo quiere decir que será una función “leptocúrtica”, los valores se concentran en el valor central y apenas tiene colas.
Una curtosis negativa, indicaría una distribución platicúrtica, es decir que hay pocos valores que se concentren en torno al promedio a la media, y hay muchos en las colas.
moments::kurtosis(X)
## [1] 2.480575
Vamos a ver la forma de nuestra distribución:
hist(X)
2 modos de extraer un subconjunto de los datos iniciales para ver una primera aproximación:
Cargamos dataset y trabajamos con filas y columnas:
data <- read.csv("../DataSets/auto-mpg.csv", stringsAsFactors = F)
#Index by position
data[1:5, 8:9]
data[1:5, c(8,9)]
#Index by Name (subconjunto por filas)
data[1:5, c("model_year", "car_name")]
Vamos ahora a usar operadores para hacer subconjuntos:
# & : AND
# | : OR
# ! : NOT
# ==
##Min / Max de mpg
data[data$mpg == max(data$mpg) | data$mpg == min(data$mpg),]
#Filtros con condiciones
data[data$mpg>30 & data$cylinders == 6, c("car_name", "mpg")]
data[data$mpg>30 & data$cyl == 6, c("car_name", "mpg")]
Primero indicamos de que dataframe queremos scar los datos, luego las condiciones, y por último las columnas que queremos.
#subset
subset(data, mpg>30 & cylinders == 6, select = c("car_name", "mpg"))
#Excluir columnas
data[1:5,c(-1,-9)]
data[1:5, -c(1,9)]
Buscando nombres (strings) dentro de filas o columnas:
#data[1:5, -c("No", "car_name")]
data[1:5, !names(data) %in% c("No", "car_name")] # nombres que NO estén
data[data$mpg %in% c(15,20), c("car_name", "mpg")] # nombres que estén
Usando vectores booleanos para seleccionar muestras de datos:
data[c(F,F,F,F,T), c(F, F, T)]
La función split() divide los datos en baso a un factor o a un vector, y conviene dividir por variables categoricas. I hay la función inversa que es unsplit()
#split / unsplit
data <- read.csv("../DataSets/auto-mpg.csv", stringsAsFactors = F)
Introducimos la variable que usaremos para partir los datos:
carslist <- split(data, data$cylinders)
Esta función nos devuelve una lista de dataframes. Vamos a leer la información dentro de este nuevo objeto:
carslist[1]
## $`3`
## No mpg cylinders displacement horsepower weight acceleration
## 2 2 19.0 3 70 97 2330 13.5
## 199 199 18.0 3 70 90 2124 13.5
## 251 251 23.7 3 70 100 2420 12.5
## 365 365 21.5 3 80 110 2720 13.5
## model_year car_name
## 2 72 mazda rx2 coupe
## 199 73 maxda rx3
## 251 80 mazda rx-7 gs
## 365 77 mazda rx-4
carslist[[1]]
str(carslist[1])
## List of 1
## $ 3:'data.frame': 4 obs. of 9 variables:
## ..$ No : int [1:4] 2 199 251 365
## ..$ mpg : num [1:4] 19 18 23.7 21.5
## ..$ cylinders : int [1:4] 3 3 3 3
## ..$ displacement: num [1:4] 70 70 70 80
## ..$ horsepower : int [1:4] 97 90 100 110
## ..$ weight : int [1:4] 2330 2124 2420 2720
## ..$ acceleration: num [1:4] 13.5 13.5 12.5 13.5
## ..$ model_year : int [1:4] 72 73 80 77
## ..$ car_name : chr [1:4] "mazda rx2 coupe" "maxda rx3" "mazda rx-7 gs" "mazda rx-4"
names(carslist[[1]])
## [1] "No" "mpg" "cylinders" "displacement"
## [5] "horsepower" "weight" "acceleration" "model_year"
## [9] "car_name"
Para evaluar el modelo creado por un analista de datos, usaremos la partición de datos en dos subconjuntos. Uno para entrenar el modelo, y el otro para evaluar el modelo.
library(caret)
## Loading required package: lattice
##
## Attaching package: 'caret'
## The following object is masked from 'package:purrr':
##
## lift
data <- read.csv("../DataSets/BostonHousing.csv")
Vamos a ver como partir los datos en un 80% usando la variables MEDV:
training.ids <- createDataPartition(data$MEDV, p = 0.8, list = F)
data.training <- data[training.ids,]
data.validation <- data[-training.ids,]
A veces se hacen 3 particiones, dos de ellas para entrenar el modelo, y la última para evaluarlo:
training.ids.2 <- createDataPartition(data$MEDV, p = 0.7, list = F)
data.training.2 <- data[training.ids.2,]
temp <- data[-training.ids.2,]
validation.ids.2 <- createDataPartition(temp$MEDV, p = 0.5, list = F) # hacemos una segunda división de los datos
data.validation <- temp[validation.ids.2,]
data.testing <- temp[-validation.ids.2,]
La función de createDataPartition selecciona un muestreo aleatorio basado en grupos de percentiles, de modo que para optener una buena muestra busca que sea lo suficiente homogenea. Por defecto considera 5 grupos dentro del vector, pero se puede controlar con el parámetro groups(). El parámetro list(), controlamos si queremos el resultado como lista (T) o como vector(F).
data2 <- read.csv("../DataSets/boston-housing-classification.csv")
Hacemos la partición del 70%, tomando la vaariable categórica:
training.ids.3 <- createDataPartition(data2$MEDV_CAT, p = 0.7, list = F)
data.training.3 <- data2[training.ids.3,]
data.validation.3 <- data2[-training.ids.3,]
Vamos a crear funciones para crear automaticamente particiones de dos elementos con una probabilidad (partición) dada:
rda.cb.partition2 <- function(dataframe, target.index, prob){
library(caret)
training.ids <- createDataPartition(dataframe[,target.index], p=prob, list = FALSE)
list(train = dataframe[training.ids,], val = dataframe[-training.ids,])
}
Partición con tres elementos:
rda.cb.partition3 <- function(dataframe, target.index,
prob.train, prob.val){
library(caret)
training.ids <- createDataPartition(dataframe[,target.index], p = prob.train, list = FALSE)
train.data <- dataframe[training.ids,]
temp <- dataframe[-training.ids,]
validation.ids <- createDataPartition(temp[,target.index], p = prob.val, list = FALSE)
list(train = train.data, val = temp[validation.ids,], test = temp[-validation.ids,])
}
Vamos a trabajar con las funciones que hemos creado, introduciento los valores que necesitan las funciones:
data1 <- rda.cb.partition2(data, 14, 0.8)
new.data2 <- rda.cb.partition3(data2, 14, 0.7, 0.5)
head(data1$val)
head(new.data2$val)
nrow(data)
## [1] 506
Por último se puede sacar una muestra del primer data frame usando la función de sample:
sample1 <- sample(data$CRIM, # la variables de donde podemos sacara la información
40, # indicamos le número de elementos
replace = F) # no se repetiran los valores dentro de la muestra
Para gráficos más avanzados usaríamos lattice o ggplot, los siguientes gráficos básicos lo haremos con el paquete básico:
auto <- read.csv("../DataSets/auto-mpg.csv")
Convertimos una variable en factor, considerando los niveles cada uno de los factores (levels) y dando valores a cada uno de los factores (labels):
auto$cylinders <- factor(auto$cylinders,
levels = c(3,4,5,6,8),
labels = c("3cil", "4cil", "5cil", "6cil", "8cil"))
attach(auto) # con esta función cargamos todo el dataset el la estructura principal de R, evitando que tengamos que usar el signo $ después de introducir el nombre del dataset para seleccionar la variable con la que tenemos que trabajar. Ejemplo:
## The following object is masked from package:ggplot2:
##
## mpg
head(cylinders)
## [1] 4cil 3cil 4cil 4cil 6cil 4cil
## Levels: 3cil 4cil 5cil 6cil 8cil
Vamos a crear histogramas con la función hist(), permite pintar cualquier variable numérica en un diagrama de frecuencias:
#Histograma de frecuencias
hist(acceleration,
col = rainbow(12), # ranibow() para 12 colores distintos
xlab = "Aceleración",
ylab = "Frecuencias",
main = "Histograma de las aceleraciones",
breaks = 12)
Pintanto un histograma de densidad:
hist(mpg, breaks = 16, prob = T)
lines(density(mpg)) # añadios una linea que muestre la densidad
Representando un vector numérico en un diagrama de cajas y bigotes:
#Boxplots
boxplot(mpg, xlab = "Millas por Galeón")
Generar boxplots para un subconjunto de una variable categorica:
boxplot(mpg ~ model_year, xlab = "Millas por Galeón (por año)")
Hacer lo mismo en relación al número de cilindros:
boxplot(mpg ~ cylinders, xlab = "Consumo por Número de cilindros")
Representando todas las variables de un dataset:
boxplot(auto)
Permite ver la relación de dos variables numéricas. Ayuda a ver la tendencía, pero con uno no se acostumbra a ver nada, por eso es mejor hacer una matriz de scatter plots:
#Scatterplot
plot(mpg ~ horsepower, type = "n") # primera variable sera la dependiente, la y, y la segunda la independiente, la x.
linearmodel <- lm(mpg ~ horsepower) # creando una recta de regresión lineal
abline(linearmodel) # pintamos la recta encima del gráfico inmediatamente anterior
#Agregar colores para cada cilindrada
with(subset(auto, cylinders=="8cil"),
points(horsepower, mpg, col = "red"))
with(subset(auto, cylinders == "6cil"),
points(horsepower, mpg, col = "yellow"))
with(subset(auto, cylinders == "5cil"),
points(horsepower, mpg, col = "green"))
with(subset(auto, cylinders == "4cil"),
points(horsepower, mpg, col = "blue"))
with(subset(auto, cylinders == "3cil"),
points(horsepower, mpg))
Creando una matriz de scatter plots:
#Matriz de Scatterplots
pairs(~mpg+displacement+horsepower+weight)
Podems usar par() para la configuración de parametros, para consultar todos podemos poner en consola par(). Nosotros usaremos el parámetro nfrow() dentro de la función par():
#Combinación de plots con par
old.par <- par()
par(mfrow = c(1,2))
with(auto, {
plot(mpg ~ weight, main = "Peso vs Consumo")
plot(mpg ~ acceleration, main = "Aceleración vs Consumo")
}
)
par(old.par)
## Warning in par(old.par): el parámetro del gráfico "cin" no puede ser
## especificado
## Warning in par(old.par): el parámetro del gráfico "cra" no puede ser
## especificado
## Warning in par(old.par): el parámetro del gráfico "csi" no puede ser
## especificado
## Warning in par(old.par): el parámetro del gráfico "cxy" no puede ser
## especificado
## Warning in par(old.par): el parámetro del gráfico "din" no puede ser
## especificado
## Warning in par(old.par): el parámetro del gráfico "page" no puede ser
## especificado
Ayuda a representar relaciones multivariantes entre las diferentes variables del dataset. Primero hacemos carga de datos:
library(lattice)
auto <- read.csv("../DataSets/auto-mpg.csv", stringsAsFactors = F)
auto$cylinders = factor(auto$cylinders,
levels = c(3,4,5,6,8),
labels = c("3C", "4C", "5C", "6C", "8C"))
Podemos hacer una representación de boxlpots:
bwplot(~ auto$mpg | auto$cylinders,
main = "MPG según cilindrada",
xlab = "Millas por Galeón",
layout = c(2,3), aspect = 1)
O una representación de scatterplots:
xyplot(mpg~weight | cylinders, data = auto,
main = "Peso vs Consumo vs Cilindrada",
xlab = "Peso (kg)", ylab = "Consumo (mpg)")
## bwplot, xyplot, densityplot, splom
Cambiando esquemas de colores de los gráficos con:
trellis.par.set(theme = col.whitebg())
xyplot(mpg~weight | cylinders, data = auto,
main = "Peso vs Consumo vs Cilindrada",
xlab = "Peso (kg)", ylab = "Consumo (mpg)")
data <- read.csv("../DataSets/daily-bike-rentals.csv")
Dando valores distintos a las diferentes variables:
data$season <- factor(data$season, levels = c(1,2,3,4),
labels = c("Invierno", "Primavera", "Verano", "Otoño"))
data$workingday <- factor(data$workingday, levels = c(0,1),
labels = c("Festivo", "De trabajo"))
data$weathersit <- factor(data$weathersit, levels = c(1,2,3),
labels = c("Despejado", "Nublado", "Lluvia/Nieve ligera"))
data$dteday <- as.Date(data$dteday, format = "%Y-%m-%d")
attach(data)
## The following object is masked _by_ .GlobalEnv:
##
## temp
Preparanto los grupos para ser representados:
winter <- subset(data, season == "Invierno")$cnt
spring <- subset(data, season == "Primavera")$cnt
summer <- subset(data, season == "Verano")$cnt
fall <- subset(data, season == "Otoño")$cnt
Representando las estaciones:
par(mfrow=c(2,2))
hist(winter, prob = TRUE, xlab = "Alquiler diario en invierno", main ="")
lines(density(winter))
abline(v = mean(winter), col = "red")
abline(v=median(winter), col = "blue")
hist(spring, prob = TRUE, xlab = "Alquiler diario en invierno", main ="")
lines(density(spring))
abline(v = mean(spring), col = "red")
abline(v=median(spring), col = "blue")
hist(summer, prob = TRUE, xlab = "Alquiler diario en invierno", main ="")
lines(density(summer))
abline(v = mean(summer), col = "red")
abline(v=median(summer), col = "blue")
hist(fall, prob = TRUE, xlab = "Alquiler diario en invierno", main ="")
lines(density(fall))
abline(v = mean(fall), col = "red")
abline(v=median(fall), col = "blue")
par(mfrow=c(1,1))
Tenemos la teoría que cuando hace mal tiempo se alquilan menos bicicletas. Vámos a ver como podemos aplicar el resultado:
library(lattice)
bwplot(cnt ~ weathersit, data = data,
layout = c(1,1), xlab = "Prónostico del tiempo",
ylab = "Frecuencias",
par.settings = list(box.rectangle = list(fill = c("red", "yellow","green"))))
PArece que el promedio cuando hace mal tiempo (Lluvia/Nieve ligera) es peo que cuando está despejado.
Podemos añadir información adicional al gráfico, viendo la dispersión de los datos, usando el parametro panel(), donde decimos que función se le quieren aplicar a los datos:
bwplot(cnt ~ weathersit, data = data,
layout = c(1,1), xlab = "Prónostico del tiempo",
ylab = "Frecuencias",
panel = function(x,y,...){
panel.bwplot(x,y,...)
panel.stripplot(x,y,jitter.data = TRUE,...)
},
par.settings = list(box.rectangle = list(fill = c("red", "yellow","green"))))
Podemos ver que casi no tiene dispersión de datos para los días de lluvia o nieve, dado que casi no hay datos. La tienda debe estar algún sitio donde no llueve mucho. Por lo tanto, el tiempo influye, pero como llueve muy poco esta información no es relevante para mi negocio.
Vamos a usar el dataset de las bicicletas para trabajar con estos gráficos:
library(beanplot)
beanplot(data$cnt ~data$season, col = c("blue", "red", "yellow"))
Es una mezcla de un scatter plot con un histograma, en amarillo son las medidas que son más raras, outliers.
La ralla de color negro es la media de cada una de las distribuciones. La rallas de puntitos es la media global.
La validación cruzada es una técnica muy utilizada para evaluar los resultados del análisis estadístico, y garantizar que son independientes de la partición que se ha hecho en el conjunto de entrenamiento y los datos de prueva.
Cross validation consiste en repetri el proceso de partición varias veces, y calcular la media artimética obtenida de las medias de evaluación sobre diferentes particiones llevadas a cabo. Se utilizan en torno donde el objetivo principal es predecir los datos, pero también se puede utilizar en el caso de calsificadores.
En general, lo que se quiere estimar es la precisión del modelo que se llevará a cabo a la práctica, validando que el modelo es correcto.
Veamos un ejemplo:
Si lal partición del dataset no se ha hecho correctamente, puede ocurrir que los resultados sean “overfitted”, ajustandose demasiado bien a los datos de entrenamiento, y no siendo un modelo que se pueda replicar en los datos del testing.
La validación crizada con K iteraciones, los datos de muestra se dividen en K subconjuntos, de forma que uno de los datos (k) se usa como datos de preuva miestras que el resto de datos (k-1) como entrenamiento. En el procesos de validación cruzada el proceso se vuelve a repetir, pero en este caso se cambian los papeles. Este proceso sigue hasta llevar a un total de k iteraciones. Entoces se realiza la media aritmética de los resultados de cada iteración, para obtener el resultado final.
Es un método muy preciso, ppues que evaluamos a partir de k combianaciones de los datos de entrenamiento y de prueva, pero a diferencia del metodo de retención, es más lento a nivel computacional, dado que debe llevar a cabo k iteraciones en vez de solo 1. A la práctica, el número de iteraciones depende del tamaño de los datos, pero por lo normal se seleccionan 10 iteraciones. (ten fold cross validation)
Este método divide aleatoriamente el conjunto de datos de entrenamiento, y el conjunto de datos de prueva. Se hace el mismo calculo de media arimetica que se hace anteriormente.
El problema de este método es que pueden quedar datos evaluados varias veces o ninguna vez.
En este caso dejamos un conjunto de datos fuera del modelo de entrenamiento y testing. Tiene un error muy bajo, pero a nivel computacional es más elevado, dado que tendemos a hacer un mayor número de iteraciones, exactametne tantas como muestras tengamos
Es una herramienta a visual que nos ayud a ver si un conjunto de datos puede proceder o no de una distribución teorica como la normal o la exponencial, o la poisson. Por ejemplo si llevamos a cabo un análisis estadístico que asume que nuestra variable dependiente se distribuye de forma normal, podríamos elaborar un gráfico cuantil cuantil contra la normal, para comprobar dicha hipótesis.
En un gráfico cuantil cuantil nos encotramos un conjunto de puntos, un scatter plot. Si los dos resultados proceden de la misma distribución, los resultados deberían ser casi casi una linea recta en la diagonal del gráfico
qqnorm(trees$Height)
Podríamos decir que la muestra que hemos seleccionado sí que sigue una distribución normal. Pero, ¿que es esto de los cuantiles?
Son puntos muy específicos de la muestra que dejan cierta cantidad de datos por debajo de ellos. De cuantiles o percentiles hay tres muy concretos:
1r cuartil -> dejan por debajo el 25% de los datos
2ndo cuartil -> dejan por debajo el 50% de los datos
3r cuartil -> dejan por debajo el 75% de los datos
En el caso de la campana de gauss, donde la media es 0, el percentil número 50, o el segundo cuantil, deja por abajo el 50% de los datos. El 50% está por encima. Si por ejemplo tomásemos el percentil número 95, el valor que deja debajo de la curva sería 1’64. En el caso del percentil del 99% de los datos, nos quedaría el valor 1’96. Estos son los típicos valores que se utilizan a la hora de tipificar y crear intervalos de confianza con la distibución normal.
La importancia de este gráfico se centra en la capacidad de comprobar por nosotros mismos si sigue una distribución que nosotros conocemos, puede que no sea una normal estándar, pero sí una normal con media y desvación típica que podemos calcular a partir de la muestra.
Són muy útiles sobretodo para regresiones lineales.
Creando una secuencia que empieze en 0.01 y acabe en 0.99, con separación de 0.01:
s <- seq(0.01, 0.99, 0.01)
Para investigar los diferentes percentiles de la normal, podemos usar la función qnorm(), el primer valor (-2.326) deja por debajo el 1% de los datos (es el primer percentil):
qn <- qnorm(s)
head(qn) # viendo los primeros 5 valores
## [1] -2.326348 -2.053749 -1.880794 -1.750686 -1.644854 -1.554774
Vamos a ver los datos uno al lado del otro:
df <- data.frame(p = s, q = qn)
head(df)
También podemos generar aleatoriamente datos desde una distribución normal y luego encontrar los cuantiles. Para generar muestras aleatorias siguiendo una disitrbución normal usaremos la función rnorm():
sample <- rnorm(200)
Luego podemos ver los quantiles para esta muestra creada:
head(quantile(sample, probs = s) )
## 1% 2% 3% 4% 5% 6%
## -2.548096 -2.015396 -1.848721 -1.741894 -1.636567 -1.582262
Vamos a ver gráficos de qqplot, donde nuestra meustra está ordenada de forma ascendente. Usaremos el dataset interno de R “trees”. Para hacer los gráficos, R usa dos funciones:
qqnorm
qqplot
Empezemos por qqnorm(), crea un gráfico qqplot frente a una normal. Simplemente le damos le vector de datos, y R se encargará de ellos, ordenándolos correctamente frente a los cuantiles de la distribución normal estándar. Ejemplo:
#qqnorm
qqnorm(trees$Height) # queremos ver si la altura de los árboles de este data set sigue una distribución normal. Parece que sí.
Por otro lado, el gráfico qqplot es un poco más genérico y nos permite crear gráficos cuantil cuantil para cualquier distirbución que queramos. En este caso tenemos que darle dos argumentos, un que sea el teórico y el otro el del conjunto de información que queremos enfrentar en el qqplot.
Usaremos el dataset randu, dentro de R. Son número aleatorios que no siguen una distribución normal, sino una distribución uniforme donde básicamente todos los puntos de 0 a 1 tienen la misma probabilidad de salir:
#qqplot
n <- length(randu$x) # cogemos la longitud del tamaño de la muestra
y <- qunif(ppoints(n)) # usamos qunit() de una distribución uniforme del mismo tamaño que nuestro dataset. La función ppoints genera un numero dado de proporciones (probabilidades)
qqplot(y, randu$x)
Nuestra hipótesis es correcta, siguen una distribución uniforme al seguir una inea recta.
¿Que pasaría si pintasemos estos puntos en contra de una distribución normal? Recordar que con qqnorm() te reprentará el grupo de datos vs la distribución normal:
qqnorm(randu$x)
Aquí podemos ver claramente que es una uniforme.
¿Qué ocurre cuando los datos no siguen ni una distribución normal ni una uniforme?
Vamos a crear los datos sesgada hacia a a derecha:
chi3 <- qchisq(ppoints(30), df = 3)
n30 <- qnorm(ppoints(30))
qqplot(n30, chi3)
Esto parece una parábola, ni una normal ni uniforme. Al descartar estas dos, se podría empezar a considerar que sea una chi cuadrado.
Finalmente veremos una distribución de qcauchy:
cauchy <- qcauchy(ppoints(30))
qqplot(n30, cauchy)
Las colas no se ajustan demasiado bien,, aunque los valores centrales sí.
Vamos a ver las diferentes formas para las distribuciones anteriores:
par(mfrow=c(1,2))
# Distribución normal
x <- seq(-3, 3, 0.01)
plot(x, dnorm(x)) # distribución de densidad de la distribución normal
plot(x, pnorm(x)) # dsitribución normal acumualtiva o de probabilidad
# Distribución chisquare
plot(x, dchisq(x, df=3))
plot(x, pchisq(x, df=3)) # función que empieza a acumular datos desde 0
# Distribución de cauchy
plot(x, dcauchy(x)) # Tiene colas muy importantes, parecida a la normal
plot(x, pcauchy(x))