본문 바로가기

Data Analysis/Kaggle

[Kaggle] Students Performance in Exam 데이터 분석 2 (EDA / 시각화 / 리뷰)

728x90

이전 내용은 아래 글에서 확인 하실 수 있습니다.

[Data Analysis/Kaggle] - [Kaggle] Students Performance in Exam 데이터 분석 1 (데이터 확인 / 질문 / 전처리)

 

[Kaggle] Students Performance in Exam 데이터 분석 1 (데이터 확인 / 질문 / 전처리)

Students Performance in Exam 데이터셋 분석 분석 목적 : 학생 정보와 시험 점수와의 관계 분석 데이터 출처 : https://www.kaggle.com/spscientist/students-performance-in-exams Students Performance in Exam..

sks8410.tistory.com

4. EDA & Visualization

4-1 성별과 성적의 관계는?

# 성별 비율 시각화

sp_gender = sp["gender"].value_counts()

fig = px.bar(sp_gender, x = sp_gender.index, y = sp_gender.values,
             color = sp_gender.index, text = sp_gender.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>성별 비율</b>",
        font_size = 20
    ),
    
    xaxis = dict(
        title = "성별"
    ),
    
    yaxis = dict(
        title = "성별 수"
    ),
    
    legend_title_text = "성별",
    template = "plotly_white"
)

fig.show()

여학생 518명, 남학생 482명으로 여학생이 조금 더 많이 있습니다.

 

 

# 전체 성적 합계를 total score 컬럼에 등록
sp["total score"] = sp["math score"] + sp["reading score"] + sp["writing score"]

print(sp.shape)
sp.head()

 

 

# 전체 성적 평균과 성별의 관계 시각화

sp_gender_total = sp.groupby("gender")["total score"].mean().round(2)

fig = px.bar(x = sp_gender_total.index, y = sp_gender_total.values,
             color = sp_gender_total.index, text = sp_gender_total.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>전체 성적 평균과 성별의 관계</b>",
        font_size = 20
    ),
    
    xaxis = dict(
        title = "성별"
    ),
    
    yaxis = dict(
        title = "점수"
    ),
    
    legend_title_text = "성별",
    template = "plotly_white"
)

fig.show()

전체 성적의 경우 여학생이 남학생보다 조금 더 높습니다.

 

 

# 개별 과목 성적과 성별과의 관계 시각화

sp_gender_subject = sp.groupby("gender")[["math score", "reading score", "writing score"]].mean().round(2)

color = px.colors.qualitative.Plotly

fig = make_subplots(rows = 1, cols = 3)

fig.add_trace(
    go.Bar(x = sp_gender_subject.index,
           y = sp_gender_subject["math score"],
           text = sp_gender_subject["math score"],
           marker_color = [color[0], color[1]]),
    row = 1, col = 1
)

fig.add_trace(
    go.Bar(x = sp_gender_subject.index,
           y = sp_gender_subject["reading score"],
           text = sp_gender_subject["reading score"],
           marker_color = [color[0], color[1]]),
    row = 1, col = 2
)

fig.add_trace(
    go.Bar(x = sp_gender_subject.index,
           y = sp_gender_subject["writing score"],
           text = sp_gender_subject["writing score"],
           marker_color = [color[0], color[1]]),
    row = 1, col = 3
)

fig.update_xaxes(title = "Math", row = 1, col = 1)
fig.update_xaxes(title = "Reading", row = 1, col = 2)
fig.update_xaxes(title = "Writing", row = 1, col = 3)

fig.update_yaxes(title = "점수", row = 1, col = 1)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>개별 과목 평균 성적과 성별의 관계</b>",
        font_size = 20
    ),
    
    showlegend = False,
    template = "plotly_white"
)

fig.show()

수학은 남학생이 여학생보다 성적이 더 높지만 나머지 두 과목(Reading, Writing)은 여학생 성적이 더 높습니다.

4-2 인종/민족과 성적의 관계는?  

# 인종/민족 비율 시각화

fig = px.pie(labels = sp["race/ethnicity"].value_counts().index,
             values = sp["race/ethnicity"].value_counts().values,
             names = sp["race/ethnicity"].value_counts().index)

fig.update_traces(
    textinfo = "label + percent + value",
    textfont_size = 15,
    textfont_color = "white"
)

