Análisis de rendimiento Académico
Análisis Exploratorio de Datos
# 1. IMPORTAR LAS LIBRERIAS
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# MIRO LAS PRIMERO 5 FILAS
df.head()
# MIRO LAS ULTIMAS 5 FILAS
df.tail()
# OBTENGO UN RESUMEN ESTADÍSTICO
df.describe()
# 3. REVISAR LOS TIPOS DE DATOS
df.dtypes
# 4. ELIMINAR DUPLICADOS
# Primero imprimo el conteo de las filas totales del dataframe, con el id.
print(f'Original: {df.id.count()} filas')
# Genero un set de datos duplicados con el metodo duplicated
duplicate_rows_df = df[df.duplicated()]
print(f'Cantidad de filas duplicadas: {duplicate_rows_df.id.count()}')
# ELIMINAR LOS DUPLICADOS
df = df.drop_duplicates()
# Cuento las filas luego de eliminar los duplicados
print(f'Final filas: {df.id.count()} filas')
# 5. ELIMINAR LAS COLUMNAS IRRELEVANTES
# Primero veo que columnas tengo
print(df.columns)
# Elimino la columna id, porque ya no es necesaria
df = df.drop(['id'], axis=1)
print(df.columns)
# 6. RENOMBRAR LAS COLUMNAS
df = df.rename(columns= {
"gender":"Gender",
"race/ethnicity":"Ethnicity",
"parental level of education": "Parental level of education",
"lunch": "Lunch",
"employed": "Employed",
"test preparation course":"Test preparation course",
"math score":"Math score",
"physics score": "Physics score",
"chemistry score": "Chemistry score",
"algebra_score": "Algebra score"
})
df.columns
# 7. ELIMINAR LOS VALORES PERDIDOS O NULOS
#Encontrar los valores nulos
print(df.isnull().sum())
#Eliminar los valores perdidos
df = df.dropna()
print(df.isnull().sum())
#Verifico la cantidad de filas que me quedaron
print(f'Final filas: {df.Gender.count()} filas')
# 8. DETECTAR LOS OUTLIERS
sns.boxplot(x=df['Math score'])
plt.show()
sns.boxplot(x=df['Physics score'])
plt.show()
sns.boxplot(x=df['Algebra score'])
plt.show()
sns.boxplot(x=df['Chemistry score'])
plt.show()
print(f'Antes: 993 filas\n')
Q1 = df.quantile(0.25)
Q3 = df.quantile(0.75)
IQR = Q3 - Q1
print(IQR)
df = df[~((df < (Q1-1.5 * IQR))|(df > (Q3 + 1.5 * IQR))).any(axis=1)]
print(f'\nDespues: {df.Lunch.count()} filas\n')
# 9. ENCONTRAR CORRELACIONES Y FRECUENCIAS
plt.hist(df['Algebra score'], bins=20)
plt.title('Algebra')
plt.ylabel('Student count')
plt.xlabel('Score')
plt.show()
plt.hist(df['Chemistry score'], bins=20)
plt.title('Chemistry')
plt.ylabel('Student count')
plt.xlabel('Score')
plt.show()
plt.hist(df['Math score'], bins=20)
plt.title('Math')
plt.ylabel('Student count')
plt.xlabel('Score')
plt.show()
plt.hist(df['Physics score'], bins=20)
plt.title('Physics')
plt.ylabel('Student count')
plt.xlabel('Score')
plt.show()
# Correlación entre los datos = Mapas de calor
c = df.corr()
print(c)
plt.figure(figsize=(20,10))
sns.heatmap(c, cmap='BrBG', annot=True)
plt.show()
# pandas.value_counts() -> devuelve una Serie con valores únicos en orden descendiente de frecuencia
labels = df["Gender"].value_counts().index
sizes = df["Gender"].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title("Gender")
plt.show()
# Repito para Etnia y Empleo y algunas categorias más.
labels = df['Ethnicity'].value_counts().index
sizes = df['Ethnicity'].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title('Ethnicity')
plt.show()
labels = df['Employed'].value_counts().index
sizes = df['Employed'].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title('Employed')
plt.show()
labels = df['Test preparation course'].value_counts().index
sizes = df['Test preparation course'].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title('Test preparation course')
plt.show()
labels = df['Parental level of education'].value_counts().index
sizes = df['Parental level of education'].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title('Parental level of education')
plt.show()
labels = df['Lunch'].value_counts().index
sizes = df['Lunch'].value_counts()
plt.pie(sizes, labels=labels, autopct='%1.2f%%')
plt.title('Lunch')
plt.show()
Respondiendo Preguntas
Ejemplo: ¿Hay alguna relación entre el promedio de notas obtenidas y el hecho de haber realizado el curso preparatorio?
df['Averange Score'] = df.mean(axis=1)
# axis = 1 hace que aplique la función sobre los valores numéricos de la fila en lugar de las columnas
df
si = df[df['Test preparation course'] == 'completed']
no = df[df['Test preparation course'] == 'none']
sns.histplot(si['Averange Score'], color = 'green', alpha=.4, fill = True)
sns.histplot(no['Averange Score'], color = 'red' , alpha = .4, fill = True)
plt.show()
print('Realizaron el curso:' ,si['Test preparation course'].count())
print('No realizaron el curso:', no['Test preparation course'].count())
Conclusión: La cantidad de alumnos que no realizó el curso preparatorio duplica al numero de los que si lo realizaron, esta diferencia no es significativa en el promedio de notas.
Una opción podría ser revisar los contenidos o el dictado de los cursos a fin de lograr un mayor porcentage de aprobación de los cursos.
Ejemplo: ¿Hay alguna relación entre el promedio de notas obtenidas y el genero?
Masculino = df[df['Gender'] == 'male']
Femenino = df[df['Gender'] == 'female']
sns.histplot(Masculino['Averange Score'], color = 'blue', alpha=.4, fill = True)
sns.histplot(Femenino['Averange Score'], color = 'red' , alpha = .4, fill = True)
plt.show()
print('Masculinos:' ,Masculino['Gender'].count())
print('Femeninos:', Femenino['Gender'].count())
Conclusión: Como era de esperar no se observan diferencias en las propociones de aprobación de los examenes y los generos de las personas. Se puede observar que no existe sesgo negativo en los datos.