Czynniki wpływające na wynik egzaminu

#title:"Smieszna nazwa projektu"
#author: "Beniamin Gralak i Jakub Gużewski"
#date: "2025-01-19"
#output: html_document

PROBLEM

Celem naszego projektu jest przeprowadzenie szczegółowej analizy wpływu różnych czynników na wyniki egzaminacyjne uczniów. Badanie opiera się na danych obejmujących szereg zmiennych, które mogą mieć istotne znaczenie dla osiąganych rezultatów. W szczególności skupiamy się na analizie zależności między wynikami egzaminów a takimi czynnikami jak liczba godzin snu, czas poświęcony na naukę, płeć ucznia oraz odległość z domu do szkoły itp.

1. Wczytywanie danych i bibliotek

Wczytujemy dane z zewnętrznego źródła oraz potrzebne biblioteki do analizy i wizualizacji danych.

options(repos = c(CRAN = "https://cloud.r-project.org/"))
library(RCurl)
x <- getURL('https://raw.githubusercontent.com/Guzioz/Smieszna-nazwa-projektu-Analiza/refs/heads/main/czynniki.csv')
czynniki <- read.csv(text = x)
library(naniar)
library(mice)
install.packages("gridExtra")
library(gridExtra)
library(ggplot2)
install.packages("corrplot")
library(corrplot)
library(moments)
install.packages("ggstatsplot")
library("ggstatsplot")
install.packages("knitr")
install.packages("kableExtra")
library(knitr)
library(kableExtra)

2. Zapoznanie i czyszczenie danych

Dane zawierają następujące kolumny:

- Exam_Score: wynik egzaminu końcowego

- Hours_Studied: liczba godzin nauki w tygodniu

- Sleep_Hours: średnia liczba godzin snu w ciągu nocy

- Parental_Involvement: Poziom zaangażowania rodziców w edukację ucznia (Low/Medium/High)

- Access_to_Resources: Dostępność zasobów edukacyjnych (Low/Medium/High)

- Peer_Influence: Wpływ rówieśników na wyniki w nauce (Positive/Negative/Neutral)

- Motivation_Level: Poziom motywacji ucznia (Low/Medium/High)

- School_Type: Rodzaj szkoły, do której uczęszcza uczeń (Public/Private)

- Learning_Disabilities: Obecność trudności w uczeniu się (Yes/No)

- Family_Income: Poziom dochodów rodziny (Low/Medium/High)

2.1 Wstępne informacje i typ danych

Analizujemy strukturę danych oraz sprawdzamy podstawowe statystyki opisowe każdej zmiennej, aby zrozumieć, jakie dane posiadamy i jakie są potencjalne problemy, jak na przykład brakujące zmienne.

summary(czynniki)
##  Hours_Studied     Attendance     Parental_Involvement Access_to_Resources
##  Min.   : 1.00   Min.   : 60.00   Length:6607          Length:6607        
##  1st Qu.:16.00   1st Qu.: 70.00   Class :character     Class :character   
##  Median :20.00   Median : 80.00   Mode  :character     Mode  :character   
##  Mean   :19.98   Mean   : 79.98                                           
##  3rd Qu.:24.00   3rd Qu.: 90.00                                           
##  Max.   :44.00   Max.   :100.00                                           
##                                                                           
##  Extracurricular_Activities  Sleep_Hours     Previous_Scores 
##  Length:6607                Min.   : 4.000   Min.   : 50.00  
##  Class :character           1st Qu.: 6.000   1st Qu.: 63.00  
##  Mode  :character           Median : 7.000   Median : 75.00  
##                             Mean   : 7.026   Mean   : 75.07  
##                             3rd Qu.: 8.000   3rd Qu.: 88.00  
##                             Max.   :10.000   Max.   :100.00  
##                             NA's   :350                      
##  Motivation_Level   Internet_Access    Tutoring_Sessions Family_Income     
##  Length:6607        Length:6607        Min.   :0.000     Length:6607       
##  Class :character   Class :character   1st Qu.:1.000     Class :character  
##  Mode  :character   Mode  :character   Median :1.000     Mode  :character  
##                                        Mean   :1.494                       
##                                        3rd Qu.:2.000                       
##                                        Max.   :8.000                       
##                                                                            
##  Teacher_Quality    School_Type        Peer_Influence     Physical_Activity
##  Length:6607        Length:6607        Length:6607        Min.   :0.000    
##  Class :character   Class :character   Class :character   1st Qu.:2.000    
##  Mode  :character   Mode  :character   Mode  :character   Median :3.000    
##                                                           Mean   :2.968    
##                                                           3rd Qu.:4.000    
##                                                           Max.   :6.000    
##                                                                            
##  Learning_Disabilities Parental_Education_Level Distance_from_Home
##  Length:6607           Length:6607              Length:6607       
##  Class :character      Class :character         Class :character  
##  Mode  :character      Mode  :character         Mode  :character  
##                                                                   
##                                                                   
##                                                                   
##                                                                   
##     Gender            Exam_Score    
##  Length:6607        Min.   : 56.00  
##  Class :character   1st Qu.: 65.00  
##  Mode  :character   Median : 67.00  
##                     Mean   : 67.22  
##                     3rd Qu.: 69.00  
##                     Max.   :101.00  
##                     NA's   :300
str(czynniki)
## 'data.frame':    6607 obs. of  20 variables:
##  $ Hours_Studied             : int  23 19 24 29 19 19 29 25 17 23 ...
##  $ Attendance                : int  84 64 98 89 92 88 84 78 94 98 ...
##  $ Parental_Involvement      : chr  "Low" "Low" "Medium" "Low" ...
##  $ Access_to_Resources       : chr  "High" "Medium" "Medium" "Medium" ...
##  $ Extracurricular_Activities: chr  "No" "No" "Yes" "Yes" ...
##  $ Sleep_Hours               : int  7 8 7 8 6 8 NA 6 6 8 ...
##  $ Previous_Scores           : int  73 59 91 98 65 89 68 50 80 71 ...
##  $ Motivation_Level          : chr  "Low" "Low" "Medium" "Medium" ...
##  $ Internet_Access           : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ Tutoring_Sessions         : int  0 2 2 1 3 3 1 1 0 0 ...
##  $ Family_Income             : chr  "Low" "Medium" "Medium" "Medium" ...
##  $ Teacher_Quality           : chr  "Medium" "Medium" "Medium" "Medium" ...
##  $ School_Type               : chr  "Public" "Public" "Public" "Public" ...
##  $ Peer_Influence            : chr  "Positive" "Negative" "Neutral" "Negative" ...
##  $ Physical_Activity         : int  3 4 4 4 4 3 2 2 1 5 ...
##  $ Learning_Disabilities     : chr  "No" "No" "No" "No" ...
##  $ Parental_Education_Level  : chr  "High School" "College" "Postgraduate" "High School" ...
##  $ Distance_from_Home        : chr  "Near" "Moderate" "Near" "Moderate" ...
##  $ Gender                    : chr  "Male" "Female" "Male" "Male" ...
##  $ Exam_Score                : int  67 61 74 71 NA 71 67 66 69 72 ...

