1 📤 Introduccion

Conjunto datos sintéticos que simula los comportamientos académicos y de estilo de vida de 80.000 estudiantes, incluyendo variables diversas como hábitos de estudio, salud mental, entorno familiar, motivación y factores ambientales. El objetivo es analizar cómo distintas variables influyen en el rendimiento estudiantil, medido a través del promedio académico (GPA) y las calificaciones en exámenes

2 🎯 Datos

2.1 📂 Origen del dataset y descripción de variables

Los datos utilizados fueron descargados de Kaggle y corresponden a un conjunto sintético que simula los hábitos, entorno y rendimiento académico de 80.000 estudiantes.

2.2 ✏️ Variables incluidas

  • student_id: Identificador único del estudiante.
  • age: Edad del estudiante (16 a 28 años).
  • gender: Género (Male, Female u Other).
  • major: Carrera o área de estudios (Ej: Ingeniería, Arte, Ciencias de la Computación).
  • study_hours_per_day: Promedio de horas de estudio diario.
  • social_media_hours, netflix_hours, screen_time: Tiempo de exposición a pantallas y redes sociales.
  • part_time_job: Indica si el estudiante tiene un empleo a medio tiempo (Yes/No).
  • attendance_percentage: Porcentaje de asistencia académica.
  • sleep_hours, exercise_frequency, diet_quality: Factores de estilo de vida.
  • mental_health_rating, stress_level, exam_anxiety_score: Indicadores psicológicos (escala de 1 a 10).
  • extracurricular_participation, access_to_tutoring: Apoyo y actividades extracurriculares.
  • family_income_range, parental_support_level, parental_education_level: Variables socioeconómicas y apoyo familiar.
  • motivation_level, time_management_score: Habilidades de autogestión (escala de 1 a 10).
  • learning_style: Estilo de aprendizaje preferido.
  • study_environment: Ambiente habitual de estudio.
  • dropout_risk: Riesgo estimado de abandono (Yes/No), calculado a partir de estrés y motivación.
  • previous_gpa, exam_score: Variables objetivo relacionadas con el rendimiento académico.
##install.packages("reticulate")# Recién reiniciada la sesión:
library(reticulate)
reticulate::use_condaenv("r_env_nuevo", required = TRUE)
#reticulate::py_install(c("scikit-learn", "matplotlib"), envname = "r_env_nuevo")

#reticulate::py_install("pyarrow")
reticulate::py_install("seaborn")
## + "C:/Users/nicol/miniconda3/condabin/conda.bat" install --yes --prefix "C:/Users/nicol/miniconda3/envs/r_env_nuevo" -c conda-forge seaborn

3 🧮 Metodología

Metodología de análisis predictivo basada en regresión lineal múltiple

3.1 Tipo de metodología aplicada

  1. Análisis exploratorio de datos (EDA)
    • Limpieza, normalización y renombrado de columnas.
    • Revisión de valores faltantes o mal codificados.
    • Cálculo de correlaciones para entender relaciones entre variables.
  2. Modelado estadístico con regresión lineal múltiple
    • Construcción de un modelo para predecir la variable nota_examen utilizando múltiples variables independientes (previous_gpa y exam_anxiety_score).
    • Interpretación de coeficientes, intercepto, error cuadrático medio (MSE) y coeficiente de determinación (R²).
  3. Visualización de resultados
    • Uso de regresiones 2D con seaborn para representar gráficamente la relación entre cada variable predictora y la variable objetivo.
    • Inclusión de gráficos que respaldan la interpretación numérica.
  4. Comunicación e interpretación de resultados
    • Traducción de los coeficientes estadísticos a conclusiones interpretables en lenguaje natural.
    • Evaluación de la calidad del modelo y sus limitaciones.

4 🧱 Lectura y limpieza de datos

import polars as pl
import pandas as pd
import numpy as np

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt

# 1. Leer CSV con Polars
df = pl.read_csv(
   r"C:\Users\nicol\Documents\Curso Big Data 2025 Sudameris\Trabajo Final\archive\enhanced_student_habits_performance_dataset.csv",
    separator=";",         # muy importante
    encoding="latin1"   
)
df 
shape: (80_000, 31)
student_idagegendermajorstudy_hours_per_daysocial_media_hoursnetflix_hourspart_time_jobattendance_percentagesleep_hoursdiet_qualityexercise_frequencyparental_education_levelinternet_qualitymental_health_ratingextracurricular_participationprevious_gpasemesterstress_leveldropout_risksocial_activityscreen_timestudy_environmentaccess_to_tutoringfamily_income_rangeparental_support_levelmotivation_levelexam_anxiety_scorelearning_styletime_management_scoreexam_score
i64i64strstrstrf64f64strf64f64stri64strstrstrstrf64i64f64stri64f64strstrstri64i64i64strf64i64
10000026"Male""Computer Scien…"11,46"3.00.1"Yes"70.36.2"Poor"3"Some College""High""6.0""Yes"4.055.8"No"010.9"Co-Learning Gr…"Yes""High"968"Reading"3.0100
10000128"Male""Arts""10,85"0.50.4"No"88.47.2"Good"4"PhD""Low""6.8""No"4.075.8"No"58.3"Co-Learning Gr…"Yes""Low"7710"Reading"6.099
10000217"Male""Arts""1,21"4.20.7"No"82.19.2"Good"4"High School""Low""5.7""Yes"3.7948.0"No"58.0"Library""Yes""High"346"Kinesthetic"7.698
10000327"Other""Psychology""10,37"4.62.3"Yes"79.34.2"Fair"3"Master""Medium""8.5""Yes"4.064.6"No"311.7"Co-Learning Gr…"Yes""Low"5710"Reading"3.2100
10000425"Female""Business""9,29"0.82.7"Yes"62.96.5"Good"6"PhD""Low""9.2""No"4.045.7"No"29.4"Quiet Room""Yes""Medium"9410"Reading"7.198
10000517"Female""Engineering""8,4"0.52.5"No"49.29.2"Good"3"PhD""High""9.2""Yes"4.031.5"No"28.9"Quiet Room""No""High"1105"Visual"3.994
10000619"Male""Psychology""6,24"2.42.2"Yes"97.98.5"Good"6"Some College""High""5.8""No"4.022.5"No"39.2"Dorm""Yes""High"548"Kinesthetic"10.097
10000717"Male""Psychology""10,4"3.20.9"No"44.37.4"Fair"5"Master""High""4.8""Yes"3.325.3"No"310.0"Co-Learning Gr…"Yes""Low"9610"Kinesthetic"7.584
10000828"Female""Psychology""5,35"0.32.6"Yes"64.27.6"Fair"0"High School""Medium""3.5""No"2.6124.0"No"34.8"Library""No""Low"4310"Kinesthetic"5.870
10000919"Male""Engineering""0,72"1.11.6"Yes"40.17.2"Fair"6"Master""Low""5.9""Yes"3.7823.3"No"18.0"Cafe""Yes""Medium"786"Auditory"7.0100
10001016"Other""Arts""1,6"2.70.2"No"44.16.9"Poor"2"Some College""High""7.8""Yes"4.013.7"No"33.9"Co-Learning Gr…"Yes""Medium"275"Visual"3.2100
10001126"Other""Biology""9,54"3.21.8"No"40.68.1"Good"1"PhD""Low""4.0""Yes"4.062.0"No"010.8"Dorm""No""Low"226"Auditory"2.9100
17998828"Female""Engineering""0,58"3.80.0"Yes"50.39.3"Poor"4"PhD""Medium""7.2""Yes"4.013.2"No"28.4"Cafe""Yes""High"515"Kinesthetic"5.898
17998919"Other""Business""10,59"4.63.8"No"57.17.5"Good"1"PhD""High""5.2""Yes"2.6366.7"No"113.4"Cafe""No""High"2810"Auditory"8.865
17999025"Male""Engineering""3,85"2.43.2"Yes"89.87.3"Poor"7"PhD""Low""4.7""No"4.033.4"No"48.6"Library""Yes""Low"1079"Auditory"1.792
17999124"Female""Engineering""11,06"2.51.2"Yes"62.34.1"Good"1"Bachelor""High""6.4""Yes"3.0627.6"No"25.2"Dorm""No""High"4910"Visual"4.081
17999220"Other""Computer Scien…"4,06"0.63.9"Yes"66.05.3"Good"6"PhD""Low""7.9""Yes"3.0767.9"No"010.5"Co-Learning Gr…"Yes""Low"218"Auditory"3.276
17999328"Male""Arts""9,4"1.91.9"Yes"75.75.3"Good"4"Master""Medium""9.0""No"2.6233.5"No"16.1"Quiet Room""Yes""Medium"2210"Kinesthetic"8.360
17999424"Other""Business""4,4"3.22.6"No"96.06.8"Good"3"Bachelor""Low""5.4""Yes"4.052.1"No"29.7"Library""No""Low"2210"Auditory"1.6100
17999516"Male""Engineering""11,09"2.11.0"Yes"80.86.1"Fair"0"High School""Medium""1""No"3.422.1"No"18.3"Library""No""Low"1810"Auditory"5.388
17999616"Female""Business""8,98"0.42.9"No"99.54.1"Good"0"Some College""Low""5.7""Yes"2.2613.9"No"34.7"Co-Learning Gr…"No""Low"3610"Kinesthetic"6.852
17999726"Female""Arts""5,91"1.61.6"Yes"46.18.3"Good"7"Master""Low""6.7""Yes"3.1535.6"No"37.5"Dorm""No""Medium"7510"Visual"1.389
17999823"Other""Biology""3,84"0.63.5"Yes"58.75.8"Good"2"PhD""High""7.6""Yes"3.6762.4"No"49.3"Quiet Room""Yes""Low"237"Kinesthetic"3.796
17999925"Other""Engineering""5,91"4.53.4"Yes"97.75.3"Fair"1"Some College""High""3.5""No"4.072.8"No"012.2"Co-Learning Gr…"Yes""Medium"167"Reading"6.7100
# 2. Normalizar nombres de columna
mapping = {
    col: (
        col.strip().lower()
           .replace("á","a").replace("é","e")
           .replace("í","i").replace("ó","o")
           .replace("ú","u").replace("ñ","n")
           .replace(" ", "_").replace("/", "_")
    )
    for col in df.columns
}
df = df.rename(mapping)
# 3. Convertir a pandas para usar .corr()
pdf = df.to_pandas()