fig.update_layout(
    title = dict(
        text = "<b>인종/민족 비율</b>",
        font_size = 20
    ),
    
    showlegend = False
)

fig.show()

group C 가 가장 비율이 높고 group A 가 가장 비율이 낮습니다.

 

 

# 인종/민족별 성별 비율

sp_race_gender = sp.groupby(["race/ethnicity", "gender"]).agg({"lunch" : "count"}).reset_index()
sp_race_gender = sp_race_gender.rename(columns = {"lunch" : "count"})

fig = px.bar(sp_race_gender, x = "race/ethnicity", y = "count", color = "gender",
             barmode = "group", text = "count")

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>인종/민족별 성별 비율</b>",
        font_size = 20
    ),
    
    xaxis = dict(title = "인종/민족"),
    yaxis = dict(title = "수"),
    
    template = "plotly_white"
)

fig.show()

group C 가 남학생/여학생이 가장 많습니다.
group B, group C 는 여학생이 남학생보다 많고 나머지 그룹(group A/group D/group E)은 남학생이 더 많습니다.

 

 

# 전체 성적 평균과 인종/민족과의 관계 시각화

sp_race_total = sp.groupby("race/ethnicity")["total score"].mean().round(2)

fig = px.bar(x = sp_race_total.index, y = sp_race_total.values,
             color = sp_race_total.index, text = sp_race_total.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>전체 성적 평균과 인종/민족의 관계</b>",
        font_size = 20
    ),
    
    xaxis = dict(
        title = "인종/민족"
    ),
    
    yaxis = dict(
        title = "점수"
    ),
    
    legend_title_text = "인종/민족",
    template = "plotly_white"
)

fig.show()

group E 가 전체 성적 평균이 가장 높고 group A 가 가장 낮으나 전체적으로 차이가 크게나지 않습니다.

 

 

# 개별 성적 평균과 인종/민족의 관계 시각화

fig = make_subplots(rows = 3, cols = 1)

fig.add_trace(
    go.Box(
        x = sp["race/ethnicity"],
        y = sp["math score"],
        marker_color = color[0],
        name = "Math"
    ),
    row = 1, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["race/ethnicity"],
        y = sp["reading score"],
        marker_color = color[1],
        name = "Reading"
    ),
    row = 2, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["race/ethnicity"],
        y = sp["writing score"],
        marker_color = color[2],
        name = "Writing"
    ),
    row = 3, col = 1
)

fig.update_xaxes(
    categoryorder = "array",
    categoryarray = ["group A", "group B", "group C", "group D", "group E"],    
)

fig.update_xaxes(title = "인종/민족", row = 3, col = 1)
fig.update_yaxes(title = "Math score", row = 1, col = 1)
fig.update_yaxes(title = "Reading score", row = 2, col = 1)
fig.update_yaxes(title = "Writing score", row = 3, col = 1)

fig.update_layout(
    height = 1000,
    title = dict(
        text = "<b>개별 과목별 성적과 인종/민족의 관계</b>",
        font_size = 20
    )
)

fig.show()

개별 성적도 모든 과목에서 group E 가 가장 높고 group A 가 가장 낮으나 전체 그룹간에 차이가 크게 나지 않습니다.

4-3 부모의 교육 수준과 성적의 관계는?

# 부모의 교육 수준 비율 시각화

fig = px.pie(labels = sp["parental level of education"].value_counts().index,
             values = sp["parental level of education"].value_counts().values,
             names = sp["parental level of education"].value_counts().index)

fig.update_traces(
    textinfo = "label + percent + value",
    textfont_size = 15,
    textfont_color = "black",    
)

fig.update_layout(
    title = dict(
        text = "<b>부모의 교육 수준 비율</b>",
        font_size = 20
    ),
    
    showlegend = False
)

fig.show()

학사 수준 이상의 교육을 받은 비율이 약 62.5% 이며 나머지는 고등 교육까지 이수했습니다.

 

 

# 부모의 교육 수준에 따른 성별 비율

sp_parent_gender = sp.groupby(["parental level of education", "gender"]).agg({"lunch" : "count"}).reset_index()
sp_parent_gender = sp_parent_gender.rename(columns = {"lunch" : "count"})

fig = px.bar(sp_parent_gender, x = "parental level of education", y = "count", color = "gender",
             barmode = "group", text = "count")

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>부모의 교육 수준별 성별 비율</b>",
        font_size = 20
    ),
    
    xaxis = dict(title = "부모의 교육 수준"),
    yaxis = dict(title = "수"),
    
    template = "plotly_white"
)