Poniżej przedstawiliśmy brakujące wartości jakie pojawiły się w bazie danych.

LICZBA_NA <- data.frame(liczba_brakow = colSums(is.na(czynniki)))
LICZBA_NA
##                            liczba_brakow
## Hours_Studied                          0
## Attendance                             0
## Parental_Involvement                   0
## Access_to_Resources                    0
## Extracurricular_Activities             0
## Sleep_Hours                          350
## Previous_Scores                        0
## Motivation_Level                       0
## Internet_Access                        0
## Tutoring_Sessions                      0
## Family_Income                        350
## Teacher_Quality                       78
## School_Type                            0
## Peer_Influence                         0
## Physical_Activity                      0
## Learning_Disabilities                  0
## Parental_Education_Level              90
## Distance_from_Home                    67
## Gender                                 0
## Exam_Score                           300

Poniżej przedstawiliśmy ilości unikatowych wartości dla każdej zmiennej.

WARTOSCI_BEZ_NA <- data.frame(liczba_unikatowych_wartosci = sapply(czynniki, function(x) length(unique(na.omit(x)))))
WARTOSCI_BEZ_NA
##                            liczba_unikatowych_wartosci
## Hours_Studied                                       41
## Attendance                                          41
## Parental_Involvement                                 3
## Access_to_Resources                                  3
## Extracurricular_Activities                           2
## Sleep_Hours                                          7
## Previous_Scores                                     51
## Motivation_Level                                     3
## Internet_Access                                      2
## Tutoring_Sessions                                    9
## Family_Income                                        3
## Teacher_Quality                                      3
## School_Type                                          2
## Peer_Influence                                       3
## Physical_Activity                                    7
## Learning_Disabilities                                2
## Parental_Education_Level                             3
## Distance_from_Home                                   3
## Gender                                               2
## Exam_Score                                          44

2.2 Standaryzacja wartości

Wyświetlamy posiadane wartości oraz standaryzujemy. Robimy ograniczenia, chociażby dla wyników, które nie powinny przekraczać 100. Dodatkowo przypisujemy zmienne kategoryczne do faktorów, w celu przeprowadzenia dalszej analizy.

typ_danych <- data.frame(typ = sapply(czynniki, class))
typ_danych
##                                  typ
## Hours_Studied                integer
## Attendance                   integer
## Parental_Involvement       character
## Access_to_Resources        character
## Extracurricular_Activities character
## Sleep_Hours                  integer
## Previous_Scores              integer
## Motivation_Level           character
## Internet_Access            character
## Tutoring_Sessions            integer
## Family_Income              character
## Teacher_Quality            character
## School_Type                character
## Peer_Influence             character
## Physical_Activity            integer
## Learning_Disabilities      character
## Parental_Education_Level   character
## Distance_from_Home         character
## Gender                     character
## Exam_Score                   integer

Na podstawie poniżej tabeli możemy zobaczyć, jak wyglądają unikalne wartości dla każdej kolumny. Jest to etap, który pozwala nam zwizualizować badaną baze danych.