# 4. Filtrar solo columnas numéricas
numeric_cols = pdf.select_dtypes(include="number").columns

# 5. Calcular correlaciones con exam_score
correlaciones = pdf[numeric_cols].corr()["exam_score"].sort_values(ascending=False)

# 6. Mostrar resultados Correlacion
print(correlaciones)
## exam_score                1.000000
## previous_gpa              0.932940
## screen_time               0.169788
## sleep_hours               0.090820
## exercise_frequency        0.086983
## student_id                0.007557
## time_management_score     0.005940
## attendance_percentage     0.002876
## semester                  0.000541
## age                       0.000487
## motivation_level          0.000021
## netflix_hours            -0.001271
## social_activity          -0.002795
## parental_support_level   -0.006333
## social_media_hours       -0.006351
## stress_level             -0.118550
## exam_anxiety_score       -0.235909
## Name: exam_score, dtype: float64
# 7. Seleccionar y limpiar las variables más relevantes
df = (
    df
    .select([
        pl.col("previous_gpa").alias("promedio_anterior"),
        pl.col("exam_anxiety_score").alias("ansiedad_examen"),
        pl.col("exam_score").alias("nota_examen")
    ])
    .with_columns([
        pl.col("promedio_anterior")
          .str.replace(",", ".")
          .cast(pl.Float64),
        pl.col("ansiedad_examen")
          .str.replace(",", ".")
          .cast(pl.Float64),
        pl.col("nota_examen")
          .str.replace(",", ".")
          .cast(pl.Float64)
    ])
    .drop_nulls()
)

# 8. Convertir a pandas (ya hecho antes)
pdf = df.to_pandas()
X = pdf[["promedio_anterior", "ansiedad_examen"]].values
y = pdf["nota_examen"].values

# 9. Entrenar regresión
model = LinearRegression().fit(X, y)
y_pred = model.predict(X)

# 10. Métricas
print(f"Coeficientes: {model.coef_}")
## Coeficientes: [2.33810692e+01 1.81972239e-02]
print(f"Intercepto: {model.intercept_:.2f}")
## Intercepto: 4.76
print(f"MSE: {mean_squared_error(y, y_pred):.2f}")
## MSE: 17.42
print(f"R²: {r2_score(y, y_pred):.4f}")
## R²: 0.8704
import matplotlib.pyplot as plt
import seaborn as sns

# 11. Primer gráfico: Nota vs. Promedio Anterior
plt.figure(figsize=(8,6))
sns.regplot(x=pdf["promedio_anterior"], y=pdf["nota_examen"], scatter_kws={'alpha':0.6})
plt.title("Nota de Examen vs. Promedio Anterior")
plt.xlabel("Promedio Anterior")
plt.ylabel("Nota de Examen")
plt.grid(True)
plt.tight_layout()
plt.show()

# 12. Segundo gráfico: Nota vs. Ansiedad de Examen
plt.figure(figsize=(8,6))
sns.regplot(x=pdf["ansiedad_examen"], y=pdf["nota_examen"], scatter_kws={'alpha':0.6}, color="orange")
plt.title("Nota de Examen vs. Ansiedad ante el Examen")
plt.xlabel("Ansiedad en Examen")
plt.ylabel("Nota de Examen")
plt.grid(True)
plt.tight_layout()
plt.show()

5 📈 Interpretación del modelo de regresión

5.1 📊 Análisis 1: Influencia del Promedio Anterior (previous_gpa)

Pendiente (coeficiente ≈ 0.93)
Cada punto adicional en el promedio académico previo se asocia con un incremento estimado de 0.93 puntos en la nota del examen.

Intercepto (≈ valor obtenido)
Representa la nota esperada cuando el promedio previo es cero. No tiene interpretación práctica directa, pero permite ajustar la línea de predicción.

Calidad del ajuste
- MSE: [valor]
- R² ≈ 0.93 → aproximadamente el 93 % de la variación en la nota puede explicarse por el promedio anterior. Es un predictor altamente confiable.


5.2 🧠 Análisis 2: Influencia de la Ansiedad de Examen (exam_anxiety_score)

Pendiente (coeficiente ≈ -0.23)
Indica que cada punto más en el nivel de ansiedad se asocia con una disminución estimada de 0.23 puntos en la nota.

Intercepto (≈ valor obtenido)
Nota estimada cuando la ansiedad es cero. Funciona como base del modelo, aunque no siempre tiene sentido práctico.

Calidad del ajuste
- MSE: [valor]
- R² ≈ 0.05 → solo el 5 % de la variación se explica por la ansiedad. Es un factor relevante pero débil por sí solo.


6 📌 Conclusión General

🔎 Conclusión: El promedio anterior es un predictor fuerte del rendimiento, mientras que la ansiedad aporta una señal más suave pero aún valiosa si se combina con otras variables.

7 ✅Referencias