"""Reproducible analysis for: Student Outcomes Study

Generated by thericerca on 2026-07-30 21:03 UTC.
Regenerate the same statistical output on the same data by running this script (or the
matching .ipynb) with the third-party libraries at the top installed.

Statement of the problem:
  This study examines student academic outcomes.

Objectives:
  - To describe the age, study_hours, gpa, and satisfaction of the respondents.
  - To determine the relationship between study_hours and gpa.
  - To determine the relationship between age and gpa.
  - To determine whether gpa differs across the program groups.
  - To determine whether study_hours differs across the program groups.
  - To determine the association between gender and civil_status.
  - To determine the association between gender and program.

"""

import pandas as pd
import numpy as np
from scipy import stats
import statsmodels.api as sm
import statsmodels.formula.api as smf


# Load the dataset. Point this at your local copy of 'survey.csv'.
df = pd.read_csv('survey.csv')
print(f'Loaded {len(df)} rows, {len(df.columns)} columns.')
df.head()


# ------------------------------------------------------------------------------
# [1/8] Descriptive Statistics
#   Question: To describe the age, study_hours, gpa, and satisfaction of the respondents.
# ------------------------------------------------------------------------------
cols = ['age', 'study_hours', 'gpa']
print(df[cols].describe(include='all').T)


# ------------------------------------------------------------------------------
# [2/8] Frequency & Percentage Distribution
#   Question: To describe the age, study_hours, gpa, and satisfaction of the respondents.
# ------------------------------------------------------------------------------
# Frequency & percentage distribution for each categorical variable.
vc = df['satisfaction'].value_counts(dropna=False)
print(pd.DataFrame({'n': vc, 'pct': (vc / vc.sum() * 100).round(2)}))


# ------------------------------------------------------------------------------
# [3/8] Spearman Rank Correlation
#   Question: To determine the relationship between study_hours and gpa.
# ------------------------------------------------------------------------------
a, b = df['study_hours'].dropna(), df['gpa'].dropna()
pair = pd.concat([a, b], axis=1).dropna()
rho, p_value = stats.spearmanr(pair.iloc[:, 0], pair.iloc[:, 1])
print(f'rho = {rho:.3f}, p = {p_value:.4g}, n = {len(pair)}')


# ------------------------------------------------------------------------------
# [4/8] Pearson Correlation
#   Question: To determine the relationship between age and gpa.
# ------------------------------------------------------------------------------
a, b = df['age'].dropna(), df['gpa'].dropna()
pair = pd.concat([a, b], axis=1).dropna()
r, p_value = stats.pearsonr(pair.iloc[:, 0], pair.iloc[:, 1])
print(f'r = {r:.3f}, p = {p_value:.4g}, n = {len(pair)}')


# ------------------------------------------------------------------------------
# [5/8] One-Way ANOVA
#   Question: To determine whether gpa differs across the program groups.
# ------------------------------------------------------------------------------
model = smf.ols(f'Q("gpa") ~ C(Q("program"))', data=df).fit()
aov = sm.stats.anova_lm(model, typ=2)
print(aov)


# ------------------------------------------------------------------------------
# [6/8] One-Way ANOVA
#   Question: To determine whether study_hours differs across the program groups.
# ------------------------------------------------------------------------------
model = smf.ols(f'Q("study_hours") ~ C(Q("program"))', data=df).fit()
aov = sm.stats.anova_lm(model, typ=2)
print(aov)


# ------------------------------------------------------------------------------
# [7/8] Chi-Square Test of Independence
#   Question: To determine the association between gender and civil_status.
# ------------------------------------------------------------------------------
contingency = pd.crosstab(df['gender'], df['civil_status'])
chi2, p_value, dof, expected = stats.chi2_contingency(contingency)
n = contingency.values.sum()
cramers_v = np.sqrt(chi2 / (n * (min(contingency.shape) - 1)))
print(f'chi2 = {chi2:.3f}, df = {dof}, p = {p_value:.4g}, Cramer\'s V = {cramers_v:.3f}, N = {n}')
print(contingency)


# ------------------------------------------------------------------------------
# [8/8] Chi-Square Test of Independence
#   Question: To determine the association between gender and program.
# ------------------------------------------------------------------------------
contingency = pd.crosstab(df['gender'], df['program'])
chi2, p_value, dof, expected = stats.chi2_contingency(contingency)
n = contingency.values.sum()
cramers_v = np.sqrt(chi2 / (n * (min(contingency.shape) - 1)))
print(f'chi2 = {chi2:.3f}, df = {dof}, p = {p_value:.4g}, Cramer\'s V = {cramers_v:.3f}, N = {n}')
print(contingency)


# ------------------------------------------------------------------------------
# End of thericerca reproducible analysis.
# ------------------------------------------------------------------------------
