Taula de continguts

1 Preprocessament

1.1 Nom de les variables

Enunciat:

Carregueu el fitxer de dades “Findata.csv”.

Resposta:

fin_df <- fread(
  "data/Findata.csv", # Camí al fitxer
  dec = ".", # Caràcter decimal
  data.table = FALSE # Data frame de R (no data.table)
)

Enunciat:

Comproveu els tipus de dades de les variables.

Resposta:

sapply(fin_df, class)
##                             V1                            Age 
##                      "integer"                      "numeric" 
##                         Gender                    Weight..kg. 
##                    "character"                    "character" 
##                     Height..m.                        Max_BPM 
##                    "character"                      "numeric" 
##                        Avg_BPM                    Resting_BPM 
##                      "numeric"                      "numeric" 
##       Session_Duration..hours.                Calories_Burned 
##                      "numeric"                      "numeric" 
##                   Workout_Type                 Fat_Percentage 
##                    "character"                      "numeric" 
##          Water_Intake..liters.  Workout_Frequency..days.week. 
##                      "numeric"                      "numeric" 
##               Experience_Level                            BMI 
##                      "integer"                      "numeric" 
##          Daily.meals.frequency              Physical.exercise 
##                      "numeric"                      "numeric" 
##                          Carbs                       Proteins 
##                      "numeric"                      "numeric" 
##                           Fats                       Calories 
##                      "numeric"                      "integer" 
##                      meal_name                      meal_type 
##                    "character"                    "character" 
##                      diet_type                        sugar_g 
##                    "character"                      "numeric" 
##                      sodium_mg                 cholesterol_mg 
##                      "numeric"                      "numeric" 
##                 serving_size_g                 cooking_method 
##                      "numeric"                    "character" 
##                  prep_time_min                  cook_time_min 
##                      "numeric"                      "numeric" 
##                         rating               Name.of.Exercise 
##                      "numeric"                    "character" 
##                           Sets                           Reps 
##                      "numeric"                      "numeric" 
##                        Benefit    Burns.Calories..per.30.min. 
##                    "character"                      "numeric" 
##            Target.Muscle.Group               Equipment.Needed 
##                    "character"                    "character" 
##               Difficulty.Level                      Body.Part 
##                    "character"                    "character" 
##                 Type.of.Muscle                        Workout 
##                    "character"                    "character" 
##                       BMI_calc                cal_from_macros 
##                      "numeric"                      "numeric" 
##                      pct_carbs                 protein_per_kg 
##                      "numeric"                      "numeric" 
##                        pct_HRR                      pct_maxHR 
##                      "numeric"                      "numeric" 
##                    cal_balance                   lean_mass_kg 
##                      "numeric"                      "numeric" 
##                  expected_burn Burns.Calories..per.30.min._bc 
##                      "numeric"                    "character" 
##             Burns_Calories_Bin 
##                    "character"

Enunciat:

Elimineu els punts al final dels noms de les variables.

Resposta:

# Índexs dels noms de les variables amb punt al final
replacement_indexes <- which(grepl("\\.$", names(fin_df)))
# Mostra els noms de les variables abans d'eliminar el punt al final
names(fin_df)[replacement_indexes]
## [1] "Weight..kg."                   "Height..m."                   
## [3] "Session_Duration..hours."      "Water_Intake..liters."        
## [5] "Workout_Frequency..days.week." "Burns.Calories..per.30.min."
# Elimina el punt al final dels noms de les variables
names(fin_df)[replacement_indexes] <- gsub(
  "\\.$", "", names(fin_df)[replacement_indexes]
)
# Mostra els noms de les variables després d'eliminar el punt al final
names(fin_df)[replacement_indexes]
## [1] "Weight..kg"                   "Height..m"                   
## [3] "Session_Duration..hours"      "Water_Intake..liters"        
## [5] "Workout_Frequency..days.week" "Burns.Calories..per.30.min"

Enunciat:

Substituïu els punts dins del nom de la variable per un guió baix. Si hi ha dos punts seguits, reemplaceu-los per un únic guió baix.

Resposta:

# Índexs dels noms de les variables amb un o dos punts al mig
replacement_indexes <- which(grepl("\\.{1,2}", names(fin_df)))
# Mostra els noms de les variables abans de la substitució
names(fin_df)[replacement_indexes]
##  [1] "Weight..kg"                     "Height..m"                     
##  [3] "Session_Duration..hours"        "Water_Intake..liters"          
##  [5] "Workout_Frequency..days.week"   "Daily.meals.frequency"         
##  [7] "Physical.exercise"              "Name.of.Exercise"              
##  [9] "Burns.Calories..per.30.min"     "Target.Muscle.Group"           
## [11] "Equipment.Needed"               "Difficulty.Level"              
## [13] "Body.Part"                      "Type.of.Muscle"                
## [15] "Burns.Calories..per.30.min._bc"
# Fes la substitució
names(fin_df)[replacement_indexes] <- gsub(
  "\\.{1,2}", "_", names(fin_df)[replacement_indexes],
  perl = TRUE
)
# Mostra els noms de les variables després de la substitució
names(fin_df)[replacement_indexes]
##  [1] "Weight_kg"                     "Height_m"                     
##  [3] "Session_Duration_hours"        "Water_Intake_liters"          
##  [5] "Workout_Frequency_days_week"   "Daily_meals_frequency"        
##  [7] "Physical_exercise"             "Name_of_Exercise"             
##  [9] "Burns_Calories_per_30_min"     "Target_Muscle_Group"          
## [11] "Equipment_Needed"              "Difficulty_Level"             
## [13] "Body_Part"                     "Type_of_Muscle"               
## [15] "Burns_Calories_per_30_min__bc"

Enunciat:

Substituïu els guions baixos seguits per un únic guió baix.

Resposta:

# Índexs dels noms de les variables amb dos o més guions baixos seguits
replacement_indexes <- which(grepl("_{2,}", names(fin_df)))
# Mostra els noms de les variables abans de la substitució
names(fin_df)[replacement_indexes]
## [1] "Burns_Calories_per_30_min__bc"
# Fes la substitució
names(fin_df)[replacement_indexes] <- gsub(
  "_{2,}", "_", names(fin_df)[replacement_indexes],
  perl = TRUE
)
# Mostra els noms de les variables després de la substitució
names(fin_df)[replacement_indexes]
## [1] "Burns_Calories_per_30_min_bc"

Enunciat:

Comproveu que no hi hagi dos guions baixos seguits.

Resposta:

any(grepl("__", names(fin_df)))
## [1] FALSE

1.2 Variables Weight_kg i Height_m

Consulteu els tipus de dades de les variables Weight_kg i Height_m. Si és necessari, apliqueu les transformacions apropiades. Esbrineu possibles inconsistències en els valors de les variables. En cas que existeixin inconsistències, corregiu-les. Definiu les variables com numèriques

