20장. 교육 콘텐츠 설계와 종합 실습
실습 1 — 수업 계획표 만들기
학습목표, 행동 동사, 확인 방법, 시간을 한 표에 적은 수업 계획표를 pandas 로 만듭니다. 목표 문장을 프로그램으로 점검하고, 시간 배분을 그래프로 본 뒤 out_ch20_plan.csv 로 저장합니다.
1단계. 계획표 만들기
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Malgun Gothic"
plt.rcParams["axes.unicode_minus"] = False
# 한 차시(필터 수업)의 활동을 줄마다 적는다. 시간은 분
plan = pd.DataFrame([
{"활동": "도입", "학습목표": "노이즈 낀 그림과 깨끗한 그림의 차이를 PSNR 로 견줄 수 있다",
"확인 방법": "PSNR 두 값을 찍은 출력", "시간": 10},
{"활동": "실습 1", "학습목표": "Median 필터로 잡티를 지워 PSNR 을 3dB 이상 올릴 수 있다",
"확인 방법": "전후 PSNR 차이", "시간": 20},
{"활동": "실습 2", "학습목표": "필터 세 가지를 같은 그림에 걸어 결과를 표로 견줄 수 있다",
"확인 방법": "필터별 PSNR 표", "시간": 25},
{"활동": "실습 3", "학습목표": "필터를 이해한다",
"확인 방법": "", "시간": 15},
{"활동": "정리", "학습목표": "전후 비교 격자를 만들어 저장할 수 있다",
"확인 방법": "저장된 out_ 그림", "시간": 10},
])
print(plan[["활동", "시간"]].to_string(index=False))
print("총 시간:", int(plan["시간"].sum()), "분") 활동 시간
도입 10
실습 1 20
실습 2 25
실습 3 15
정리 10
총 시간: 80 분2단계. 학습목표 문장 점검하기
VERBS = ["견줄", "올릴", "만들어", "찾을", "셀", "고칠", "저장할"] # 이 계획표에서 쓰는 행동 동사
VAGUE = ["이해", "안다", "익힌다"] # 덜 알맞은 말
def review(row):
"""학습목표 한 줄을 점검해 고칠 점을 글자로 돌려준다. 문제가 없으면 '통과'."""
goal = row["학습목표"]
notes = []
if not goal.endswith("수 있다"):
notes.append("'~할 수 있다'로 끝내기")
if any(word in goal for word in VAGUE):
notes.append("행동 동사로 바꾸기")
if not any(verb in goal for verb in VERBS):
notes.append("행동 동사 넣기")
if not row["확인 방법"]:
notes.append("확인 방법 적기")
return "통과" if not notes else ", ".join(notes)
# apply(함수, axis=1): 표의 줄마다 함수를 불러 결과를 새 칸에 담는다
plan["점검"] = plan.apply(review, axis=1)
print(plan[["활동", "점검"]].to_string(index=False)) 활동 점검
도입 통과
실습 1 통과
실습 2 통과
실습 3 '~할 수 있다'로 끝내기, 행동 동사로 바꾸기, 행동 동사 넣기, 확인 방법 적기
정리 통과3단계. 고치고 시간 배분 보기
# 점검에 걸린 줄을 고쳐 적는다
plan.loc[plan["활동"] == "실습 3", "학습목표"] = "윤곽선으로 잡티를 지운 그림의 부품 수를 셀 수 있다"
plan.loc[plan["활동"] == "실습 3", "확인 방법"] = "정답 개수와 같은지"
plan["점검"] = plan.apply(review, axis=1)
print("통과한 줄:", int((plan["점검"] == "통과").sum()), "/", len(plan))
# 활동마다 시간을 가로 막대로 그린다. barh = bar horizontal(가로 막대)
fig, ax = plt.subplots(figsize=(7, 3))
ax.barh(plan["활동"], plan["시간"])
ax.invert_yaxis() # 위에서부터 수업 순서대로 보이게 뒤집는다
ax.set_xlabel("시간(분)")
ax.set_title(f"한 차시 {int(plan['시간'].sum())}분의 시간 배분")
plt.tight_layout()
plt.show()통과한 줄: 5 / 5
4단계. 저장하고 다시 읽어 확인하기
# utf-8-sig: 엑셀에서 열어도 한글이 깨지지 않게 맨 앞에 표시(BOM)를 붙여 저장한다
plan.to_csv("out_ch20_plan.csv", index=False, encoding="utf-8-sig")
back = pd.read_csv("out_ch20_plan.csv", encoding="utf-8-sig")
print("저장한 줄과 칸:", back.shape)
print("칸 이름:", list(back.columns))
print("실습 비중:", round(float(back.loc[back["활동"].str.startswith("실습"), "시간"].sum() / back["시간"].sum()), 3))저장한 줄과 칸: (5, 5)
칸 이름: ['활동', '학습목표', '확인 방법', '시간', '점검']
실습 비중: 0.75코드 설명
pd.DataFrame([{...}, {...}])은 사전 하나를 한 줄로 삼아 표를 만듭니다. 계획표의 칸(활동, 학습목표, 확인 방법, 시간)이 사전의 키입니다.plan.apply(review, axis=1)은 줄마다review함수를 부릅니다.axis=1은 "줄 방향으로 하나씩"이라는 뜻입니다. 학습목표 점검을 사람이 아니라 함수가 하므로, 계획표가 길어져도 같은 기준으로 봅니다.plan.loc[조건, "칸"] = 값은 조건에 맞는 줄의 그 칸만 고칩니다. loc 은 location(자리)의 줄임입니다.ax.barh는 가로 막대,ax.invert_yaxis()는 위아래를 뒤집어 첫 활동이 맨 위에 오게 합니다.encoding="utf-8-sig"로 저장하면 엑셀에서 열어도 한글이 깨지지 않습니다. 17장의mistakes.csv도 이 방식입니다.