columns_to_check <- c("Hours_Studied", "Attendance", "Parental_Involvement", "Access_to_Resources", 
                      "Extracurricular_Activities", "Sleep_Hours", "Previous_Scores", 
                      "Motivation_Level", "Internet_Access", "Tutoring_Sessions", "Family_Income", 
                      "Teacher_Quality", "School_Type", "Peer_Influence", "Physical_Activity", 
                      "Learning_Disabilities", "Parental_Education_Level", "Distance_from_Home", 
                      "Gender", "Exam_Score")
unique_values_all <- lapply(czynniki[columns_to_check], unique)
print(unique_values_all)
## $Hours_Studied
##  [1] 23 19 24 29 25 17 21  9 10 14 22 15 12 20 11 13 16 18 31  8 26 28  4 35 27
## [26] 33 36 43 34  1 30  7 32  6 38  5  3  2 39 37 44
## 
## $Attendance
##  [1]  84  64  98  89  92  88  78  94  80  97  83  82  68  60  70  75  99  74  65
## [20]  62  91  90  66  69  72  63  61  86  77  71  67  87  73  96 100  81  95  79
## [39]  85  76  93
## 
## $Parental_Involvement
## [1] "Low"    "Medium" "High"  
## 
## $Access_to_Resources
## [1] "High"   "Medium" "Low"   
## 
## $Extracurricular_Activities
## [1] "No"  "Yes"
## 
## $Sleep_Hours
## [1]  7  8  6 NA 10  9  5  4
## 
## $Previous_Scores
##  [1]  73  59  91  98  65  89  68  50  80  71  88  87  97  72  74  70  82  58  99
## [20]  84 100  75  54  90  94  51  57  66  96  93  56  52  63  79  81  69  95  60
## [39]  92  77  62  85  78  64  76  55  86  61  53  83  67
## 
## $Motivation_Level
## [1] "Low"    "Medium" "High"  
## 
## $Internet_Access
## [1] "Yes" "No" 
## 
## $Tutoring_Sessions
## [1] 0 2 1 3 4 5 6 7 8
## 
## $Family_Income
## [1] "Low"    "Medium" "High"   NA      
## 
## $Teacher_Quality
## [1] "Medium" "High"   "Low"    NA      
## 
## $School_Type
## [1] "Public"  "Private"
## 
## $Peer_Influence
## [1] "Positive" "Negative" "Neutral" 
## 
## $Physical_Activity
## [1] 3 4 2 1 5 0 6
## 
## $Learning_Disabilities
## [1] "No"  "Yes"
## 
## $Parental_Education_Level
## [1] "High School"  "College"      "Postgraduate" NA            
## 
## $Distance_from_Home
## [1] "Near"     "Moderate" "Far"      NA        
## 
## $Gender
## [1] "Male"   "Female"
## 
## $Exam_Score
##  [1]  67  61  74  71  NA  66  69  72  68  70  65  64  60  63  62 100  76  79  73
## [20]  78  89  75  59  86  97  83  84  80  58  94  92  82  77 101  88  91  99  87
## [39]  57  96  98  95  85  93  56
czynniki <- subset(czynniki, Exam_Score <= 100)
czynniki$Family_Income <- factor(czynniki$Family_Income, levels = c("Low", "Medium", "High"))
czynniki$Teacher_Quality <- factor(czynniki$Teacher_Quality, levels = c("Low", "Medium", "High"))
czynniki$Parental_Education_Level <- factor(czynniki$Parental_Education_Level, levels = c("High School", "College", "Postgraduate"))
czynniki$Distance_from_Home <- factor(czynniki$Distance_from_Home, levels = c("Near", "Moderate", "Far"))
czynniki$Motivation_Level <- factor(czynniki$Motivation_Level, levels = c("Low", "Medium", "High"))
czynniki$Internet_Access <- factor(czynniki$Internet_Access, levels = c("Yes", "No"))
czynniki$Learning_Disabilities <- factor(czynniki$Learning_Disabilities, levels = c("No", "Yes"))
czynniki$School_Type <- factor(czynniki$School_Type, levels = c("Public", "Private"))
czynniki$Extracurricular_Activities <- factor(czynniki$Extracurricular_Activities, levels = c("No", "Yes"))
czynniki$Peer_Influence <- factor(czynniki$Peer_Influence, levels = c("Positive", "Negative", "Neutral"))
czynniki$Gender <- factor(czynniki$Gender, levels = c("Male", "Female"))

2.3 Czyszczenie brakujących wartości

Początkowo usuwamy brakujące wartości wyników egzaminu, ze względu na to, że jest to zmienna badana. W celu ograniczenia ryzyka, uważamy, że jest to ważne dla dalszej analizy.

czynniki2 <- subset(czynniki, !is.na(Exam_Score))
LICZBA_NA2 <- data.frame(liczba_brakow = colSums(is.na(czynniki2)))
LICZBA_NA2
##                            liczba_brakow
## Hours_Studied                          0
## Attendance                             0
## Parental_Involvement                   0
## Access_to_Resources                    0
## Extracurricular_Activities             0
## Sleep_Hours                          339
## Previous_Scores                        0
## Motivation_Level                       0
## Internet_Access                        0
## Tutoring_Sessions                      0
## Family_Income                        325
## Teacher_Quality                       71
## School_Type                            0
## Peer_Influence                         0
## Physical_Activity                      0
## Learning_Disabilities                  0
## Parental_Education_Level              88
## Distance_from_Home                    63
## Gender                                 0
## Exam_Score                             0