Nota: Si els valors de Weight_kg estan en lliures s’han de passar a kg. Si els valors de Height_m estan en peus i polzades s’han de passar a metres. Considereu els següents factors de conversió: 1 kg = 2.20 lb i 1 mt = 39.37 polzades, 12 polzades = 1 peu.

Resposta:

# Tipus de les variables Weight_kg i Height_m
sapply(fin_df[c("Weight_kg", "Height_m")], class)
##   Weight_kg    Height_m 
## "character" "character"
# Conversió de Weight_kg de lliures a kg
fin_df$Weight_kg <- ifelse(
  grepl("lb$", fin_df$Weight_kg),
  as.numeric(gsub("lb$", "", fin_df$Weight_kg)) / 2.20,
  fin_df$Weight_kg
)
# Conversió de Height_m de peus i polzades a metres
fin_df$Height_m <- ifelse(
  grepl("'", fin_df$Height_m),
  {
    feet_inches <- strsplit(gsub('"$', "", fin_df$Height_m), "'")
    sapply(feet_inches, function(x) {
      feet <- as.numeric(x[1])
      inches <- as.numeric(x[2])
      total_inches <- (feet * 12) + inches
      total_inches / 39.37
    })
  },
  fin_df$Height_m
)
# Conversió de les variables Weight_kg i Height_m a numèriques
fin_df$Weight_kg <- as.numeric(fin_df$Weight_kg)
fin_df$Height_m <- as.numeric(fin_df$Height_m)
# Tipus de les variables Weight_kg i Height_m després de la conversió
sapply(fin_df[c("Weight_kg", "Height_m")], class)
## Weight_kg  Height_m 
## "numeric" "numeric"
# Resum estadístic de les variables Weight_kg i Height_m
summary(fin_df[c("Weight_kg", "Height_m")])
##    Weight_kg         Height_m    
##  Min.   : 39.18   Min.   :1.490  
##  1st Qu.: 58.16   1st Qu.:1.620  
##  Median : 70.00   Median :1.710  
##  Mean   : 73.90   Mean   :1.723  
##  3rd Qu.: 86.10   3rd Qu.:1.800  
##  Max.   :130.77   Max.   :2.010

1.3 Valors absents i atípics

Determineu el nombre de valors absents i el nombre de valors atípics de les variables Weight_kg i Height_m.

Resposta:

# Nombre de valors absents
n_na_weight <- sum(is.na(fin_df$Weight_kg))
n_na_height <- sum(is.na(fin_df$Height_m))
kable(
  data.frame(
    Variable = c("Weight_kg", "Height_m"),
    Valors_absents = c(n_na_weight, n_na_height)
  ),
  caption = "Nombre de valors absents",
  col.names = c("Variable", "Valors absents")
) |>
  kable_styling(
    "striped",
    latex_options = c("striped", "scale_down", "repeat_header"),
    position = "center",
    full_width = FALSE
  )
Nombre de valors absents
Variable Valors absents
Weight_kg 0
Height_m 0

Per determinar els valors atípics, primer relacionem l’altura i el pes amb l’índex de massa corporal (IMC), que es calcula com el pes en quilograms dividit per l’altura en metres al quadrat.

# Càlcul de l'índex de massa corporal (IMC)
imc <- fin_df$Weight_kg / (fin_df$Height_m^2)

A través dels diagrames de caixa, visualitzem els valors atípics de l’IMC, de l’altura i del pes.

# Diagrama de caixa de l'IMC, de l'altura i del pes
par(mfrow = c(1, 3))
boxplot(
  imc,
  main = "Diagrama de caixa de l'IMC",
  ylab = "IMC"
)
boxplot(
  fin_df$Height_m,
  main = "Diagrama de caixa de l'altura",
  ylab = "Height_m (m)"
)
boxplot(
  fin_df$Weight_kg,
  main = "Diagrama de caixa del pes",
  ylab = "Weight_kg (kg)"
)

par(mfrow = c(1, 1))

A continuació, calculem el nombre de valors atípics de l’IMC, de l’altura i del pes utilitzant el criteri de l’interval interquartílic (IQR). Un valor es considera atípic si és inferior a Q1 - 1.5 * IQR o superior a Q3 + 1.5 * IQR, on Q1 i Q3 són el primer i tercer quartil, respectivament.

En el cas de l’IMC:

q1 <- quantile(imc, 0.25, na.rm = TRUE)
q3 <- quantile(imc, 0.75, na.rm = TRUE)
iqr <- q3 - q1
lower_bound_imc <- q1 - 1.5 * iqr
upper_bound_imc <- q3 + 1.5 * iqr
# Nombre de valors atípics inferiors de l'IMC
n_lower_bound_imc <- sum(imc < lower_bound_imc, na.rm = TRUE)
# Nombre de valors atípics superiors de l'IMC
n_upper_bound_imc <- sum(imc > upper_bound_imc, na.rm = TRUE)

En el cas del pes:

q1_weight <- quantile(fin_df$Weight_kg, 0.25, na.rm = TRUE)
q3_weight <- quantile(fin_df$Weight_kg, 0.75, na.rm = TRUE)
iqr_weight <- q3_weight - q1_weight
lower_bound_weight <- q1_weight - 1.5 * iqr_weight
upper_bound_weight <- q3_weight + 1.5 * iqr_weight
# Nombre de valors atípics inferiors del pes
n_lower_bound_weight <- sum(fin_df$Weight_kg < lower_bound_weight, na.rm = TRUE)
# Nombre de valors atípics superiors del pes
n_upper_bound_weight <- sum(fin_df$Weight_kg > upper_bound_weight, na.rm = TRUE)

En el cas de l’altura:

q1_height <- quantile(fin_df$Height_m, 0.25, na.rm = TRUE)
q3_height <- quantile(fin_df$Height_m, 0.75, na.rm = TRUE)
iqr_height <- q3_height - q1_height
lower_bound_height <- q1_height - 1.5 * iqr_height
upper_bound_height <- q3_height + 1.5 * iqr_height
# Nombre de valors atípics inferiors de l'altura
n_lower_bound_height <- sum(fin_df$Height_m < lower_bound_height, na.rm = TRUE)
# Nombre de valors atípics superiors de l'altura
n_upper_bound_height <- sum(fin_df$Height_m > upper_bound_height, na.rm = TRUE)

En la taula següent es mostra el nombre de valors atípics de l’IMC, de l’altura i del pes.

outliers_count <- data.frame(
  Variable = c("IMC", "Weight_kg", "Height_m"),
  lower_outliers = c(
    n_lower_bound_imc, n_lower_bound_weight, n_lower_bound_height
  ),
  upper_outliers = c(
    n_upper_bound_imc, n_upper_bound_weight, n_upper_bound_height
  )
)
kable(
  outliers_count,
  caption = "Nombre de valors atípics",
  col.names = c(
    "Variable", "Valors atípics inferiors", "Valors atípics superiors"
  )
) |>
  kable_styling(
    "striped",
    latex_options = c("striped", "scale_down", "repeat_header"),
    position = "center",
    full_width = FALSE
  )