fig.show()

부모의 교육 수준이 some college 인 여학생/남학생의 수가 가장 많습니다.
부모의 교육 수준이 high school 인 경우를 제외하고, 여학생 수가 남학생 수보다 많습니다.

 

 

# 부모의 교육 수준과 전체 성적의 관계 시각화

sp_parent_total = sp.groupby("parental level of education")["total score"].mean().round(2)
sp_parent_total = sp_parent_total.sort_values(ascending = False)

fig = px.bar(x = sp_parent_total.index, y = sp_parent_total.values,
             color = sp_parent_total.index, text = sp_parent_total.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15,
    textfont_color = "black"
)

fig.update_layout(
    title = dict(
        text = "<b>부모의 교육 수준과 전체 성적의 관계</b>",
        font_size = 20
    ),
    
    xaxis = dict(title = "부모의 교육 수준"),
    yaxis = dict(title = "점수"),
    
    showlegend = False,
    template = "plotly_white"    
)

fig.show()

부모의 교육 수준이 master's degree 인 경우가 성적이 가장 높고 high school 인 경우 성적이 가장 낮지만 전반적으로 큰 차이가 나지 않습니다.

 

 

# 개별 성적 평균과 부모의 교육 수준 관계 시각화

fig = make_subplots(rows = 3, cols = 1)

fig.add_trace(
    go.Box(
        x = sp["parental level of education"],
        y = sp["math score"],
        marker_color = color[0],
        name = "Math"
    ),
    row = 1, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["parental level of education"],
        y = sp["reading score"],
        marker_color = color[1],
        name = "Reading"
    ),
    row = 2, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["parental level of education"],
        y = sp["writing score"],
        marker_color = color[2],
        name = "Writing"
    ),
    row = 3, col = 1
)

fig.update_xaxes(title = "부모의 교육 수준", row = 3, col = 1)
fig.update_yaxes(title = "Math score", row = 1, col = 1)
fig.update_yaxes(title = "Reading score", row = 2, col = 1)
fig.update_yaxes(title = "Writing score", row = 3, col = 1)

fig.update_layout(
    height = 1000,
    title = dict(
        text = "<b>개별 과목별 성적과 부모의 교육 수준의 관계</b>",
        font_size = 20
    )
)

fig.show()

math 의 경우 high school 이 조금 낮지만 전반적으로 크게 차이나지 않습니다.
reading 과 writing 의 경우 master's degree 인 경우 조금 높고 high school 인 경우 조금 낮지만 전반적으로 크게 차이나지 않습니다.

4-4 점심식사와 성적의 관계는? 

# 점심식사 시각화

sp_lunch = sp["lunch"].value_counts()

fig = px.pie(labels = sp_lunch.index, values = sp_lunch.values,
             names = sp_lunch.index)

fig.update_traces(
    textinfo = "label + percent + value",
    textfont_size = 15,
    textfont_color = "white"
),

fig.update_layout(
    title = dict(
        text = "<b>점심식사</b>",
        font_size = 20
    ),
    
    showlegend = False
)


fig.show()

급식을 하는 학생이 64.5% 로 더 많습니다.

 

 

# 점심식사별 성별 비율

sp_lunch_gender = sp.groupby(["lunch", "gender"]).agg({"race/ethnicity" : "count"}).reset_index()
sp_lunch_gender = sp_lunch_gender.rename(columns = {"race/ethnicity" : "count"})

fig = px.bar(sp_lunch_gender, x = "lunch", y = "count", color = "gender",
             barmode = "group", text = "count")

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>점심식사별 성별 비율</b>",
        font_size = 20
    ),
    
    xaxis = dict(title = "점심식사"),
    yaxis = dict(title = "학생 수"),
    
    template = "plotly_white"
)

fig.show()

점심식사 종류와 상관없이 여학생이 더 많지만 남학생과 차이가 크지 않다.

 

 

# 전체 성적 평균과 점심식사와의 관계 시각화

sp_lunch_total = sp.groupby("lunch")["total score"].mean().round(2)