Reszte zmiennych postanawiamy zastąpić przy użyciu metody mice. Która będzie najlepsza wobec zastąpywania brakujących wartości dla naszych danych. Ze względu na to, że mice jest techniką wielokrotnej imputacji, która polega na generowaniu kilku zestawów imputowanych danych, a nie tylko jednej “najlepszej” wartości.

method <- make.method(czynniki2)
method[c("Sleep_Hours", "Previous_Scores", "Tutoring_Sessions", "Physical_Activity", "Exam_Score")] <- "pmm"
method[c("Internet_Access", "Gender", "Extracurricular_Activities")] <- "logreg"
method[c("Family_Income", "Teacher_Quality", "Parental_Education_Level", "Distance_from_Home", 
         "Motivation_Level", "Learning_Disabilities", "School_Type", "Peer_Influence")] <- "polyreg"
czynnikisleep <- mice(czynniki2, m = 5, method = method, seed = 500)
czynniki3 <- complete(czynnikisleep, 1)
LICZBA_NA <- data.frame(liczba_brakow = colSums(is.na(czynniki3)))
LICZBA_NA
##                            liczba_brakow
## Hours_Studied                          0
## Attendance                             0
## Parental_Involvement                   0
## Access_to_Resources                    0
## Extracurricular_Activities             0
## Sleep_Hours                            0
## Previous_Scores                        0
## Motivation_Level                       0
## Internet_Access                        0
## Tutoring_Sessions                      0
## Family_Income                          0
## Teacher_Quality                        0
## School_Type                            0
## Peer_Influence                         0
## Physical_Activity                      0
## Learning_Disabilities                  0
## Parental_Education_Level               0
## Distance_from_Home                     0
## Gender                                 0
## Exam_Score                             0

3. Wizualizacja

3.1 Wizualizacja zmiennej objaśnianej (Exam_Score)

Tworzymy wykres pudełkowy, oraz histogram dla zmiennej wynikowej(Exam_Score).

b1 <- ggplot(czynniki3, aes(y = Exam_Score)) +
  geom_boxplot() +
  labs(title = "Exam_Score")
h1 <- ggplot(czynniki3) +
  aes(x = Exam_Score) +
  geom_histogram(bins = 30, fill = "#0c4c8a") +
  theme_minimal()
grid.arrange(b1, h1, nrow = 1)

Na powyższych wykresach możemy zauważyć, że znacząca większość uczniów osiąga wyniki między 65-70%. Z drugiej strony widzimy odstające wartości powyżej 70%, co może sugerować skośność prawostronną, co zostanie przeanalizowane w dalszej części projektu.

3.2 Wykresy kołowe

Tworzymy wykresy kołowe dla zmiennych kategorycznych, takich jak dostęp do Internetu, oraz obecności trudności w nauce, aby zobaczyć proporcje poszczególnych kategorii i łatwiej zinterpretować dane.

fill_colors <- c("Yes" = "blue", "No" = "red")
create_pie_chart <- function(data, var, fill_colors) {
  ggplot(data, aes(x = "", fill = as.factor(!!sym(var)))) +
    geom_bar(width = 1, color = "white") +
    coord_polar(theta = "y") +
    scale_fill_manual(values = fill_colors) +
    labs(title = paste("Pie Chart of", var), fill = "Categories") +
    theme_void() +
    theme(legend.position = "top") +
    geom_text(aes(label = scales::percent(..count.. / sum(..count..))),
              stat = "count", position = position_stack(vjust = 0.5), color = "white")
}
pie_internet <- create_pie_chart(czynniki3, "Internet_Access", fill_colors)
pie_learning_disabilities <- create_pie_chart(czynniki3, "Learning_Disabilities", fill_colors)
pie_internet | pie_learning_disabilities

Powyższy wykres przedstawiający procentowy dostęp uczniów do internetu, ukazuje, że tylko 8% uczniów nie ma dostępu do internetu.

Kolejny wykres kołowy, ukazuje, że aż 11% uczniów ma pewne trudności w nauce, co może sugerować obecność pewnych dysfunkcji wśród uczniów

3.3 Wykresy słupkowe

Tworzymy wykresy słupkowe dla zmiennych kategorycznych, takich jak płeć, wpływ rówieśników, poziomu dochodu rodziny, oraz odległości od domu do szkoły, aby porównać liczebność grup i zauważyć ewentualne nierówności.

gender_colors <- c("Female" = "pink", "Male" = "blue")
peer_influence_colors <- c("Neutral" = "blue", "Positive" = "green", "Negative" = "red")
family_income_colors <- c("Low" = "red", "Medium" = "blue", "High" = "green")
distance_from_home_colors <- c("Near" = "green", "Moderate" = "blue", "Far" = "red")
gender_plot <- ggplot(czynniki3, aes(x = Gender, fill = as.factor(Gender))) +
  geom_bar() +
  scale_fill_manual(values = gender_colors) +
  labs(title = "Bar Plot of Gender", x = "Gender", y = "Count") +
  theme_minimal()