Nombre de valors atípics
Variable Valors atípics inferiors Valors atípics superiors
IMC 0 529
Weight_kg 0 152
Height_m 0 0

2 Estadística inferencial

2.1 Contrast d’hipòtesi

Podem acceptar que els homes cremen en promig més calories als entrenaments que les dones? Responeu a la pregunta utilitzant un nivell de confiança del 97,5%.

Nota:

S’han de realitzar els càlculs per comparar mitjanes manualment. No es poden usar funcions de R que calculin directament el contrast com a t.test o similar. Si que es poden usar funcions com mean, sd, qnorm, pnorm, qt i pt.

Seguiu els passos que es detallen a continuació.

2.1.1 Escriviu la hipòtesi nul·la i l’alternativa

Resposta:

Hipòtesis nul·la (H0): \(\mu_1 = \mu_2\): La mitjana de calories cremades pels homes és igual a la mitjana de calories cremades per les dones.

Hipòtesis alternativa (H1): \(\mu_1 > \mu_2\): La mitjana de calories cremades pels homes és major que la mitjana de calories cremades per les dones.

2.1.2 Justificació del test a aplicar

Resposta:

Contrast unilateral per la dreta de dues mostres independents sobre la mitjana, amb variàncies desconegudes. Segons el teorema del límit central, podem assumir normalitat quan fem un test sobre les mitjanes amb un nombre de mostres gran.

Per veure si podem assumir igualtat de variàncies, fem la prova F d’Snedecor (contrast d’homogeneïtat de variàncies):

  • Hipòtesis nul·la (H0): \(\sigma_1^2 = \sigma_2^2\): La variància de calories cremades pels homes és igual que la variància de calories cremades per les dones.
  • Hipòtesis alternativa (H1): \(\sigma_1^2 \neq \sigma_2^2\): La variància de calories cremades pels homes és diferent a la variància de calories cremades per les dones.
alpha <- 0.025
# Subconjunts de calories cremades per homes i dones
calories_homes <- fin_df$Calories_Burned[fin_df$Gender == "Male"]
calories_dones <- fin_df$Calories_Burned[fin_df$Gender == "Female"]
# Variances de les dues mostres
mean1 <- mean(calories_homes)
mean2 <- mean(calories_dones)
# Nombre d'elements de les dues mostres
n1 <- length(calories_homes)
n2 <- length(calories_dones)
# Desviacions estàndard de les dues mostres
s1 <- sd(calories_homes)
s2 <- sd(calories_dones)
# F_observed
fobs <- s1^2 / s2^2
fcrit_l <- qf(alpha / 2, n1 - 1, n2 - 1)
fcrit_u <- qf(1 - alpha / 2, n1 - 1, n2 - 1)
# p-valor
pvalue <- min(
  pf(fobs, df1 = n1 - 1, df2 = n2 - 2, lower.tail = FALSE),
  pf(fobs, df1 = n1 - 1, df2 = n2 - 2)
) * 2
# Resultats de la prova F d'Snedecor
c(fobs, fcrit_l, fcrit_u, pvalue)
## [1] 1.05041507 0.95615544 1.04585231 0.01393386

El valor de p és 0.0139, que és menor de 0.025, per tant rebutgem la hipòtesi nul·la i assumim que les variàncies són diferents. Caldrà fer el test amb variàncies diferents (t-test de Welch).

2.1.3 Càlculs

Realitzeu els càlculs de l’estadístic de contrast, valor crític i p valor a un nivell de confiança del 97,5%.

Resposta:

# Estadístic de contrast
tobs <- (mean1 - mean2) / sqrt((s1^2 / n1) + (s2^2 / n2))
# Graus de llibertat aproximats
df <- ((s1^2 / n1) + (s2^2 / n2))^2 /
  (((s1^2 / n1)^2) / (n1 - 1) + ((s2^2 / n2)^2) / (n2 - 1))
# Valor crític
tcrit <- qt(1 - alpha, df)
# p-valor del test unilateral per la dreta
calories_burned_pt <- pt(tobs, df = df, lower.tail = FALSE)
# Resultats del test
c(tobs, tcrit, calories_burned_pt)
## [1] 0.1481908 1.9600827 0.4410968

Off topic:

Comprovació amb les funcions d’R:

# test d'homoscedasticitat
var_test <- var.test(
  calories_homes, calories_dones,
  alternative = "two.sided",
  conf.level = 0.975
)
c(var_test$statistic, var_test$p.value)
##          F            
## 1.05041507 0.01393143
if (var_test$p.value < 0.025) {
  var_equal <- FALSE # Les variàncies no són iguals, es fa el test de Welch
} else {
  var_equal <- TRUE # Les variàncies són iguals,
}
# Comprovació amb t.test
t_test_result <- t.test(
  calories_homes, calories_dones,
  conf.level = 0.975,
  alternative = "greater",
  var.equal = var_equal
)
c(t_test_result$statistic, t_test_result$p.value)
##         t           
## 0.1481908 0.4410968

2.1.4 Interpretació del test

Resposta:

El valor de p és 0.4411, que és un valor més gran de 0.025, per tant no rebutgem la hipòtesi nul·la. És a dir, no hi ha prou evidència per acceptar que els homes cremen més calories que les dones als entrenaments.

3 Model de regressió

3.1 Regressió lineal múltiple

Volem investigar quines variables expliquen el valor de les calories cremades (Calories_Burned). Estimeu un model de regressió lineal múltiple que tingui com a variables explicatives: Session_Duration_hours, Experience_Level, Workout_Frequency_days_week, Height_m, Weight_m, Gender i Workout_Type.

Interpreteu el model lineal ajustat. Com és la qualitat de l’ajust? Interpreteu breument la contribució de la variable Experience_Level sobre la variable depenent.

Resposta:

# Càlcul del model de regressió lineal múltiple
model <- lm(
  Calories_Burned ~ Session_Duration_hours + Experience_Level +
    Workout_Frequency_days_week + Height_m + Weight_kg + Gender +
    Workout_Type,
  data = fin_df
)
# Resum del model
summary(model)
## 
## Call:
## lm(formula = Calories_Burned ~ Session_Duration_hours + Experience_Level + 
##     Workout_Frequency_days_week + Height_m + Weight_kg + Gender + 
##     Workout_Type, data = fin_df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -272.46  -49.96   -9.88   43.31  372.91 
## 
## Coefficients:
##                               Estimate Std. Error  t value Pr(>|t|)    
## (Intercept)                 -365.97518    9.80638  -37.320   <2e-16 ***
## Session_Duration_hours      1052.84626    2.79080  377.256   <2e-16 ***
## Experience_Level              59.07094    1.46821   40.233   <2e-16 ***
## Workout_Frequency_days_week   37.05314    1.10226   33.616   <2e-16 ***
## Height_m                      14.47045    5.70921    2.535   0.0113 *  
## Weight_kg                      0.03321    0.03427    0.969   0.3325    
## GenderMale                     0.67295    1.35676    0.496   0.6199    
## Workout_TypeHIIT             451.90977    1.92862  234.318   <2e-16 ***
## Workout_TypeStrength         151.98634    1.91970   79.172   <2e-16 ***
## Workout_TypeYoga            -297.30110    1.92313 -154.592   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 95.92 on 19990 degrees of freedom
## Multiple R-squared:  0.9635, Adjusted R-squared:  0.9635 
## F-statistic: 5.87e+04 on 9 and 19990 DF,  p-value: < 2.2e-16

Gairebé tote les variables tenen un efecte significatiu en la variable dependent (p-value < 0.05), excepte GenderMale i Weight_kg.

El valor de R2 ajustat és 0.9635, un valor molt elevat, indica que el model explica un percentatge molt alt de la variabilitat de les calories cremades (96.35 %).

La variable predictora Experience_Level té un efecte significatiu en la variable dependent (p-value < 0.05). En concret, te un efecte positiu, és a dir, a mesura que augmenta el nivell d’experiència, augmenten les calories cremades durant l’entrenament (59.07 calories cremades per cada nivell d’experiència).

3.2 Multicol·linealitat

Analitzeu possibles problemes de multicol·linealitat (alta correlació entre variables explicatives) mitjançant la interpretació de la matriu de correlacions de les variables explicatives quantitatives i del factor d’inflació de la variància (vif). Es pot utilitzar la funció vif de la llibreria car.

Resposta:

# Matriu de correlacions de les variables explicatives quantitatives
cor_matrix <- cor(
  fin_df[c(
    "Session_Duration_hours", "Workout_Frequency_days_week",
    "Height_m", "Weight_kg"
  )],
  use = "complete.obs"
)
cor_matrix
##                             Session_Duration_hours Workout_Frequency_days_week
## Session_Duration_hours                 1.000000000                 0.637626139
## Workout_Frequency_days_week            0.637626139                 1.000000000
## Height_m                               0.006781343                 0.007252810
## Weight_kg                             -0.002275379                -0.003893683
##                                Height_m    Weight_kg
## Session_Duration_hours      0.006781343 -0.002275379
## Workout_Frequency_days_week 0.007252810 -0.003893683
## Height_m                    1.000000000  0.353758800
## Weight_kg                   0.353758800  1.000000000
# Gràfica de la matriu de correlacions
corrplot(cor_matrix,
  method = "circle",
  diag = FALSE,
  type = "upper",
  tl.srt = 45,
  tl.col = "black"
)

En la gràfica de la matriu de correlacions, podem observar que no hi ha cap parella de variables explicatives quantitatives amb una correlació molt alta (per exemple, superior a 0.8 o inferior a -0.8), de fet només es mostren dues correlacions directes moderades: entre Session_Duration_hours i Workout_Frequency_days_week (0.64) i entre Height_m i Weight_kg (0.35). Per tant, no sembla haver-hi problemes greus de multicol·linealitat entre les variables explicatives quantitatives.

# Càlcul del factor d'inflació de la variància (VIF)
vif(model)
##                                 GVIF Df GVIF^(1/(2*Df))
## Session_Duration_hours      1.972570  1        1.404482
## Experience_Level            2.282941  1        1.510941
## Workout_Frequency_days_week 2.192816  1        1.480816
## Height_m                    1.143372  1        1.069286
## Weight_kg                   1.144245  1        1.069694
## Gender                      1.000395  1        1.000197
## Workout_Type                1.001246  3        1.000208

En quant al factor d’inflació de la variància (VIF), si en fixem en l’última columna tots els valors són inferiors a 5 (potencialment problemàtic) i propers a 1 (absència de col·linealitat). Això indica que no hi ha problemes de multicol·linealitat entre les variables.

3.3 Anàlisi visual dels residus

Analitzeu gràficament els residus del model per comprovar la linealitat, l’homoscedasticitat, la normalitat i la presència d’outliers. A quina conclusió arribeu?

Resposta:

# Gràfics de diagnòstic del model
par(mfrow = c(1, 2))
plot(model, which = 1, main = "Model Fit")
plot(model, which = 2, main = "Q-Q Plot")

par(mfrow = c(1, 1))

La gràfica de “Residuals vs Fitted” mostra una clara desviació respecte a la línia horitzontal, especialment als extrems, on la corba vermella indica una tendència no lineal. Aquest comportament suggereix que la relació entre les variables explicatives i la variable resposta no és estrictament lineal. En quant a la homoscedasticitat, la mateixa gràfica mostra un patró en forma d’embut, on la variabilitat augmenta amb els valors ajustats. Aquest patró és típic d’heteroscedasticitat, és a dir, la variància dels errors no és constant.

En la gràfica “Q-Q Residuals”, al centre se segueix la diagonal, mentre que a les cues se separen una mica, sobretot a la dreta. Aquesta desviació indica que els residus no segueixen una distribució normal perfecta, especialment en els extrems.

La presència d’outliers es pot observar en les dues gràfiques. En la primera, hi ha punts que es troben lluny de la línia horitzontal, i en la segona, hi ha punts que es desvien significativament de la línia diagonal.

En conclusió, els gràfics de diagnòstic indiquen que el model de regressió lineal múltiple presenta problemes de no linealitat, heteroscedasticitat, desviació de la normalitat i presència d’outliers.

3.4 Regressió logística

Ajusteu un model predictiu basat en la regressió logística per predir la probabilitat de ser una persona sense experiència en fitness.

A partir de la variable Experience_Level, classifiqueu les persones sense experiència (valor 1) en comparació a la resta (valor 2 o 3). Com a regressors considereu les mateixes variables que en apartat anterior. Nota: Calories_Burned ara és una variable explicativa del model de regressió.

Mostreu el resultat del model i interpreteu-lo en termes de: quines són les variables significatives i com és la qualitat del model.

Resposta:

Primer creem la variable binària Without_Experience, que val 1 si la persona no té experiència (Experience_Level = 1) i 0 altrament.

# Crear la variable binària
fin_df$Without_Experience <- ifelse(fin_df$Experience_Level == 1, 1, 0)

Després separem el conjunt de dades en un conjunt d’entrenament (70%) i un de prova (30%).

# Fixem el valor de la llavor per a la reproductibilitat
set.seed(42)
# Separació del conjunt de dades en train (70%) i test (30%) de forma aleatòria
train_indexes <- sample(1:nrow(fin_df), size = 0.7 * nrow(fin_df))
train_dataset <- fin_df[train_indexes, ]
test_dataset <- fin_df[-train_indexes, ]