fig = px.bar(x = sp_lunch_total.index, y = sp_lunch_total.values,
             color = sp_lunch_total.index, text = sp_lunch_total.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>전체 성적 평균과 점심식사의 관계</b>",
        font_size = 20
    ),
    
    xaxis = dict(
        title = "점심식사"
    ),
    
    yaxis = dict(
        title = "점수"
    ),
    
    legend_title_text = "점심식사",
    template = "plotly_white"
)

fig.show()

급식을 하는 경우가 하지 않는 경우보다 성적이 높습니다.

 

 

# 개별 성적 평균과 점심식사의 관계 시각화

fig = make_subplots(rows = 3, cols = 1)

fig.add_trace(
    go.Box(
        x = sp["lunch"],
        y = sp["math score"],
        marker_color = color[0],
        name = "Math"
    ),
    row = 1, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["lunch"],
        y = sp["reading score"],
        marker_color = color[1],
        name = "Reading"
    ),
    row = 2, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["lunch"],
        y = sp["writing score"],
        marker_color = color[2],
        name = "Writing"
    ),
    row = 3, col = 1
)

fig.update_xaxes(title = "점심식사", row = 3, col = 1)
fig.update_yaxes(title = "Math score", row = 1, col = 1)
fig.update_yaxes(title = "Reading score", row = 2, col = 1)
fig.update_yaxes(title = "Writing score", row = 3, col = 1)

fig.update_layout(
    height = 1000,
    title = dict(
        text = "<b>개별 과목별 성적과 점심식사의 관계</b>",
        font_size = 20
    )
)

fig.show()

모든 과목에서 급식을 하는 경우가 하지 않는 경우보다 성적이 더 높습니다.

4-5 시험 준비학습 여부와 성적의 관계는?

# 시험 준비학습 여부 시각화

sp_test = sp["test preparation course"].value_counts()

fig = px.pie(labels = sp_test.index, values = sp_test.values,
             names = sp_test.index)

fig.update_traces(
    textinfo = "label + percent + value",
    textfont_size = 15,
    textfont_color = "white"
),

fig.update_layout(
    title = dict(
        text = "<b>시험 준비학습 여부 비율</b>",
        font_size = 20
    ),
    
    showlegend = False
)


fig.show()

시험 준비학습을 하지 않은 학생이 64.2%로 학습을 한 학생보다 더 많습니다.

 

 

# 시험 준비학습 여부에 따른 성별 비율

sp_test_gender = sp.groupby(["test preparation course", "gender"]).agg({"lunch" : "count"}).reset_index()
sp_test_gender = sp_test_gender.rename(columns = {"lunch" : "count"})

fig = px.bar(sp_test_gender, x = "test preparation course", y = "count", color = "gender",
             barmode = "group", text = "count")

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>시험 준비학습 여부별 성별 비율</b>",
        font_size = 20
    ),
    
    xaxis = dict(title = "시험 준비학습 여부"),
    yaxis = dict(title = "학생 수"),
    
    template = "plotly_white"
)

fig.show()

시험 준비학습 여부에 상관없이 여학생의 수가 남학생 보다 더 많습니다.

 

 

# 전체 성적 평균과 시험 준비학습의 관계 시각화

sp_test_total = sp.groupby("test preparation course")["total score"].mean().round(2)

fig = px.bar(x = sp_test_total.index, y = sp_test_total.values,
             color = sp_test_total.index, text = sp_test_total.values)

fig.update_traces(
    textposition = "outside",
    textfont_size = 15
)

fig.update_layout(
    title = dict(
        text = "<b>전체 성적 평균과 시험 준비학습의 관계</b>",
        font_size = 20
    ),
    
    xaxis = dict(
        title = "시험 준비학습 여부"
    ),
    
    yaxis = dict(
        title = "점수"
    ),
    
    legend_title_text = "시험 준비학습",
    template = "plotly_white"
)

fig.show()

시험 준비학습을 한 경우가 하지 않은 경우보다 점수가 더 높습니다.

 

 

# 개별 성적 평균과 시험 준비학습의 관계 시각화

fig = make_subplots(rows = 3, cols = 1)

fig.add_trace(
    go.Box(
        x = sp["test preparation course"],
        y = sp["math score"],
        marker_color = color[0],
        name = "Math"
    ),
    row = 1, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["test preparation course"],
        y = sp["reading score"],
        marker_color = color[1],
        name = "Reading"
    ),
    row = 2, col = 1
)

fig.add_trace(
    go.Box(
        x = sp["test preparation course"],
        y = sp["writing score"],
        marker_color = color[2],
        name = "Writing"
    ),
    row = 3, col = 1
)