family_income_plot <- ggplot(czynniki3, aes(x = Family_Income, fill = as.factor(Family_Income))) +
  geom_bar() +
  scale_fill_manual(values = family_income_colors) +
  labs(title = "Bar Plot of Family Income", x = "Family Income", y = "Count") +
  theme_minimal()
distance_plot <- ggplot(czynniki3, aes(x = Distance_from_Home, fill = as.factor(Distance_from_Home))) +
  geom_bar() +
  scale_fill_manual(values = distance_from_home_colors) +
  labs(title = "Bar Plot of Distance from Home", x = "Distance from Home", y = "Count") +
  theme_minimal()
peer_influence_plot <- ggplot(czynniki3, aes(x = Peer_Influence, fill = as.factor(Peer_Influence))) +
  geom_bar() +
  scale_fill_manual(values = peer_influence_colors) +
  labs(title = "Bar Plot of Peer Influence", x = "Peer Influence", y = "Count") +
  theme_minimal()
(gender_plot / family_income_plot) 

Na podstawie powyższych wykresów możemy zauważyć, że większość wśród uczniów stanowią mężczyźni o prawie tysiąc uczniów więcej.

Dodatkowo, znacząca większość uczniów pochodzi z rodzin, które posiadają dochody niskie, oraz średnio(około tylu samo uczniów na katergorie), a niewiele ponad tysiąc uczniów pochodzi z rodzin oiągających wysokie dochody.

(distance_plot / peer_influence_plot)

Kolejny wykres ukazuje, że znacząco ponad połowa uczniów pochodzi z rejonów, które znajdują się blisko szkoły.

Ostatni wykres ukazuje wpływ rówieśników na ucznia, ciekawym faktem może być to, że porównywalnie tyle samo uczniów odczówa pozytywny wpływ, jak i negatywny.

3.4 Wykresy pudełkowe

Tworzymy wykresy pudełkowe, by zobaczyć, jak jakość nauczycieli, poziom wyedukowania rodziców, poziom motywacji, czy typ szkoły wpływają na wyniki egzaminów.

plot1 <- ggplot(czynniki3, aes_string(x = "Teacher_Quality", y = "Exam_Score", fill = "Teacher_Quality")) +
  geom_boxplot(color = "black") +
  labs(title = "Boxplot of Exam_Score by Teacher_Quality", x = "Teacher Quality", y = "Exam Score") +
  scale_fill_manual(values = rainbow(length(unique(czynniki3[["Teacher_Quality"]])))) +
  theme_minimal()
print(plot1)

Na podstawie wykresu jakości nauczycieli, a wyniku egzaminu, możemy zauważyć lekką asymetryczność, dla wyników low, oraz high. Uczniowie, mający nauczycieli, których ocenili na wysoką jakość, mieli szanse na osiągnięcie lepszych wyników, niż Ci z na przykład niską jakościa. Możemy dodatkowo zauważyć, że nauczyciele ocenieni na jakość średnią, mieli najwięcej odstający wyników.

plot2 <- ggplot(czynniki3, aes_string(x = "Parental_Education_Level", y = "Exam_Score", fill = "Parental_Education_Level")) +
  geom_boxplot(color = "black") +
  labs(title = "Boxplot of Exam_Score by Parental_Education_Level", x = "Parental Education Level", y = "Exam Score") +
  scale_fill_manual(values = rainbow(length(unique(czynniki3[["Parental_Education_Level"]])))) +
  theme_minimal()
print(plot2)

Na podstawie wykresu poziom wykształcenia rodziców, a wyniku egzaminu, możemy zauważyć, że im wyższe wykształcenie rodziców, tym wyniki osiągane przez uczniów były większe. Z drugiej strony możemy zauważyć asymetryczność dla rodziców z wykształceniem wyższym. Najwięcej odstających wartośći jest dla wyników uczniów, których rodzice mają wykształcene policealne.

plot3 <- ggplot(czynniki3, aes_string(x = "Motivation_Level", y = "Exam_Score", fill = "Motivation_Level")) +
  geom_boxplot(color = "black") +
  labs(title = "Boxplot of Exam_Score by Motivation_Level", x = "Motivation Level", y = "Exam Score") +
  scale_fill_manual(values = rainbow(length(unique(czynniki3[["Motivation_Level"]])))) +
  theme_minimal()
print(plot3)

Na podstawie wykresu poziom motywacji, a wyniku egzaminu, możemy zauważyć, że im wyższa motywacja, tym wyniki osiągane przez uczniów były większe. Z drugiej strony możemy zauważyć asymetryczność dla motywacji niskiej i wysokiej. Najwięcej odstających wartośći jest dla wyników uczniów, z motywacją średnią.

plot4 <- ggplot(czynniki3, aes_string(x = "School_Type", y = "Exam_Score", fill = "School_Type")) +
  geom_boxplot(color = "black") +
  labs(title = "Boxplot of Exam_Score by School_Type", x = "School Type", y = "Exam Score") +
  scale_fill_manual(values = rainbow(length(unique(czynniki3[["School_Type"]])))) +
  theme_minimal()
print(plot4)

Na podstawie wykresu typ szkoły, a wyniku egzaminu, możemy zauważyć, że wyniki dla obu szkół rozkładają się podobnie symetrycznie. Z druegiej strony możemy zauważyć, więcej wyników odstającyh dla uczniów ze szkół publicznych.