A continuació, ajustem el model de regressió logística.

# Model de regressió logística
logistic_model <- glm(
  Without_Experience ~ Session_Duration_hours + Workout_Frequency_days_week +
    Height_m + Weight_kg + Gender + Workout_Type + Calories_Burned,
  data = train_dataset,
  family = binomial(link = "logit")
)
# Resum del model
summary(logistic_model)
## 
## Call:
## glm(formula = Without_Experience ~ Session_Duration_hours + Workout_Frequency_days_week + 
##     Height_m + Weight_kg + Gender + Workout_Type + Calories_Burned, 
##     family = binomial(link = "logit"), data = train_dataset)
## 
## Coefficients:
##                               Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                  8.1491979  0.3982147  20.464  < 2e-16 ***
## Session_Duration_hours      11.1644562  0.4630786  24.109  < 2e-16 ***
## Workout_Frequency_days_week -1.3038111  0.0429654 -30.346  < 2e-16 ***
## Height_m                     0.0055454  0.2105665   0.026 0.978990    
## Weight_kg                   -0.0040391  0.0011675  -3.459 0.000541 ***
## GenderMale                  -0.0247900  0.0498334  -0.497 0.618867    
## Workout_TypeHIIT             6.3337820  0.2306999  27.455  < 2e-16 ***
## Workout_TypeStrength         2.1101334  0.1020544  20.677  < 2e-16 ***
## Workout_TypeYoga            -4.1281999  0.1543039 -26.754  < 2e-16 ***
## Calories_Burned             -0.0146002  0.0004959 -29.442  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 19314.9  on 13999  degrees of freedom
## Residual deviance:  9979.7  on 13990  degrees of freedom
## AIC: 9999.7
## 
## Number of Fisher Scoring iterations: 6

Les variables significatives en el model de regressió logística són aquelles amb un valor de p menor a 0.05.

# Variables significatives (p < 0.05)
significant_vars <- summary(logistic_model)$coefficients[, "Pr(>|z|)"] < 0.05
# Elimina l'intercept
significant_vars <- significant_vars[names(significant_vars) != "(Intercept)"]
# Noms de les variables significatives
names(significant_vars)
## [1] "Session_Duration_hours"      "Workout_Frequency_days_week"
## [3] "Height_m"                    "Weight_kg"                  
## [5] "GenderMale"                  "Workout_TypeHIIT"           
## [7] "Workout_TypeStrength"        "Workout_TypeYoga"           
## [9] "Calories_Burned"

Per avaluar la qualitat del model, podem utilitzar la corba ROC i l’àrea sota la corba (AUC). Un AUC proper a 1 indica un bon model, mentre que un AUC proper a 0.5 indica un model poc informatiu (entre 0,7 i 0,8 es considera acceptable, entre 0,8 i 0,9 és excel·lent, i superior a 0,9 és excepcional).

# Prediccions de probabilitats sobre el conjunt de test
prob_predictions <- predict(
  logistic_model,
  newdata = test_dataset,
  type = "response"
)
# Corba ROC
roc_curve <- roc(test_dataset$Without_Experience, prob_predictions)
# Plot de la corba ROC i valor AUC
plot(roc_curve, print.auc = TRUE, main = "ROC Curve", legacy.axes = TRUE)
abline(a = 0, b = 1, lty = 2, col = "grey")

# AUC
auc_value <- auc(roc_curve)

És excepcional perquè té un AUC de 0.919. Això indica que el model té una bona capacitat de discriminació: distingeix força bé entre persones amb i sense experiència. En termes pràctics, quan el model compara dues persones a l’atzar (una amb experiència i l’altra sense), hi ha una alta probabilitat que assigni una probabilitat més alta de ser sense experiència a la persona que realment no té experiència.

3.5 Matriu de confusió

A continuació analitzeu la precisió del model, comparant la predicció del model sobre les mateixes dades del conjunt de dades. Assumirem que la predicció del model és 1 (Sense experiència) si la probabilitat del model de regressió logística és superior o igual a 0.5 i 0 en cas contrari. Calculeu la matriu de confusió.

Interpreteu els resultats. Indiqueu els valors de sensibilitat i especificitat i interpreteu-los. Es pot utilitzar funció confusionMatrix de la llibreria Caret.

Resposta:

# Convertir les probabilitats a classes amb un llindar de 0.5
class_predictions <- ifelse(prob_predictions > 0.5, "Alt", "No Alt")
class_predictions <- factor(class_predictions, levels = c("No Alt", "Alt"))
# Convertir la referència a factor amb els mateixos nivells
reference_factor <- factor(
  ifelse(test_dataset$Without_Experience == 1, "Alt", "No Alt"),
  levels = c("No Alt", "Alt")
)
# Matriu de confusió
confusion_matrix <- confusionMatrix(
  data = class_predictions,
  reference = reference_factor,
  positive = "Alt"
)
confusion_matrix
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction No Alt  Alt
##     No Alt   2145  568
##     Alt       570 2717
##                                           
##                Accuracy : 0.8103          
##                  95% CI : (0.8002, 0.8202)
##     No Information Rate : 0.5475          
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.6172          
##                                           
##  Mcnemar's Test P-Value : 0.9764          
##                                           
##             Sensitivity : 0.8271          
##             Specificity : 0.7901          
##          Pos Pred Value : 0.8266          
##          Neg Pred Value : 0.7906          
##              Prevalence : 0.5475          
##          Detection Rate : 0.4528          
##    Detection Prevalence : 0.5478          
##       Balanced Accuracy : 0.8086          
##                                           
##        'Positive' Class : Alt             
## 

La precisió del model és del 0.8103, que indica que el model classifica correctament el 81.03 % de les persones en el conjunt de dades de prova. El valor de la sensibilitat és 0.8271, que indica la capacitat del model per identificar correctament les persones sense experiència. En aquest cas, el model identifica correctament el 82.71 % de les persones sense experiència. El valor de l’especificitat és 0.7901, que indica la capacitat del model per identificar correctament les persones amb experiència. En aquest cas, el model identifica correctament el 79.01 % de les persones amb experiència.

En conjunt, el model presenta un rendiment equilibrat i raonable per a una classificació binària amb un punt de tall del 50 %, ja que tant la sensibilitat com l’especificitat són altes, una mica més alta la sensibilitat, la qual cosa és desitjable en aquest context si es vol identificar correctament les persones sense experiència.

4 Anàlisi de la variància (ANOVA) d’un factor

En aquest apartat analitzarem si existeixen diferències significatives en la variable Calories_Burned en funció del tipus d’entrenament (Workout_Type).

4.1 Visualització

Visualitzar les dades per tipus d’entrenament amb un boxplot.

Resposta:

# Boxplot de Calories_Burned per Workout_Type
ggplot(fin_df, aes(x = Workout_Type, y = Calories_Burned)) +
  geom_boxplot(fill = "lightblue", color = "darkblue") +
  labs(
    title = "Boxplot de Calories_Burned per Workout_Type",
    x = "Tipus d'entrenament",
    y = "Calories Cremades"
  ) +
  theme_minimal()

En els diagrames de caixa es pot observar que hi ha diferències en la distribució de les calories cremades segons el tipus d’entrenament. Per exemple, l’entrenament de tipus HIIT sembla tenir una mediana més alta de calories cremades en comparació amb altres tipus d’entrenament com Yoga, Cardio i Strength. A més, hi ha una variabilitat diferent en les calories cremades entre els diferents tipus d’entrenament, amb alguns tipus mostrant una distribució més ampla que altres. HIIT té una variabilitat més gran en les calories cremades, mentre que Yoga sembla tenir una variabilitat més petita.

4.2 Hipòtesi nul·la i alternativa

Escriviu la hipòtesi nul·la i l’alternativa.

Resposta:

  • Hipòtesi nul·la (H0): No hi ha diferència entre les calories cremades i tipus d’entrenament que es fa.
  • Hipòtesi alternativa (H1): Almenys dos grups són diferents en les calories cremades segons el tipus d’entrenament.

4.3 Model

Calculeu l’anàlisi de variància, fent servir la funció aov o lm. Interpreteu el resultat de l’anàlisi, tenint en compte els valors: Sum Sq, Mean Sq, F i Pr(> F).

Resposta:

# Càlcul de l'ANOVA d'un factor
anova_model <- aov(Calories_Burned ~ Workout_Type, data = fin_df)
# Resum de l'ANOVA
summary(anova_model)
##                 Df    Sum Sq   Mean Sq F value Pr(>F)    
## Workout_Type     3 1.485e+09 494905823    2780 <2e-16 ***
## Residuals    19996 3.560e+09    178021                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

La suma de quadrats entre grups (Sum Sq) indica variabilitat explicada per les diferències entre grups (Sum Sq del factor), i la variabilitat no explicada: la variabilitat interna dins dels grups (Sum Sq residual). Com més gran sigui Sum Sq del factor en relació amb la total, més probable és que hi hagi diferències reals entre grups. En aquest cas, la Sum Sq del factor és 1.484.717.469,03, mentre que la Sum Sq residual és 3.559.709.305,57. Això indica que una part significativa de la variabilitat total en les calories cremades es pot atribuir a les diferències entre els tipus d’entrenament.

Mean Sq és la mitjana de les sumes de quadrats, que es calcula \(MS=\frac{Sum Sq}{df}\), on \(df\) són els graus de llibertat associats a cada component. En aquest cas, el Mean Sq del factor \((MS_{Between})\) és 494.905.823,01, mentre que la Mean Sq residual \((MS_{Within})\) és 178.021,07.

El valor de l’estadístic \(F=\frac{MS_{Between}}{MS_{Within}}\) és 2.780,04., com que aquest valor és gran, indica que hi ha una gran variabilitat entre els grups en comparació amb la variabilitat dins dels grups, altrament seria gairebé igual a 1.

El valor de p associat a l’estadístic F és \(<2e-16\), menor que 0.05, per tant rebutgem la hipòtesi nul·la i acceptem l’alternativa. Això indica que hi ha diferències significatives en les calories cremades segons el tipus d’entrenament.

4.4 Efectes dels nivells del factor

Proporcioneu l’estimació de l’efecte dels nivells del factor Workout_Type.

Resposta:

En el model ANOVA el valor p és petit (< 0.05), això indica necessitem el model complet amb els efectes dels nivells del factor per explicar les diferències en les calories cremades segons el tipus d’entrenament.

# Estimació dels efectes dels nivells del factor Workout_Type
effects <- model.tables(anova_model, "means")$tables$Workout_Type

# Mitjana global
mitjana_global <- mean(fin_df$Calories_Burned, na.rm = TRUE)
mitjana_global
## [1] 1280.11
# Diferència entre la mitjana de cada grup i la mitjana global
efectes_df <- data.frame(
  "Mitjana del grup" = as.numeric(effects),
  "Diferència respecte mitjana global" = as.numeric(effects) - mitjana_global,
  row.names = names(effects)
)
efectes_df
##          Mitjana.del.grup Diferència.respecte.mitjana.global
## Cardio          1211.5447                          -68.56492
## HIIT            1652.5332                          372.42361
## Strength        1361.4305                           81.32086
## Yoga             897.1072                         -383.00238

4.5 Interpretació dels resultats

Interpreteu els resultats obtinguts en els apartats anteriors.

Resposta:

L’anàlisi de variància (ANOVA) indica que hi ha diferències significatives en les calories cremades segons el tipus d’entrenament realitzat. El valor de p és menor que 0.05, la qual cosa ens porta a rebutjar la hipòtesi nul·la i acceptar que almenys dos tipus d’entrenament són diferents en termes de calories cremades.

Els efectes estimats dels nivells del factor Workout_Type mostren com cada tipus d’entrenament afecta les calories cremades en comparació amb la mitjana global. Per exemple, l’entrenament de tipus HIIT té un efecte positiu més elevat (1.652,53), indicant que aquest tipus d’entrenament està associat amb un augment significatiu en les calories cremades en comparació amb altres tipus d’entrenament.

4.6 Adequació del model

Mostreu visualment l’adequació del model ANOVA. Verificar els supòsits de normalitat i homoscedasticitat. Podeu fer servir plot sobre el model ANOVA calculat.

En cas de trobar diferències a les mitjanes, cal fer anàlisis post hoc on es fan les comparacions múltiples de tots els parells de mitjanes possibles. Si tinguéssim homogeneïtat de variàncies, prova de Scheffé si les variàncies no són iguals optar per la prova T2 de Tamhane.

Resposta:

# Gràfics de diagnòstic del model ANOVA
par(mfrow = c(1, 2))
plot(anova_model, which = 1, main = "Model Fit")
plot(anova_model, which = 2, main = "Q-Q Plot")

par(mfrow = c(1, 1))

En l’apartat anterior hem vist que hi ha diferències significatives en les calories cremades segons el tipus d’entrenament. Ara, per determinar quins tipus d’entrenament són diferents entre si, abans de realitzar les proves post hoc, hem de verificar els supòsits de normalitat i homoscedasticitat. Això s’analitzarà en els següents subapartats.

4.6.1 Normalitat dels residus

Interpreteu la normalitat dels residus a partir del gràfic Normal Q-Q que heu mostrat a l’apartat anterior i verifica amb una prova de contrast (Anderson-Darling). Tot i això, recordem que l’ANOVA és una prova robusta davant la violació del supòsit de normalitat si tenim n ≥ 30 gràcies al Teorema del Límit Central.