fig.update_xaxes(title = "시험 준비학습", row = 3, col = 1)
fig.update_yaxes(title = "Math score", row = 1, col = 1)
fig.update_yaxes(title = "Reading score", row = 2, col = 1)
fig.update_yaxes(title = "Writing score", row = 3, col = 1)

fig.update_layout(
    height = 1000,
    title = dict(
        text = "<b>개별 과목별 성적과 시험 준비학습의 관계</b>",
        font_size = 20
    )
)

fig.show()

모든 과목에서 시험 준비학습을 하는 경우가 하지 않는 경우보다 성적이 더 높습니다.

 4-6 각 시험 성적의 상관관계는?

f, ax = plt.subplots(2, 2, figsize = [18, 12])

sns.scatterplot(data = sp, x = "math score", y = "reading score", hue = "gender", ax = ax[0,0])
sns.scatterplot(data = sp, x = "math score", y = "writing score", hue = "gender", ax = ax[0,1])
sns.scatterplot(data = sp, x = "reading score", y = "writing score", hue = "gender", ax = ax[1,0])

ax[0,0].set_title("각 시험 성적 간 상관관계", size = 20) # 그래프 제목

plt.show()

개별 시험 성적은 성별에 상관없이 전체적으로 양의 상관관계를 나타내고 있습니다.

5. Review

1) 성별과 성적의 관계는?
   - 여학생 518명, 남학생 482명으로 여학생이 조금 더 많이 있습니다.  
   - 전체 성적의 경우 여학생이 남학생보다 조금 더 높습니다.
   - 수학은 남학생이 여학생보다 성적이 더 높지만 나머지 두 과목(Reading, Writing)은 여학생 성적이 더 높습니다.

2) 인종/민족과 성적의 관계는?
   - 인종/민족 비율은 group C 가 가장 많으며 group A 가 가장 적습니다.
   - group C 학생수가 가장 많습니다.
   - group B, group C 는 여학생이 남학생보다 많고 나머지 그룹(group A/group D/group E)은 남학생이 더 많습니다.
   - group E 가 전체 성적 평균이 가장 높고 group A 가 가장 낮으나 전체적으로 차이가 크게나지 않으며, 개별 성적도 모든 과목에서 group E 가 가장 높고 group A 가 가장 낮으나 전체 그룹간에 차이가 크게 나지 않습니다.

3) 부모의 교육 수준과 성적의 관계는?
   - 부모의 교육 수준이 some college 인 여학생/남학생의 수가 가장 많습니다.
   - 부모의 교육 수준이 high school 인 경우를 제외하고, 여학생 수가 남학생 수보다 많습니다.
   - 학사 수준 이상의 교육을 받은 비율이 약 62.5% 이며 나머지는 고등 교육까지 이수했습니다.
   - 부모의 교육 수준이 master's degree 인 경우가 성적이 가장 높고 high school 인 경우 성적이 가장 낮지만 전반적으로 큰 차이가 나지 않습니다.
   - math 의 경우 high school 이 조금 낮고, reading 과 writing 은 master's degree 인 경우 조금 높고 high school 인 경우 조금 낮지만 전반적으로 크게 차이나지 않습니다.

4) 점심식사 여부와 성적의 관계는? 
   - 급식을 하는 학생이 64.5% 로 더 많습니다.
   - 급식 여부와 상관없이 여학생이 더 많지만 남학생과 차이가 크지 않습니다.
   - 급식을 하는 경우가 하지 않는 경우보다 성적이 높고 모든 과목에서 급식을 하는 경우가 하지 않는 경우보다 성적이 더 높습니다.

5) 시험 준비학습 여부와 성적의 관계는?
   - 시험 준비학습을 하지 않은 학생이 64.2%로 학습을 한 학생보다 더 많습니다.
   - 시험 준비학습 여부에 상관없이 여학생의 수가 남학생 보다 더 많습니다.
   - 시험 준비학습을 한 경우가 하지 않은 경우보다 점수가 더 높고, 모든 과목에서 시험 준비학습을 하는 경우가 하지 않는 경우보다 성적이 더 높습니다.

6) 각 시험 성적의 상관관계는?
   - 각 시험 성적은 성별에 상관없이 전체적으로 양의 상관관계를 나타내고 있습니다.

728x90