3.5 Histogramy

Tworzymy histogramy dla zmiennych liczbowych jak, godziny nauki, liczba godzin snu, liczba sesji korepetycji w miesiącu, średnia liczba godzin aktywności fizycznej, aby zrozumieć rozkład każdej zmiennej i zauważyć ewentualne skupienia lub wartości odstające.

plots <- list()
numeric_vars <- c("Hours_Studied", "Sleep_Hours", "Tutoring_Sessions", "Physical_Activity")
for (var in numeric_vars) {
  hist_plot <- ggplot(czynniki3, aes_string(x = var)) +
    geom_histogram(bins = 30, fill = "#0c4c8a", color = "black") +
    labs(title = paste("Histogram of", var), x = var, y = "Frequency") +
    theme_minimal()
  plots[[var]] <- hist_plot
}
(plots[["Hours_Studied"]] | plots[["Sleep_Hours"]]) / 
(plots[["Tutoring_Sessions"]] | plots[["Physical_Activity"]])

Możemy zauważyć wobec rozkładów liczby godzin nauki, snu, oraz aktywności fizycznej mniej więcej symetryczne rozkłady, które nie mają większych odstających wartości. Z drugiej strony, na wykresie średniej liczby sesji korepetycji w miesiącu, możemy zaobserwować skośność prawostronną, gdzie większość uczniów ma maksymalnie do około 2 sesji miesięcznie, a reszta potrafi mieć nawet do 8 sesji miesięcznie.

3.6 Wykres punktowy

Tworzymy wykresy punktowe (scatter plots) dla zmiennych liczbowych, takich jak frekwencja, oraz poprzedni wynik egzaminu w odniesieniu do wyniku egzaminu.

scatter_plots <- list()
numeric_vars <- c("Attendance", "Previous_Scores")
for (var in numeric_vars) {
  scatter_plot <- ggplot(czynniki3, aes_string(x = var, y = "Exam_Score")) +
    geom_point(color = "#0c4c8a") +
    labs(title = paste("Scatter Plot of Exam_Score vs", var), x = var, y = "Exam Score") +
    theme_minimal()
  scatter_plots[[var]] <- scatter_plot
}
scatter_plots[["Attendance"]] | scatter_plots[["Previous_Scores"]]

Na podstawie wykresu punktowego wynik egzaminu, a frekwencja możemy zauważyć pewien trend, który ukazuje, że im większa frekwencja tym średnio wynik egzaminu był wyższy. Dodatkowo możemy zauważyć pewne odstające wartości, które osiągał znacząco większe wyniki od średniej.

Na podstawie wykresu punktowego wynik egzaminu, a poprzedni wynik egzaminu możemy zauważyć, że wyniki rozkładają się w porównywalnie w ten sam sposób, nie zależnie od poprzedniego wyniku egzaminu.

4. Statystyki

4.1 Statystyki opisowe

Obliczamy podstawowe statystyki, między innymi takie jak, minimum, maksimum, mediana, kwartyle, średnia i odchylenie standardowe.

# Obliczanie poszczególnych statystyk (testowe bo inaczej nie działało)
Min <- min(czynniki3$Exam_Score, na.rm = TRUE)
Max <- max(czynniki3$Exam_Score, na.rm = TRUE)
Kwartyl_dolny <- quantile(czynniki3$Exam_Score, 0.25, na.rm = TRUE)
Mediana <- median(czynniki3$Exam_Score, na.rm = TRUE)
Kwartyl_gorny <- quantile(czynniki3$Exam_Score, 0.75, na.rm = TRUE)
Srednia <- mean(czynniki3$Exam_Score, na.rm = TRUE)
Odch_std <- sd(czynniki3$Exam_Score, na.rm = TRUE)
IQR_value <- IQR(czynniki3$Exam_Score, na.rm = TRUE)
Skosnosc <- skewness(czynniki3$Exam_Score, na.rm = TRUE)
Kurtoza_value <- kurtosis(czynniki3$Exam_Score, na.rm = TRUE)
Odch_std_pct <- (Odch_std / Srednia) * 100
Odch_cwiartkowe_pct <- (IQR_value / Mediana) * 100
Odchylenie_cwiartkowe <- IQR_value / 2
statystyki <- data.frame(
  Min = round(Min, 3),
  Max = round(Max, 3),
  "Kwartyl_dolny" = round(Kwartyl_dolny, 3),
  Mediana = round(Mediana, 3),
  "Kwartyl_górny" = round(Kwartyl_gorny, 3),
  Średnia = round(Srednia, 3),
  "Odchylenie_standardowe" = round(Odch_std, 3),
  IQR = round(IQR_value, 3),
  "Skośność" = round(Skosnosc, 3),
  "Kurtoza" = round(Kurtoza_value, 3),
  "Odchylenie_standardowe%" = paste0(round(Odch_std_pct, 3), "%"),
  "Odchylenie_ćwiartkowe%" = paste0(round(Odch_cwiartkowe_pct, 3), "%"),
  "Odchylenie_ćwiartkowe" = round(Odchylenie_cwiartkowe, 3)
)
statystyki <- t(statystyki)
statystyki <- as.data.frame(statystyki)
colnames(statystyki) <- c("Wartości")
statystyki$Statystyki <- rownames(statystyki)
rownames(statystyki) <- NULL
kable(statystyki, format = "html", caption = "Statystyki opisowe dla zmiennej 'Exam_Score'") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = T)
Statystyki opisowe dla zmiennej ‘Exam_Score’
Wartości Statystyki
56 Min
100 Max
65 Kwartyl_dolny
67 Mediana
69 Kwartyl_górny
67.217 Średnia
3.835 Odchylenie_standardowe
4 IQR
1.554 Skośność
13.062 Kurtoza
5.705% Odchylenie_standardowe.
5.97% Odchylenie_ćwiartkowe.
2 Odchylenie_ćwiartkowe

