01. 무한 반복 영어 단어 퀴즈 while문으로
어제 한 for문의 영어퀴즈에 이어서 오늘은 while 문을 통해 영어 퀴즈를 만드는 것이다.
이번 목표는 "stop"을 입력할 때까지 무한히 문제가 나오고, 매번 어떤 단어가 나올지 예측할 수 없도록 랜덤하게 출제되도록 만드는 것이다.
import random
# 영어 단어 퀴즈가 무한 반복으로 진행되고, 사용자가 stop 키워드를 입력해야지만 퀴즈가 종료되게 설계
words = {'꽃':'flower',"나비":'butterfly','학교':'school','자동차':'car'}
#딕셔너리의 키들만 따로 저장 (퀴즈 문제로 사용)
words_keys = list(words.keys())
print('***영어 단어 맞추기 퀴즈 시작***')
while True:
key = random.choice(words_keys) #random.choice
input_word = input('%s에 해당되는 영어 단어를 입력하세요' % key)
if input_word == 'stop':
print('퀴즈를 종료합니다.')
break
elif input_word == words[key]:
print('정답입니다.')
else:
print('오답입니다.')
print('***영어 단어 맞취기 퀴즈 끝***')
1) 딕셔너리에서 키 리스트를 확보.
- 딕셔너리 리스트와 달리 순서를 보장하지 않기 때문에 인덱스로 키를 꺼내 쓸 수 없다.
- 대신 딕셔너리가 제공하는 key() 메서드로 뷰 객체를 받은 뒤 list()로 감싸서 리스트로 변환 하여야 한다.
2) 무한 반복문과 random.choice
- 먼저 random은 파이썬 표준 라이브러리에 포함되지 않아. import random이 필요하다.
- random.choice()은 인자로 받은 시퀀스에서 하나의 요소를 무작위로 반환한다.
- while True 는 조건 없이 진입 하는 무한 루프로서 종료 조건이 필요하다.
- 'stop'을 입력 받으면 break로 탈줄한다.
02. csv 파일에 대한 이해와 NOtePad++ 편집기
1) CSV가 데이터 분석의 기본 포맷인 이유
- CSV(Comma Separated Values)는 쉼표(
,)로 필드를 구분한 순수 텍스트 파일이다. - 셀 파일과 대비되는 세 가지 장점
- (1) 엑셀 파일은 별도의 소프트웨어(유료)가 설치되어야 열리지만 CSV는 메모장으로도 열린다.
- (2) 엑셀은 대략 1만 행을 넘어가면 열기 자체가 어려워지지만 CSV는 대용량에서도 안정적이다.
- (3) 학습 데이터셋과 공공 데이터는 대부분 CSV 형식으로 배포된다.
우리나라 공공 데이터 포털과 기상자료개방포털도 기본으로 CSV를 제공하며, 편의를 위해 XLSX도 병행 배포하는 경우가 많다. 다만 데이터 원본 이해라는 관점에서는 CSV를 다루는 능력이 더 근본적이다.
2) 인코딩과 한글 깨짐 이슈
- CSV 파일의 가장 큰 함정은 인코딩이다. 파이썬의 기본 인코딩은 UTF-8이지만, 국내 공공기관이 배포하는 CSV는 대부분 EUC-KR로 저장되어 있다. UTF-8은 한글 한 글자를 3바이트로 표현하는 유니코드 기반 인코딩이고, EUC-KR은 한국어에 특화된 완성형 인코딩이다. 인코딩이 어긋나면 파일을 열 때 한글이 깨지거나 아예 오류가 발생한다.
3) Notepad++로 원본 확인하기
- 원본 데이터는 무엇보다 눈으로 먼저 확인해야 한다는 것이 교수님께서 여러 번 강조하였다.
- 원본 데이터를 볼 때 확인 해야 할 포인트
- 파일의 총 행 수를 확인
- 화면 하단에 표시된 인코딩을 확인
- 컬럼 구분자가 실제로 쉼표인지, 앞뒤에 불필요한 공백이나 탭이 섞여 있지 않은지 확인
- 위에 사항을 잘 확인하고 삭제한 뒤 저장할 필요가 있다. csv.reader로 스캔할 때 헤더 위에 잔여 텍스트가 있으면 파싱이 어긋날 수 있다.
4) 서울 데이터셋의 구조