Resposta:

# Residus del model ANOVA
res <- residuals(anova_model)
# Prova d'Anderson-Darling per normalitat dels residus
ad_test <- ad.test(res)
ad_test
## 
##  Anderson-Darling normality test
## 
## data:  res
## A = 199.49, p-value < 2.2e-16

El valor p de la prova d’Anderson-Darling és \(< 2.2e-16\), que és menor que 0.05, per tant rebutgem la hipòtesi nul·la i assumim que els residus no segueixen una distribució normal. A més, el valor de l’estadístic d’Anderson-Darling és 199,49, el qual és relativament alt, suggerint una desviació significativa de la normalitat. Aquesta conclusió és coherent amb el gràfic Q-Q, on es pot observar una desviació notable dels punts respecte a la línia diagonal, especialment en les cues de la distribució. Tot i això, com que tenim un nombre d’observacions gran (n > 30), l’ANOVA és robusta davant la violació del supòsit de normalitat gràcies al Teorema del Límit Central.

4.6.2 Homocedasticitat dels residus

El gràfic “Residuals vs Fitted” proporciona informació sobre la homocedasticitat dels residus.

Mostreu, interpreteu aquest gràfic i verifiqueu amb una prova de contrast. Si no es compleix homocedasticitat, recorda que es recomana una ANOVA de Welch. L’ANOVA de Welch no assumeix la igualtat de variàncies i utilitza una correcció en els graus de llibertat per calcular el valor F i el valor p. Confirma amb la prova de contrast d’igualtat de variàncies de Levene.

Resposta:

El gràfic “Residuals vs Fitted”, el valor ajustat d’una observació és, en l’ANOVA d’un factor, la mitjana del grup al qual correspon l’observació. Per tant, per a totes les observacions que corresponen al nivell i, el valor ajustat és la mitjana del grup i. En aquest tipus de gràfic de residus apareixeran tires verticals de punts, una tira per cada nivell. Si la variància és constant, l’extensió vertical de les tires serà aproximadament la mateixa. Si la variància no és constant, apareixerà un patró en la dispersió vertical dels residus. És a dir, els nivells de tractament mostraran una disposició dels residus amb diferent dispersió vertical.

En aquest cas, el gràfic mostra clarament que les tires de punts tenen diferents extensions verticals, indicant que la variància no és constant entre els diferents tipus d’entrenament. Aquesta observació suggereix que el supòsit d’homoscedasticitat no es compleix, ja que la línia vermella no és horitzontal.

# Prova d'homogeneïtat de variàncies mitjançant el test de Bartlett
bartlett_test <- bartlett.test(
  Calories_Burned ~ Workout_Type,
  data = fin_df
)
bartlett_test
## 
##  Bartlett test of homogeneity of variances
## 
## data:  Calories_Burned by Workout_Type
## Bartlett's K-squared = 1857.5, df = 3, p-value < 2.2e-16

El valor de p de la prova de Bartlett és 0, que és menor que 0.05, per tant rebutgem la hipòtesi nul·la i assumim que les variàncies no són iguals. Aquesta conclusió és coherent amb l’observació feta en el gràfic “Residuals vs Fitted”.

Per confirmar aquesta observació, realitzem la prova de Levene.

levene_test <- leveneTest(
  Calories_Burned ~ Workout_Type,
  data = fin_df
)
levene_test
## Levene's Test for Homogeneity of Variance (center = median)
##          Df F value    Pr(>F)    
## group     3  407.77 < 2.2e-16 ***
##       19996                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Df és el nombre de grups menys 1 per al factor i el nombre total d’observacions menys el nombre de grups per als residus. El valor de p és \(< 2.2e-16\), que és menor que 0.05, per tant rebutgem la hipòtesi nul·la i assumim que les variàncies no són iguals. Per tant, realitzem la prova T2 de Tamhane per a les comparacions múltiples.

F és l’estadístic de la prova de Levene, que mesura la variabilitat entre els grups en comparació amb la variabilitat dins dels grups. Un valor alt de F indica que hi ha diferències significatives en les variàncies entre els grups, mentre que un valor proper a 1 indica que les variàncies són similars. En aquest cas, el valor de F és 407,77, el qual és relativament alt, suggerint que hi ha diferències significatives en les variàncies entre els diferents tipus d’entrenament.

# Prova post hoc T2 de Tamhane
post_hoc_tamhane <- pairwise.t.test(
  fin_df$Calories_Burned,
  fin_df$Workout_Type,
  p.adjust.method = "none",
  pool.sd = FALSE # variàncies no iguals
)
post_hoc_tamhane
## 
##  Pairwise comparisons using t tests with non-pooled SD 
## 
## data:  fin_df$Calories_Burned and fin_df$Workout_Type 
## 
##          Cardio HIIT   Strength
## HIIT     <2e-16 -      -       
## Strength <2e-16 <2e-16 -       
## Yoga     <2e-16 <2e-16 <2e-16  
## 
## P value adjustment method: none

Tots els valors de p són menors que 0.05, per tant hi ha diferències significatives entre tots els parells de tipus d’entrenament en termes de calories cremades.

5 ANOVA multifactorial

Ara analitzarem si les calories cremades depenen del tipus d’entrenament (Workout_Type), de tenir un índex de massa corporal saludable i si existeix interacció entre aquests dos factors.

En primer lloc es crearà una variable binària anomenada BMI_bin que indiqui un índex de massa corporal alt si és major a 25 i normal/baix si és igual o menor a 25.

També analitzarem si hi ha interacció entre aquests dos factors. Si no hi ha interacció entre els factors, cal crear un model sense interacció.

Seguiu els passos que s’indiquen a continuació.

5.1 Crea la variable BIM per a majors de 25 igual a Alt

Resposta:

# Crear la variable binària BMI_bin
fin_df$BMI_bin <- ifelse(fin_df$BMI > 25, "Alt", "Normal/Baix")
fin_df$BMI_bin <- factor(fin_df$BMI_bin, levels = c("Normal/Baix", "Alt"))
# Diagrama de violí del BMI segons BMI_bin
ggplot(fin_df, aes(x = BMI_bin, y = BMI, fill = BMI_bin)) +
  geom_violin(trim = FALSE) +
  geom_boxplot(width = 0.1, position = position_dodge(0.9)) +
  labs(
    title = "Diagrama de violí del BMI segons el tipus BMI_bin",
    x = "Categoria de BMI",
    y = "Índex de Massa Corporal (BMI)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

5.2 Anàlisi visual dels efectes principals i possibles interaccions

Dibuixeu un gràfic que permeti avaluar si hi ha interacció entre els dos factors. Feu un gràfic que mostri les calories mitjanes cremades segons tipus d’entrenament diferenciant entre aquelles persones amb un índex de massa corporal alt i les que tenen un índex de massa corporal normal o baix.

Resposta:

En l’eix X apareixen els diferents tipus d’entrenament, mentre que l’eix Y mostra les calories cremades mitjanes per cada combinació de tipus d’entrenament i categoria de BMI (Índex de Massa Corporal). No s’aprecia cap intersecció clara entre les línies, i més o menys tenen les mateixes pendents, la qual cosa suggeriria que no hi ha interacció entre els dos factors.

# Gràfic d'interacció entre Workout_Type i BMI_bin
interaction.plot(
  x.factor = fin_df$Workout_Type,
  trace.factor = fin_df$BMI_bin,
  response = fin_df$Calories_Burned,
  fun = mean,
  type = "b",
  grid = TRUE,
  col.grid = "lightgray",
  col = c("blue", "red"),
  bg = "transparent",
  pch = c(19, 17),
  xlab = "Tipus d'entrenament",
  ylab = "Calories cremades mitjanes",
  legend = TRUE,
  main = "Gràfic d'interacció entre Workout_Type i BMI_bin"
)

Si canviem l’ordre dels factors, tampoc es pot observar cap intersecció clara entre les línies, les línies són més o menys paral·leles. Això reforça la idea que no hi ha interacció significativa entre els dos factors.

interaction.plot(
  x.factor = fin_df$BMI_bin,
  trace.factor = fin_df$Workout_Type,
  response = fin_df$Calories_Burned,
  fun = mean,
  type = "b",
  grid = TRUE,
  col.grid = "lightgray",
  col = c("blue", "red", "darkgreen", "purple"),
  bg = "transparent",
  pch = c(19, 17, 15, 18),
  xlab = "Tipus d'índex de massa corporal",
  ylab = "Calories cremades mitjanes",
  legend = TRUE,
  main = "Gràfic d'interacció entre Workout_Type i BMI_bin"
)

5.3 Hipòtesi nul·la i alternativa

Escriviu les hipòtesis.

Resposta:

En no haver-hi interacció entre els factors, s’escriuen les hipòtesis dels efectes principals de cada factor:

  1. Tipus d’entrenament (Workout_Type):
  • Hipòtesi nul·la (H0A): No hi ha diferències en la mitjana de calories cremades segons el tipus d’entrenament.
  • Hipòtesi alternativa (H1A): En almenys dos grups la mitjana de calories cremades són diferents segons el tipus d’entrenament.
  1. Categoria de BMI (BMI_bin):
  • Hipòtesi nul·la (H0B): La mitjana de calories cremades són iguals per al grup “Alt” i “Normal/Baix”.
  • Hipòtesi alternativa (H1B): La mitjana de calories cremades són diferents per al grup “Alt” i “Normal/Baix”.

5.4 Càlcul del model

Resposta:

# Càlcul de l'ANOVA multifactorial sense interacció
anova_multifactorial <- aov(
  Calories_Burned ~ Workout_Type + BMI_bin,
  data = fin_df
)
# Resum de l'ANOVA multifactorial
summary(anova_multifactorial)
##                 Df    Sum Sq   Mean Sq F value Pr(>F)    
## Workout_Type     3 1.485e+09 494905823  2780.3 <2e-16 ***
## BMI_bin          1 5.695e+05    569544     3.2 0.0737 .  
## Residuals    19995 3.559e+09    178001                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

5.5 Adequació del model

Comproveu els supòsits gràficament i amb les proves estadístiques de l’apartat anterior.

Resposta:

# Gràfics de diagnòstic del model ANOVA multifactorial
par(mfrow = c(1, 2))
plot(anova_multifactorial, which = 1, main = "Model Fit")
plot(anova_multifactorial, which = 2, main = "Q-Q Plot")

par(mfrow = c(1, 1))

Els gràfics són molt similars als gràfics de l’ANOVA d’un factor, ja que el factor tipus d’index de massa corporal no és significatiu, valor p > 0.05.

5.6 Interpretació dels resultats

El resultat de l’ANOVA amb dos factors i el resultat de l’ANOVA amb un factor, és el mateix quan s’afegeix un factor a l’ANOVA d’un factor, si aquest no és significatiu i no hi ha interacció entre els factors a la fórmula de l’ANOVA.

6 Conclusions

Resum de les conclusions dels diferents apartats de l’activitat.
Apartat Estadístic Resultat
Contrast d’hipòtesi p-valor Amb variances desconegudes i diferents, apliquem el test de Welch: p = 0.441 (p > 0.025), no hi ha prou evidència per acceptar que els homes cremen més calories que les dones als entrenaments amb un nivell de conviança del 97.25%.
Regressió lineal múltiple R² ajustat, valor p dels coeficients, correlació, VIF, normalitat i homoscedasticitat El valor d’R² és molt alt (96.35%) i explica gairebé tota la variabilitat de Calories_Burned, les variables significatives són (p < 0.05): Session_Duration_hours, Experience_Level, Workout_Frequency_days_week, Workout_Type i Height_m. No hi ha problemes de multicol·linealitat entre les variables explicatives quantitatives (vif < 5, matriu de correlació < 0.8). Els residus no són normals i hi ha heteroscedasticitat, no obstant això, la inferència pot ser robusta gràcies al nombre elevat de mostres, segons el teorema del límit central.
Regressió logística AUC, Estimacions dels coeficients, valor p dels coeficients, matriu de confusió, sensibilitat i especificitat, normalitat i homoscedasticitat L’AUC és excepcional (AUC > 0.9), indicant una bona capacitat de discriminació del model. Les variables significatives (p < 0.05) són: Session_Duration_hours, Workout_Frequency_days_week, Weight_kg, Workout_Type i Calories_Burned. La matriu de confusió mostra una precisió alta, amb sensibilitat i especificitat també altes. Els residus no són normals i hi ha heteroscedasticitat, no obstant això, la inferència pot ser robusta gràcies al nombre elevat de mostres, segons el teorema del límit central.
ANOVA d’un factor F value, Sum Sq, Mean Sq, valor p, efectes dels nivells del factor, normalitat i homoscedasticitat Hi ha diferències significatives en les calories cremades segons el tipus d’entrenament (p < 0.05). Els efectes dels nivells del factor mostren com cada tipus d’entrenament afecta les calories cremades. Els residus no són normals i hi ha heteroscedasticitat, no obstant això, la inferència pot ser robusta gràcies al nombre elevat de mostres, segons el teorema del límit central.
ANOVA multifactorial Interacció entre factors, F value, Sum Sq, Mean Sq, valor p, normalitat i homoscedasticitat No hi ha interacció significativa entre els factors. Hi ha diferències significatives en les calories cremades segons el tipus d’entrenament (p < 0.05), però no segons la categoria de BMI (p > 0.05). Els residus no són normals i hi ha heteroscedasticitat, no obstant això, la inferència pot ser robusta gràcies al nombre elevat de mostres, segons el teorema del límit central.