Po przeprowadzonej analizie statystyki opisowej możemy zobaczyć, że średnia oraz mediana są zbliżone około 67. Pomimo tego skośność wychodzi prawostronna, co oznacza, że występują wartości odstające dążące wyniku 100. Dodatkowo, kurtoza potwierdza spiczastość samego rozkładu

4.2 Korelacje

Tworzymy macierz korelacji, by zbadać, jak różne czynniki są ze sobą powiązane, aby zidentyfikować silne korelacje, które mogą wskazywać na potencjalne przyczyny wysokich lub niskich wyników egzaminów.

cor_matrix <- cor(czynniki_kor, use = "complete.obs")
corrplot(cor_matrix, method = "color", type = "upper", order = "hclust",
         tl.col = "black", tl.srt = 45)

5. Testowanie i wnioskowanie statystyczne

5.1 Test Korelacji Exam_Score vs Hours_Studied

Analizujemy zależność korelacji Liczby Godzin Nauki, wobec Wyniu Egazminu (Przyjęty poziom istotności alfa = 0,05). Do analizy zastosujemy test Pearsona.

ggscatterstats(
  data = czynniki3,
  x = Hours_Studied,
  y = Exam_Score,
  title = "Korelacja: Wynik egzaminu a liczba godzin nauki",
  xlab = "Liczba godzin nauki",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Choć ostateczny wynik był spodziewany, to analiza wykazała, że liczba godzin nauki ma istotny wpływ na wynik egazminu, współczynnik p<0,05 (przyjęty poziom istotności)

5.2 Test Korelacji Exam_Score vs Previous_Scores

Analizujemy zależność korelacji Wcześniejszego Wyniku, wobec Wyniu Egazminu (Przyjęty poziom istotności alfa = 0,05). Do analizy zastosujemy test Pearsona.

# Korelacja Exam_Score vs Previous_Scores
ggscatterstats(
  data = czynniki3,
  x = Previous_Scores,
  y = Exam_Score,
  title = "Korelacja: Wynik egzaminu a wcześniejsze wyniki",
  xlab = "Poprzednie wyniki",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Przeprowadzony test wykazał, że wcześniejszy wynik ma istotny wpływ na wynik egzaminu, współczynnik p<0,05 (przyjęty poziom istotności).

5.3 Model regresji liniowej Exam_Score ~ Physical_Activity + Sleep_Hours

Analizujemy zależność liniową Wyniku Egzaminu wobec Czasu Aktywności Fizycznej, oraz Średniego Czasu Snu (Przyjęty poziom istotności alfa = 0,05).

#Tworzymy model regresji liniowej z Physical_Activity i Sleep_Hours jako zmiennymi objaśniającymi
model1 <- lm(Exam_Score ~ Physical_Activity + Sleep_Hours, data = czynniki3)

plot1 <- ggcoefstats(
  model1,
  title = "Wpływ aktywności fizycznej i snu na wynik egzaminu",
  xlab = "Współczynniki regresji",
  ggtheme = ggplot2::theme_minimal()
)

# Rysowanie wykresu
print(plot1)

Przeprowadzona zależność liniowa wykazała, że aktywność fizyczna ma istotny wpływ na wynik egzaminu, współczynnik p<0,05 (przyjęty poziom istotności). Z drugiej strony czas snu jest nie istonty na wynik egzaminu, współczynnik p>0,05 (przyjęty poziom istotności)

5.4 Test Korelacji Exam_Score vs Attendance

Analizujemy zależność korelacji Frekwencji, wobec Wyniu Egazminu (Przyjęty poziom istotności alfa = 0,05). Do analizy zastosujemy test Pearsona.

ggscatterstats(
  data = czynniki3,
  x = Attendance,
  y = Exam_Score,
  title = "Korelacja: Wynik egzaminu a frekwencja",
  xlab = "Frekwencja (%)",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Przeprowadzony test wykazał, że frekwencja ma istotny wpływ na wynik egzaminu, współczynnik p<0,05(przyjęty poziom istotności).

5.5 Analiza porównawcza Exam_Score według Gender

Porównujemy wielkości efektów dla Wyniu Egazminu, ze względu na płeć (Przyjęty poziom istotności alfa = 0,05). Do analizy wykorzystamy statystyke g Hedge’a.

ggbetweenstats(
  data = czynniki3,
  x = Gender,
  y = Exam_Score,
  title = "Porównanie wyników egzaminu wg płci",
  xlab = "Płeć",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Przeprowadzony test wykazał, że wynik egzaminu, nie jest zależny od płci, współczynnik p>0,05 (przyjęty poziom istotności).

5.6 Analiza porównawcza Exam_Score według Access_to_Resources

Wykonujemy test porównania średnich dla Wyniu Egazminu, ze względu na Dostęp do Zasobów Edukacyjnych (Przyjęty poziom istotności alfa = 0,05). Do analizy wykorzystamy metodę Gamesa-Howella.

ggbetweenstats(
  data = czynniki3,
  x = Access_to_Resources,
  y = Exam_Score,
  title = "Porównanie wyników egzaminu wg dostępu do zasobów edukacyjnych",
  xlab = "Zasoby edukacyjne",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Przeprowadzony test wykazał, że wynik egzaminu, jest zależny od poziomu dostępu do zasobów edukacyjnych, współczynnik p<0,05 (przyjęty poziom istotności).

5.7 Analiza porównawcza Exam_Score według Parental_Involvement

Wykonujemy test porównania średnich dla Wyniu Egazminu, ze względu na Poziom Zaangażowania Rodziców (Przyjęty poziom istotności alfa = 0,05). Do analizy wykorzystamy metodę Gamesa-Howella.

ggbetweenstats(
  data = czynniki3,
  x = Parental_Involvement,
  y = Exam_Score,
  title = "Porównanie wyników egzaminu wg poziomu zaagnażowania rodziców",
  xlab = "Poziom zaangażowania rodziców",
  ylab = "Wynik egzaminu",
  ggtheme = ggplot2::theme_minimal()
)

Przeprowadzony test wykazał, że wynik egzaminu, jest zależny od poziomu zaangażowania rodziców, współczynnik p<0,05 (przyjęty poziom istotności).

6. Podsumowanie

Celem projektu była analiza czynników wpływających na wyniki egzaminów uczniów. W ramach projektu przeprowadziliśmy kompleksową analizę danych zawierających informacje na temat takich zmiennych jak między innymi liczba godzin snu, czas poświęcony na naukę, rodzaj szkoły, czy na przykład wpływ rówieśników i motywacja ucznia.

Proces analizy obejmował kilka kluczowych etapów:

  1. Data Wrangling: Na początek zajęliśmy się przygotowaniem danych. Wczytaliśmy dane z dostępnych źródeł i sprawdziliśmy ich strukturę, aby upewnić się, że zawierają one wszystkie niezbędne informacje. Etap ten obejmował także identyfikację zmiennych, które miały istotny wpływ na wyniki egzaminów. Przeanalizowaliśmy dane pod kątem ich typu, rozkładu oraz obecności błędów w strukturze.

  2. Czyszczenie Danych: Po wstępnym przygotowaniu danych, przystąpiliśmy do oczyszczania ich z błędów i braków. Wykorzystaliśmy techniki imputacji brakujących danych, takie jak imputacja metodą “mice”, co pozwoliło nam uzyskać kompletny zbiór danych. Ponadto, usunęliśmy wszelkie niezgodności i błędne wartości, co poprawiło jakość analizy.

  3. Wizualizacja: W kolejnym kroku skoncentrowaliśmy się na wizualizacji danych. Użyliśmy wykresów pudełkowych, histogramów, wykresów słupkowych, kołowych, czy punktowych, aby zobrazować rozkład danych i zależności pomiędzy poszczególnymi zmiennymi. Wizualizacje te pozwoliły na łatwiejsze zrozumienie kluczowych informacji, takich jak rozkład wyników egzaminu czy różnice w wynikach między uczniami o różnym poziomie motywacji i dostępie do zasobów edukacyjnych.

  4. Analiza Opisowa: W ramach analizy opisowej obliczyliśmy podstawowe miary statystyczne, takie jak średnia, mediana, odchylenie standardowe oraz kwartyle dla wyniku egzaminu. Zauważyliśmy, że wyniki uczniów rozkładają się dość równomiernie, a średni wynik egzaminu wynosi około 67%. Przeanalizowaliśmy również skośność i kurtozę, co pozwoliło na lepsze zrozumienie rozkładu wyników wśród uczniów.

  5. Wnioskowanie Statystyczne: Na podstawie wyników analizy opisowej, przystąpiliśmy do wnioskowania statystycznego. Sprawdziliśmy zależności między różnymi czynnikami a wynikami egzaminów. Zauważyliśmy, że czynniki takie jak liczba godzin snu, motywacja uczniów, wsparcie ze strony rodziców oraz dostępność zasobów edukacyjnych mają znaczący wpływ na wyniki. Wykorzystaliśmy testy statystyczne, aby potwierdzić, że obserwowane różnice są istotne i nie wynikają z przypadkowych fluktuacji w danych.

Wyniki naszej analizy pokazują, że wyniki egzaminów zależą od wielu czynników. Kluczowymi zmiennymi, które mają istotny wpływ na wyniki egzaminów, są liczba godzin nauki, wcześniejsze wyniki, aktywność fizyczna, frekwencja, dostęp do zasobów edukacyjnych oraz zaangażowanie rodziców. Z kolei czas snu i płeć nie mają bezpośredniego wpływu na wyniki.