03. csv 읽기
import csv
# 1) 파일을 연다.
f = open('/content/seoul (1).csv', 'r', encoding='euc-kr')
# 2) 파일을 읽는다.
data = csv.reader(f, delimiter=',')
print(data)
# 3) 파일 내용을 출력
for row in data:
print(row)
# 4) 파일 닫기
f.close()
1) 파일은 f = open('/content/seoul (1).csv', 'r', encoding='euc-kr')이와 같은 방식으로 열어서 확인할 수 있다.
2) csv.reader(f, delimiter=',')csv.reader에 전달하면 행 단위로 순회 가능한 이터레이터 객체가 만들어진다.csv.reader의 delimiter=','는 구분자를 명시하는 옵션이다.for row in data로 순회한 결과, 각 행은 리스트로 반환되었다
- 예시
- 주목할 점은 작은 따옴표로 감싸진 문자열이다. csv.reader는 파일의 값을 자동으로 형변환하지 않는 것을 알 수 있다.
- 마지막엔 f.close() 파일을 닫아준다.
['1907-10-01', '108', '13.5', '7.9', '20.7']
04. 헤더 저장
1) next( )로 헤더 한 줄 분리
next(iterator)는 이터레이터에서 다음 요소 하나를 꺼내고 커서를 그다음 위치로 이동시키는 내장 함수이다.
# 헤더 저장 - next()가 한 줄 읽고 커서를 다음으로 넘김
header = next(data)
f.close()
print(header)
- 출력은
['날짜', '지점', '평균기온(℃)', '최저기온(℃)', '최고기온(℃)']이다.next()는 어제 배운 리스트의pop()과 유사한 감각으로 이해할 수 있다.pop이 원본 리스트에서 요소를 잘라내는 반면next는 원본을 그대로 두면서 커서만 앞으로 이동시킨다는 점이 다르다. - 2) 헤더 분리 없이 데이터 처리를 시도하면 어떻게 될까?*
- 만약 헤더를 분리하지 않고 곧바로 최고 기온을
float(row[4])로 형변환하면 첫 번째 반복에서'최고기온(℃)'문자열을 실수로 바꾸려다 ValueError가 발생한다. 원본을 훼손하지 않으면서 컬럼명 라인만 건너뛰는 정석 방법이next()`이다.
05. 기온 출력과 결측치 처리
1) 결측치 처리에 대한 전략
- 전략1. 극단값 대체
for row in data: if row[4] == '': # 결측치 확인 print(row[0]) # 결측치가 발생한 날짜 확인 row[4] = -999 # 극단값 대체 print(row[0], float(row[-1]))- 절략2.
continue로 건너뛰기 # 날짜와 최저기온 출력 for row in data: if row[3] == '': continue print(row[0], float(row[3]))# 날짜와 평균기온 출력 for row in data: if row[2] == '': continue # 결측치면 다음 반복으로 print(row[0], float(row[2]))
06. matplotlib 기본 그래프
라이브러리리 임포트와 별칭
import matplotlib.pyplot as plt
시각화의 사실상 표준 라이브러리는 matplotlib이며, 그중 pyplot 서브패키지가 상태 기반의 간편 API를 제공한다. 관례상 plt라는 별칭을 사용한다.
y값만 준 plot() 호출
plt.plot(y)처럼 리스트 하나만 인자로 넘기면 그 리스트를 y값으로 인식하고 x값은 0부터 자동으로 1씩 증가시키며 선을 그린다.
import matplotlib.pyplot as plt
plt.plot([20, 10, 50, 10, 30]) # y값만 주면 x는 자동으로 0부터 1씩 증가
plt.show()
y값만 준 plot() 호출
x와 y를 명시적으로 지정하려면 두 개의 리스트를 순서대로 전달한다.
import matplotlib.pyplot as plt
plt.plot([100, 200, 300, 400, 500], [10, 20, 30, 40, 50]) # x, y 순서
plt.show()
타이틀 속성 추가
차트에는 반드시 타이틀을 부여한다는 원칙이 있다. 타이틀·x축 라벨·y축 라벨·범례가 없는 차트는 정보 전달에 실패한 차트이다.
plt.title('plotting')
plt.plot([100, 200, 300, 400, 500], [10, 20, 30, 40, 50])
plt.show()



07. 서울 기온 데이터 시각화
import csv
import matplotlib.pyplot as plt
# 1) 파일을 연다.
f = open('/content/seoul (1).csv', 'r', encoding='euc-kr')
# 2) 파일을 읽는다.
data = csv.reader(f, delimiter=',')
# 3) 헤더 저장
header = next(data)
# 4) 최고 기온을 담을 리스트 변수 선언
result = []
# 5) 결측치를 제외한 최고 기온 데이터만 result 리스트에 담기
for row in data:
if row[4] != '':
result.append(float(row[-1]))
# 6) 파일 닫기
f.close()
# 7) 차트 그리기
plt.title('seoul')
plt.plot(result, 'r')
plt.show()

08. 한글 깨짐 해결 - koreanize-matplotlib
matplotlib은 기본 폰트로 한글을 지원하지 않는다. plt.title('서울 최고 기온')을 그대로 실행하면 한글이 네모 박스(□□□)로 표시된다. Google Colab 환경에는 한글 폰트가 설치되어 있지 않기 때문이다.
koreanize-matplotlib 설치와 임포트
가장 간편한 해결책은 koreanize-matplotlib 패키지를 설치하고 임포트하는 것이다. pip 명령어로 설치할 수 있다.
!pip install koreanize-matplotlib
09. 문자열 슬라이싱으로 월별 데이터 추출
1) 날짜 문자열의 구조
날짜 컬럼은 YYYY-MM-DD 포맷의 문자열이다. 예를 들어 '1907-10-01'은 10자리 문자열이며 각 위치는 다음과 같이 대응된다.
| 인덱스 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| 문자 | 1 | 9 | 0 | 7 | - | 1 | 0 | - | 0 | 1 |
파이썬 문자열 슬라이싱 s[start:end]는 start 이상 end 미만 구간을 반환한다. 이 성질을 이용해 연도, 월, 일을 각각 추출할 수 있다.
date = '1907-10-01'
print(date[0:4]) # '1907' - 연도
print(date[5:7]) # '10' - 월
print(date[8:]) # '01' - 일
10. 팀 프로젝트
한국의 철베리아라고 불리는 철원의 여름철 기온 변화보면서 지구온난화의 영향이 얼마나 유의미하게 나타나는지 알아보았다.
import csv
import matplotlib.pyplot as plt
import koreanize_matplotlib
f = open('/content/Cheorwon.csv', 'r', encoding='euc-kr')
data = csv.reader(f, delimiter=',')
header = next(data)
# 연도별 7월-8월 평균 기온을 저장할 딕셔너리
yearly_jul_aug_temps = {}
for row in data:
try:
date_str = row[0]
year = int(date_str[0:4])
month = int(date_str[5:7])
avg_temp = float(row[2])
if month in [7, 8]:
if year not in yearly_jul_aug_temps:
yearly_jul_aug_temps[year] = []
yearly_jul_aug_temps[year].append(avg_temp)
except (ValueError, IndexError):
continue
f.close()
# 각 연도별 7-8월 평균 기온 계산
years = sorted(yearly_jul_aug_temps.keys())
avg_summer_temps = [sum(yearly_jul_aug_temps[year]) / len(yearly_jul_aug_temps[year])
for year in years if len(yearly_jul_aug_temps[year]) > 0]
filtered_years = [year for year in years if len(yearly_jul_aug_temps[year]) > 0]
plt.figure(figsize=(14, 7))
plt.plot(filtered_years, avg_summer_temps, marker='o',
linestyle='-', color='blue', markersize=4)
plt.title('철원 7-8월 평균 기온 변화 (1907-현재)', fontsize=16)
plt.xlabel('년도', fontsize=12)
plt.ylabel('평균 기온 (℃)', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.xticks(filtered_years, rotation=45, ha='right', fontsize=10)
plt.yticks(fontsize=10)
plt.tight_layout()
plt.show()
print(f"데이터 범위: {min(filtered_years)}년부터 {max(filtered_years)}년까지")

코드는 claude의 도움을 살짝 받긴 했다.
지구온난화가 본격적으로 시작하기 시점인 20세기 후반 21세기 초 상승하는 시점과 철원의 7~8월의 평균 기온도 엇비슷하게 상승하고 있다는 것을 볼 수 있다.
'MLOps엔지니어' 카테고리의 다른 글
| ABC 부트캠프 AI파일럿 1기 MLOps 6일차_탐색적 데이터 분석(EDA) 실습 (0) | 2026.08.04 |
|---|---|
| ABC 부트캠프 AI파일럿 1기 MLOps 5일차_주민등록 인구통계 CSV 전처리와 plotly 시각화 (0) | 2026.08.02 |
| ABC 부트캠프 AI파일럿 1기 MLOps 4일차_NumPy 배열 연산과 pandas 데이터 파악하기 (0) | 2026.08.02 |
| ABC 부트캠프 AI파일럿 1기 MLOps 2일차_ 데이터 분석을 위한 파이썬 기초 (1) | 2026.07.26 |
| ABC 부트캠프 AI파일럿 1기 MLOps 1일차 (0) | 2026.07.26 |