Resumen Laboratorio EYP1113 2025-01

Introducción

Este resumen busca ser una herramienta práctica para enfrentar el Laboratorio de Probabilidad y Estadística (EYP1113). No está centrado en definiciones teóricas rigurosas ni en lenguaje formal, sino en aplicar los contenidos de manera concreta, tal como se trabajan en los ejercicios del curso.

En ningún caso se espera que este resumen reemplace las clases de laboratorio y el material que éste ofrece. Entiéndase este resumen solo como una ayuda adicional.

Por último mencionar que hay varias formas de resolver los problemas presentados en este resumen. Sin embargo para simplicidad y para omitir contenidos que no se profundizan mucho en este curso, se explicarán algunos solamente.

Conceptos básicos

Variables

Las variables en R son “cajitas” que guardan datos en memoria, lo que permite que se puedan referenciar después.

Se pueden definir de dos maneras:

  • X <- 5
  • X = 5

En estricto rigor, la flechita sigue la convención de los scripts formales de R, pero para efectos de este laboratorio, se puede usar = sin problema y va a funcionar igual.

Entorno

Todas las variables y objetos creados se guardan en el Entorno (Global Environment). Es como una lista de todas las variables que hayas guardado en tu sesión.

Puedes hacer click encima de las variables que tengas guardadas para consultar detalles sobre esta. Esto es especialmente útil para ver una tabla del dataframe que acabas de crear, para asegurarte que se haya seleccionado/filtrado bien (Ver en Manejo de Datos).

💡Recomendación: Borrar variables guardadas en el entorno

Antes de hacer cualquier ejercicio, borra todas las variables que tengas guardadas en tu entorno, ejecutando:

rm(list = ls())

De esta manera te aseguras de no trabajar con variables con valores antiguos que se te olvidaron redefinir.

Esto debido a que es mucho mejor recibir el error de variable indefinida, que calcular un resultado con una variable antigua y desactualizada. En ese último caso no hay forma de darse cuenta que el resultado obtenido esté malo.

Cuidado, que este comando borra TODAS las variables que tengas definidas. Si por alguna razón te interesa borrar una sola, puedes correr:

rm(nombre_de_la_variable)

Paquetes

Los paquetes son funciones hechas por otras personas que se pueden importar en tu código para facilitarte el trabajo.

Para usarlos, en primer lugar hay que instalarlos (si es que no lo has hecho antes) corriendo en la consola:

install.packages("nombre_del_paquete") # Usando las comillas ("")

Esto basta con hacerlo solo una vez (No pasa nada si los instalas varias veces). Teniéndolo instalado, solo debes cargarlo en la sesión ejecutando:

library(nombre_del_paquete) # Sin usar comillas

Habiendo hecho eso, ya puedes usar todas las funciones que el paquete ofrece.

💡Recomendación: Gana tiempo importando e instalando paquetes

En este curso, no son muchos los paquetes que se usan, pero son importantes. Al momento de rendir cualquier evaluación, que el primer paso sea ganar tiempo importando todo los paquetes que puedas utilizar e instalarlas en caso que aún no lo hayas hecho. Esto último es importante, porque puede que los computadores de la sala de computación no tengan todas los paquetes instalados.

Manejo de Datos

Se entiende por manejo de datos todo el proceso que empieza desde la base de datos que te entregan, hasta obtener los valores que te interesan, que te sirven para calcular lo solicitado en los ejercicios.

Esto implica:

  • Leer archivos

  • Convertirlos a DataFrames

  • Seleccionar columnas

  • Filtrar según condiciones

  • Entre otros…

Para mayor claridad, se trabajará este contenido con un ejemplo, usando la base de datos Spotify2.xlsx disponible en el Canvas del curso.

Lectura de archivos

⚠️Recuerda: Cargar los paquetes típicos

Salvo que se indique lo contrario, los paquetes que (casi siempre) se usan para el manejo de datos, se cargan con:

library(dplyr)
library(rio)

Para trabajar los datos de un archivo en R, siempre el primer paso es importarlo. En pocas palabras, esto significa guardar un archivo, que puede ser por ejemplo un excel o un csv, en una variable de R.

Las bases de datos suelen importarse y guardarse en objetos tipo DataFrame, que no son más que tablas (Las mismas que ves en un excel) que R puede operar fácilmente.

Por lo general, si es que no se indica de otra manera, la forma común de que en la evaluación se entreguen los datos sea a traves de un archivo excel. En ese caso, la manera mas simple y rápida de importar el dataframe sería:

ruta = file.choose() # Se abre una ventana donde tienes que seleccionar la ubicacion del archivo guardado
bd = import(ruta)
Ventana que se abre al usar file.choose()
Ventana que se abre al usar file.choose()

💡Recomendación: Verificar datos importados

Al guardar una base de datos en una variable, sea un vector o un dataframe, siempre puedes verla representada como tabla haciendo click sobre el nombre de ésta en la lista del entorno.

Esto es muy útil, porque permite verificar que la variable realmente sea lo que esperas. Puedes hacer lo mismo si filtras/seleccionas un dataframe, y quieres revisar que realmente haya funcionado.

También pueden hacerlo usando el comando head() y summary():

head(bd)
summary(bd)
##     Title              Artist            topGenre             Year          
##  Length:135         Length:135         Length:135         Length:135        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##    Popularity    Length_duration
##  Min.   :12.00   Min.   :154.0  
##  1st Qu.:41.00   1st Qu.:212.0  
##  Median :51.00   Median :244.0  
##  Mean   :53.03   Mean   :250.0  
##  3rd Qu.:64.50   3rd Qu.:268.5  
##  Max.   :98.00   Max.   :526.0

Seleccionar y Filtrar

Teniendo el dataframe creado, recomiendo dos principales métodos de seleccionar y filtrar los datos.

Funciones de Dplyr

El primero es usando las funciones del paquete dplyr, donde cada función es bien clara con lo que pretende hacer. Se usan de forma secuencial, donde entre cada paso se usa un operador pipe %>%, que representan una forma de decir “y luego haz esto…”.

Función Descripción Ejemplo
select(x, columnas) Selecciona del dataframe x las columnas indicadas select(bd, c("Artist", Year")
filter(x, condicion) Filtra del dataframe x las filas que cumplan con la/las condiciones indicadas filter(bd, bd$Year >= 2000 & bd$topGenre == "pop")
arrange(x, columna) Ordena el dataframe x según el valor de la columna indicada arrange(bd, Artist)
%>% Si bien el operador pipe no es de dplyr, se ocupa mucho. Representa una forma de decir “y luego haz esto…”
bd_filtrada = bd %>%
  filter(Year >= 2000 & topGenre == "pop") %>%
  select(c("Title", "Artist", "Year")) %>%
  arrange(Year)

Notar que no se usa el argumento bd en las funciones, porque el operador pipe “le pasa” el resultado a la próxima función.

Ver ejemplo para entenderlo:

Ejemplo: Seleccionar y Filtrar datos con Dplyr

Imaginar que nos piden un dataframe con los artistas, año y título de las canciones que se hayan publicado después del año 2000, sean del género pop, y que el resultado esté en orden creciente según el año.

Para eso “diseñamos” en palabras el código para que:

  1. A partir de la base de datos bd, luego que…
  2. Filtre por año > 2000 y por genero == "pop" y luego que…
  3. Seleccione solamente las columnas c("Title", "Artist", "Year") y luego que…
  4. Ordene según año

Notar que esos “y luego que” son exactamente lo mismo que hacen los operadores pipe en este ejemplo:

bd_filtrada = bd %>% 
  filter(Year >= 2000 & topGenre == "pop") %>% 
  select(c("Title", "Artist", "Year")) %>% 
  arrange(Year)

bd_filtrada

Subset()

El segundo método es mucho más simple, y si bien es más limitado que las funciones que ofrece dplyr, cubre la mayoría de las herramientas básicas de seleccionado/filtrado.

Se usa entonces la función subset(). Es un “comodín” porque sirve para casi todo.

Funcionalidad Aplicación
Filtrar subset(bd, bd$Year >= 2000 & bd$topGenre == "pop")
Seleccionar subset(bd, select = c("Title"))
Ambas subset(bd, bd$Year >= 2000, select = c("Title", "Artist))

Como se puede notar subset() es mucho más versátil, pero se limita a solo esas dos funcionalidades, pero que convenientemente son las que más se ocupan en este laboratorio.

Agrupar

Agrupar, es literalmente agrupar los datos según un determinado criterio, lo que permite después aplicar operaciones al grupo en conjunto.

Cabe mencionar que la función que hace esto group_by(), seguido por summarise() que aplica las operaciones por cada conjunto agrupado. Ambas son del paquete dplyr por lo que para este caso, la función subset() no es opción.

Ejemplo: group_by() y summarise()

Siguiendo el ejemplo de Spotify, nos podría interesar el promedio (media) de la popularidad de todas las canciones de cada artista. Eso implicaría agrupar por artista.

group_by(bd, Artist) %>% summarise(media = mean(Popularity))

Notar que con este método se podía resolver la segunda pregunta de la primera evaluación de laboratorio:

Medidas descriptivas

⚠️Recuerda: Cargar los paquetes

Los paquetes que se podrían usar en esta sección, se cargan con:

Las medidas descriptivas son formas de cuantificar propiedades del conjunto de datos. Recalcar que se aplican sobre vectores, o dicho de otra forma, una columna del dataframe de los datos (variable), no el dataframe completo.

Por ejemplo si queremos describir la popularidad de las canciones de la base de datos de Spotify2. Para otras medidas descriptivas de asociación, donde se requieren dos vectores (variables), también podríamos considerar el año de las canciones.

Tabla de medidas descriptivas

Sea x = bd$Popularity, y sea y = bd$Year

Medida Descriptiva Significado Código
Media (No confundir con mediana) Promedio de los datos mean(x)
Moda Dato más común o popular

Requiere paquete modeest

mlv(x)

Mediana (No confundir con media) Imagina ordenar todos los datos de menor a mayor en fila y seleccionar el dato que se encuentre justo en la mitad de esa fila que se forma. Eso es la mediana.

median(x)

o

cuantile(x, probs = 0.5)

Cuantíl Lo mismo que la mediana, pero no necesariamente la mitad de la fila, si no que por ejemplo, el 78% de la fila. cuantile(x, probs = 0.78)
Mínimo/Máximo El menor/mayor valor que pueden tomar los datos.

min(x)

y

max(x)

Varianza Mide cuanto se alejan los datos entre si var(x)
Desviación Estándar Raíz cuadrada de la varianza. sd(x)
Coeficiente de Variación Desviación estándar dividido en la media sd(x)/mean(x)
Rango Rango de valores por el cual se distribuyen max(x)-min(x)
Rango intercuartil Lo mismo que el rango, pero considerando solo entre el primer y el tercer cuartil. IQR(x)
Covarianza Indica como se relacionan dos variables entre sí cov(x,y)
Correlación Similar a la covarianza, pero se mueve en un ragno de -1 a +1. cor(x,y)
Asimetría Indica hacia que lado esta la “cola” de la funcion de densidad de los datos. Si la cola esta a la derecha, tiene skewness positiva, negativa en caso contrario.

Requiere paquete moments

skewness(x)

Kurtosis Indica que tan puntiaguda es la curva de la función de densidad de los datos. Como referencia, la kurtosis de la normal estandar es igual a 3.

Requiere paquete moments

kurtosis(x)

Recomendación: describe() para casi todas las medidas descriptivas.

La función describe() del paquete psych te entrega casi todas las medidas descriptivas mas útiles y comunes. Permite como argumento un dataframe completo, indicando cada medida para cada variable.

library(psych)
bd %>% 
  select(Year, Popularity, Length_duration) %>% 
  mutate(Year = as.numeric(Year)) %>% # String => Numeric
  describe()

Cálculo de probabilidades y cuantiles de distribuciones

R tiene varios modelos de probabilidad incluidos, cada uno identificado por su nombre. Para usarlos, solo basta con plantear lo que se quiere calcular, especificar la función que quieres aplicar (d, p o q) seguido del nombre de la distribución e indicar los valores de los argumentos correspondientes.

Para cualquier distribución * , proporciona la funcionalidades para:

Función de densidad

Considerando la distribución *, para evaluar un valor a en la función de densidad de *, se ejecuta:

d*(x = a, [parámetros de *])

Lo que equivale a \(f_x(a)\) o \(p_x(a)\), para variables continuas y discretas respectivamente.

Ejemplo: Evaluación en función de densidad continua v/s discreta

Digamos que una variable X representa la altura (en metros) de las jirafas en un zoológico. X distribuye Normal con parámetros \(\mu=5\) y \(\sigma=0.8\). Si evaluamos x = 6 en la función densidad:

dnorm(x = 6, mean = 5, sd = 0.8)
## [1] 0.2283114

Obtenemos \(f_x(x=7) = 0.228\) , que representa la densidad de probabilidad en el punto exacto de 7 metros. Ojo, que no es una probabilidad directa, porque la distribución normal al ser continua, sus probabilidades existen solamente en intervalos. La probabilidad de encontrar una jirafa que mida exactamente 7 metros es casi nula, porque la altura, al ser una unidad continua, se puede mover en un rango de milésimas o incluso millonésimas de metro. Entonces en este caso, 0.228 se puede interpretar como la altura relativa de la curva en x=7 o dicho de otra manera, mide qué tan “probable” es encontrar valores cercanos a 7 comparado con otros puntos.

Por otro lado, ahora digamos que la variable Y representa la cantidad de “6” obtenidos al lanzar 20 veces un dado. Cada lanzamiento es independiente entre sí, y la probabilidad de obtener el “6” (o cualquier número en un dado de 6 caras) es siempre de 1/6. Como estamos contando cantidad de casos exitosos en un experimento de bernoulli, podemos decir que \(Y\sim Binomial(p = 1/6, n = 20)\) y su función de densidad evaluada en 5 \(p_Y(y=5)\) el R sería:

dbinom(x = 5, size = 20, prob = 1/6)
## [1] 0.1294103

Esto se puede interpretar, como la probabilidad exacta de obtener 5 dados con la cara “6”, en un total de 20 lanzamientos. Ahora como estamos hablando de unidades discretas (cantidad de éxitos) sí podemos afirmar que evaluando en la función de probabilidad discreta obtenemos la probabilidad exacta de lo que se obtenga y cantidades de casos exitosos.

Función de probabilidad acumulada

Si lo que queremos es calcular la probabilidad acumulada hasta cierto quantil, imaginamos el área bajo la curva generada por la funcióin densidad.

Dependiendo de lo que se nos esté preguntando, es tarea de nosotros definir ese intervalo de integración (Nada más, R se encarga de integrar).

\[ P(X \leq a) = F_X(a) = \boxed{\int_{-\infty}^a f_X(x) ~ dx} \Rightarrow (Eso~lo~calcula~R) \]

Equivalente a correr: p*(q = a, [parámetros de *])

Lo único desafiante, o de lo que deberíamos estar atentos, es cuando nos piden una probabilidad acumulada en un intervalo no muy evidente, donde se deben recordar las siguientes propiedades:

\[ P(X > a) = 1-P(X\leq a) \]

\[ P(a < X \leq b) = P(X\leq b) - P(X\leq a) \]

Esto último considerando X como una variable continua. Particularmente, si X fuera una variable discreta, la única consideración que hay que tomar en cuenta es:

\[ P(X < a) = P(X \leq (a-1))\] Pues, se calcula el con el límite de la sumatoria como un valor entero.

Recomendación: Cálculo de probabilidades acumuladas

Si es que te cuesta recordar las propiedades y equivalencias recién indicadas, o si te quieres asegurar de no estar cometiendo un error, puedes dibujar una función de densidad a la rápida e ir viendo gráficamente las probabilidades acumuladas que te piden.

Literalmente hice eso en Paint para la primera evaluación:

Puede parecer ridículo, pero es buena forma de asegurarse que estas planteando bien la probabilidad que te están pidiendo.

Ejemplo: Pregunta 3 de evaluación 1

Nos piden:

\[ P(30 < X \leq 50) = P(X \leq 50) - P(X\leq 30) = F_X(50) - F_X(30) \]

Entonces:

# Se importan los datos
ruta_bd_ev1 = "data/Fuga_muestraV.xlsx";
bd_ev1 = import(ruta_bd_ev1);
x = bd_ev1$Edad;

# Se definen los parámetros que se usarán
k = 10.08;
v = k / mean(x);

# Se calcula la probabilidad pedida
pgamma(q = 50, shape = k, rate = v) - pgamma(q = 30, shape = k, rate = v)
## [1] 0.5728773

Cuantiles

Calcular cuantiles corresponde a determinar el valor de c mediante el cual:

\[ P(X\leq c) = p_0 \]

para una probabilidad p0. Entonces, no es más que la inversa de probabilidad acumulada. Para una distribución *, determinar lo anterior equivale a correr:

q*(p = p0, [parámetros de *])

Ejemplo: Pregunta 3 de evaluación 1

Solamente basta con correr:

# Se importan los datos
ruta_bd_ev1 = "data/Fuga_muestraV.xlsx";
bd_ev1 = import(ruta_bd_ev1);
x = bd_ev1$Edad;

# Se definen los parámetros que se usarán
k = 10.08;
v = k / mean(x);

# Se calculan los cuantiles pedidos
qgamma(p = 0.25, shape = k, rate = v)
## [1] 28.91352
qgamma(p = 0.75, shape = k, rate = v)
## [1] 44.50759

Distribuciones conjuntas, marginales y condicionales

La forma más fácil de entender el cálculo de distribuciones conjuntas, marginales y condicionales, es primero comprendiendo el ejemplo realizado en el laboratorio (tabla) desde donde uno puede sacar la idea principal.

Desde ahí, entender el calculo de conjuntas, marginales y concicionales como se ve en cátedra es mucho mas intuitivo.

Suponer que trabajamos con dos variables aleatorias X e Y de 159 estudiantes de EYP1113:

  • X es el género

  • Y es la edad

Cada celda representa la cantidad de personas que comparten el mismo/s atributo/s. Es decir que corresponde a una tabla de frecuencias.

Masculino Femenino
22 años 24 27
23 años 21 26
24 años 18 15
25 años 15 8
26 años 4 1

Si lo que queremos es tener una tabla fracciones marginales, hay que dividir cada celda por la cantidad total de personas en la muestra, es decir por 159. De este modo, ahora la suma de todas las celdas debería dar igual a 1.

Masculino Femenino
22 años 0,151 0,170
23 años 0,132 0,164
24 años 0,113 0,094
25 años 0,094 0,050
26 años 0,025 0,006

Para tenerlo en código, podemos correr esto para formar las tablas:

# Suponer que tenemos un dataframe con estos datos de estudiantes
df
# Teniendo el dataframe, se convierte a tabla de frecuencias con table()
tabla_frecuencias = table(df$edad, df$genero)
tabla_frecuencias
##     
##      masculino femenino
##   22        24       27
##   23        21       26
##   24        18       15
##   25        15        8
##   26         4        1
# Para la tabla de fracciones marginales, corremos:
tabla_prob_conjunta = prop.table(tabla_frecuencias)

# Uso round para redondear los decimales
round(tabla_prob_conjunta,3)
##     
##      masculino femenino
##   22     0.151    0.170
##   23     0.132    0.164
##   24     0.113    0.094
##   25     0.094    0.050
##   26     0.025    0.006

Antes de comenzar, algunas operaciones de table() muy útiles:

# Conviene contar la cantidad de datos que tenemos. Para eso se puede sumar el total de filas del dataframe con el que creamos la tabla
n = nrow(df) # 159

Notar que table() es indexeable, quiere decir que se puede determinar:

  • tabla[fila,columna] => una celda

  • tabla[ ,columna] => una columna

  • tabla[fila, ] => una fila

# Para sumar valores de las columnas
colSums(tabla_prob_conjunta)
## masculino  femenino 
## 0.5157233 0.4842767
# o una columna especifica
sum(tabla_prob_conjunta[,"masculino"])
## [1] 0.5157233
# Para sumar valores de las filas
rowSums(tabla_prob_conjunta)
##         22         23         24         25         26 
## 0.32075472 0.29559748 0.20754717 0.14465409 0.03144654
# o una fila especifica
sum(tabla_prob_conjunta["24",])
## [1] 0.2075472

Distribución conjunta

Es la propabilidad de X e Y tomen valores específicos al mismo tiempo. Equivale a preguntar: “Pro

Distribución marginal

Distribución condicional

Normal Bivariada

Transformación de variables y Teorema del Limite Central

Estimación de parámetros

[Pendiente]