단원 홈

Ⅱ. 데이터 준비와 분석4차시

빈칸은 모두
같은 빈칸일까

결측의 뜻을 읽고, 채우는 방법을 채점한다

3차시 신상명세서에 적은 ‘일강수량 빈칸 206일’. 그 빈칸을 빼고 평균을 내면 pandas 는 하루 8.20mm라고 답합니다. 그런데 같은 파일에는 0.0으로 적힌 날이 50일 더 있어요. 빈칸과 0.0은 같은 뜻일까요? 그리고 빈칸을 채웠다면, 그 채우기가 잘한 채우기인지는 무엇으로 압니까?

  • [12데과02-02]
  • 50분네 정거장
  • 새 도구scikit-learn
  • 자료ASOS 서울 2024 366일 · 따릉이 표본 2,000행
Ⅱ 단원 지도4 / 14차시
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14

학습 목표

  1. 개념에서

    빈칸의 세 얼굴(진짜 결측 · 구조적 빈칸 · 숨은 결측)을 가르고, 그 뜻을 같은 파일의 다른 열로 확인할 수 있다.

  2. 손으로

    정답을 아는 칸을 일부러 지워 채우는 방법 넷을 채점하고, 같은 채우기를 scikit-learn SimpleImputer로 다시 할 수 있다.

  3. 확인에서

    빈칸을 어떻게 다뤘는지와 그 까닭을 분모와 함께 보고서에 적을 수 있다.

1
여는 장면 · 5분

7월의 비 — 다섯 칸이 비어 있고, 네 칸에는 0.0이 적혀 있다

3차시에서 우리는 파일을 받자마자 신상명세서를 썼습니다. 거기 ‘빈칸’ 칸에 적은 숫자가 일강수량 206일이었어요. 그 206일은 어떤 날들일까요? 한 해를 다 펼치면 눈이 어지러우니 7월 한 달, 31칸만 꺼내 봅니다.

아래 그림에서 물음표가 든 회색 칸이 빈칸입니다 — 1 · 11 · 12 · 30 · 31일, 모두 다섯 칸. 바닥에 주황 테만 있는 납작한 칸은 값이 0.0으로 적힌 날입니다 — 13 · 15 · 28 · 29일, 네 칸. 나머지 스물두 칸에는 0보다 큰 값이 있고, 가장 많이 내린 18일은 128.8mm입니다.

그림 12024년 7월, 서울의 일강수량 31칸청록 막대 = 잰 비 · 주황 테 칸 = 0.0 · 물음표 칸 = 빈칸
7월 1 ~ 16일일강수량(mm)032.56597.5130???151015날짜65.17월 17 ~ 31일일강수량(mm)032.56597.5130??17202530날짜128.87월 1 ~ 16일일강수량(mm)032.56597.5130???151015날짜65.17월 17 ~ 31일일강수량(mm)032.56597.5130??17202530날짜128.8

빈칸 5칸 · 0.0 4칸 · 0보다 큰 값 22칸. 한 달 31칸 안에 ‘비어 있음’과 ‘0.0’이 함께 들어 있습니다. 자료: 기상청 종관기상관측(ASOS) 서울(108) 2024년 일자료 — ../data/asos_seoul_2024.csv의 7월 31행(원장 계산)

먼저 예측

파일을 만든 사람이 손을 놓친 것이 아니라면, 두 표기에는 서로 다른 뜻이 있을 것입니다. 빈칸과 0.0 가운데 어느 쪽이 ‘비가 오지 않은 날’일까요? 그리고 그 답을 확인하려면 이 파일의 어느 열을 열어 보면 될까요? 한 문장으로 적어 보세요.

3정거장 실험실에서 [0판 · 빈 날의 비]를 고르면 이 31칸을 큰 화면으로 펼쳐, 칸을 하나씩 톡 쳐 가며 반 전체가 함께 확인할 수 있습니다.

체크포인트 1

7월 31칸에 두 가지 ‘없어 보이는 값’(빈칸 5 · 0.0 4)이 함께 있다는 것을 보았고, 어느 쪽이 ‘비가 오지 않은 날’인지 예측해 적었다.

다음 정거장 · 개념 15분 →
2
개념 · 15분

빈칸의 뜻은 대개 같은 파일 안에 적혀 있다

2-1봉투를 열면 — 같은 날의 ‘강수 계속시간’이 증언한다

이 파일에는 일강수량 옆에 강수 계속시간(hr)이라는 열이 하나 더 있습니다. ‘그날 비가 몇 시간 내렸는가’예요. 같은 31칸을 이번에는 그 열로 그려 봅니다 — 빈칸과 0.0이 같은 뜻이라면 이 열에서도 똑같이 생겼어야 합니다.

그림 2같은 31칸을 ‘강수 계속시간’으로 다시 그리면그림 1과 같은 날짜 · 같은 순서
7월 1 ~ 16일강수 계속시간(hr)05101520???151015날짜0.50.177월 17 ~ 31일강수 계속시간(hr)05101520??17202530날짜0.335.57월 1 ~ 16일강수 계속시간(hr)05101520???151015날짜0.50.177월 17 ~ 31일강수 계속시간(hr)05101520??17202530날짜0.335.5

빈칸이던 다섯 칸(1 · 11 · 12 · 30 · 31일)은 이 열에서도 빈칸입니다 — 잴 비가 아예 없었던 것이죠. 그런데 0.0이던 네 칸은 0.5 · 0.17 · 0.33 · 5.5시간으로 모두 0보다 큽니다. 29일에는 다섯 시간 반이나 비가 내렸는데 일강수량은 0.0으로 적혔어요. 자료: 같은 파일의 강수 계속시간(hr) 열 7월 31행(원장 계산)

한 해 전체도 같습니다. 일강수량이 빈칸인 206일은 강수 계속시간도 206일 모두 빈칸이고, 0.0인 50일은 강수 계속시간이 50일 모두 0보다 큽니다(0.13시간 ~ 5.5시간). 우연이라기에는 한 칸도 어긋나지 않아요.

그러니 이 파일에서 두 표기의 뜻은 이렇게 읽힙니다.

읽은 것빈칸 = 비(눈)가 아예 없었다(그래서 잴 것이 없었다) · 0.0 = 내리기는 했는데 0.1mm에 못 미쳤다. 기상청은 일강수량이 0.1mm 이상인 날만 ‘강수일수’로 셉니다.

여기서 조심할 것이 있습니다. 위 문장은 포털이 어딘가에 적어 둔 공식 설명이 아니라, 우리가 같은 파일 안에서 대조해 읽어 낸 것입니다. 설명서가 있으면 설명서가 먼저이고, 없으면 이렇게 다른 열에 물어보는 것이 다음 방법이에요. 그리고 읽어 낸 근거는 보고서에 함께 적습니다.

2-2빈칸의 세 얼굴 — 그리고 빈칸처럼 보이지 않는 빈칸

빈칸이라고 다 같은 빈칸이 아닙니다. 데이터에서 만나는 ‘없음’은 크게 셋으로 갈립니다. 어느 얼굴인지에 따라 해야 할 일이 다릅니다.

표 1빈칸의 세 얼굴오른쪽 끝은 이 파일에서 실제로 만난 자리
얼굴왜 비었나해야 할 일이 수업에서 만난 자리
진짜 결측 재려 했는데 못 쟀다 채우거나, 빈칸으로 두고 ‘○일 빠짐’을 적는다 풍속 3일 · 일조 3일(코드 ⑤)
구조적 빈칸 잴 일이 없었다 뜻에 맞는 값(대개 0)을 넣되 넣었다는 표시를 남긴다 일강수량 206일(코드 ①)
숨은 결측 ‘없음’ 자리에 글자나 숫자가 들어갔다 값의 목록부터 본 뒤 빈칸으로 바꿔 센다 따릉이 성별 \N 494행(코드 ②)

Ⅰ-8 에서 가져옴마우나로아 이산화탄소 자료에서 -99.99를 찾아 걷어 냈던 일이 바로 숨은 결측입니다. 그때는 숫자였고, 이번에는 글자예요 — 같은 얼굴의 다른 옷입니다.

따릉이 대여이력 표본 2,000행을 열어 성별 칸에 어떤 값들이 들어 있는지 세어 보면 이렇습니다 — M 877 · F 578 · \N 494 · 진짜 빈 칸 51. \N은 데이터베이스가 ‘값 없음’을 파일로 내보낼 때 자주 쓰는 글자입니다.

그런데 pandas 에게 isna()로 빈칸을 세어 달라고 하면 51행이라고 답합니다. \N은 글자이지 빈칸이 아니니까요. 성별을 정말 모르는 기록은 545행, 전체의 27.3%인데 말입니다.

2-3도구는 빈칸을 조용히 건너뛴다

pandas 의 .mean()은 빈칸을 빼고 평균을 냅니다. 오류도, 경고도 내지 않아요. 그래서 같은 한 줄이 서로 다른 질문에 답하고, 우리는 그 사실을 모른 채 답만 받아 옵니다. 같아야 할 것 같은 두 숫자가 다를 때가 그 신호입니다.

강수량 · 같은 .mean() 한 줄
8.20빈칸 그대로(분모 160)
vs
3.580으로 채우고(분모 366)
빈칸 빼고8.200 으로 채워3.58

앞의 것은 ‘비가 내린 날 하루 평균’, 뒤의 것은 ‘1년 하루 평균’ — 이름이 다르다.

따릉이 성별 · 같은 ‘빈칸’
51isna()가 센 행
인데
545정말 모르는 행
isna() 가 센 것51정말 모르는 것545

글자로 적힌 빈칸 494행은 값으로 세어졌다 — 2,000행의 27.3%.

연 강수량 · 같은 파일 같은 열
1,311빈칸을 0으로(mm)
vs
3,000빈칸을 평균으로(mm)
빈칸을 0 으로1,311빈칸을 평균으로3,000

비 안 온 206일에 8.2mm씩 ‘내리게’ 하면 2.3배가 된다(코드 ④).

7월 평균기온 · 같은 366일
26.60정답(°C)
→
23.4614칸을 (a)로 채우면
(a) 로 채운 7일7월 기온 — 청록이 정답

한여름 한가운데에 1년 평균 14.72°C가 일곱 칸 끼어들었다.

자료: 위 네 쌍의 숫자는 모두 3정거장 코드 ① · ② · ③ · ④가 찍는 값이다(ASOS 서울 2024 · 따릉이 표본 2,000행).

규칙평균 · 합계 · 비율을 보고할 때는 분모와 빈칸을 어떻게 다뤘는지를 함께 적는다. “하루 평균 8.2mm”가 아니라 “비가 내린 160일의 하루 평균 8.2mm(빈칸 206일 제외)”.

2-4채웠다면 — 채점할 수 있다

빈칸을 채우는 방법은 많습니다. 날짜 순서가 있는 자료라면 흔히 넷을 씁니다 — (a) 1년 평균 한 값으로 모두 · (b) 그 달 평균 · (c) 전날 값 그대로 · (d) 앞뒤를 잇는 직선(선형 보간).

어느 것이 좋을까요? 말로 고르면 끝이 없습니다. 그래서 정답을 아는 칸을 일부러 지워 봅니다 — 성한 날짜 몇 개를 골라 값을 감추고, 네 방법으로 채운 뒤, 감춰 둔 정답과 얼마나 다른지 잽니다. 이것을 마스킹 검증이라 하고, 그 차이의 절댓값 평균을 평균 절대 오차라고 부릅니다.

옆 그림은 7월 한가운데 일곱 칸을 지운 뒤 (a)와 (d)가 채운 모양입니다. (a)는 한여름에 수평으로 푹 꺼지고, (d)는 앞뒤 값을 곧게 잇습니다. 여기서는 (d)가 훨씬 가깝지요 — 그런데 그것이 ‘(d)가 더 좋은 방법’이라는 뜻일까요? 3정거장 실험실이 이 물음을 뒤집습니다.

규칙채우기를 보고할 때는 방법 이름만이 아니라 어디를 지워 채점했는지를 함께 적는다. 채점표는 시험지에 딸린 성적이다.

7월 8~23일지운 7칸
지운 7칸(a) 주황 점선 · (d) 청록 · 점은 남은 날
(a) 1년 평균 → 오차 11.87(d) 직선 보간 → 오차 0.79

자료: 코드 ③의 시험지(7월 15~21일 + 흩어진 7칸) 채점표

빈칸을 만나면 묻는 네 가지 — 차례대로

  1. 몇 칸몇 개가 비었나 — 그리고 빈칸처럼 보이지 않는 빈칸은 없나(값의 목록부터)
  2. 무슨 뜻못 쟀나, 잴 일이 없었나 — 설명서 먼저, 없으면 같은 파일의 다른 열
  3. 어떻게뜻에 맞는 방법을 골라 채운다 — 순서가 있는 자료라면 이웃한 날을 쓸 수 있다
  4. 흔들림정답을 아는 칸을 지워 채점하고, 채우기 전후로 결론이 바뀌는지 본다

넷째가 이 차시의 새로운 점입니다. 채우기는 ‘했다/안 했다’가 아니라 ‘재어 본 것/안 재어 본 것’으로 갈립니다.

체크포인트 2

빈칸의 세 얼굴을 가를 수 있고, 도구가 빈칸을 조용히 건너뛴다는 것을 숫자 넷으로 보았고, 채우기를 채점하는 방법(마스킹 검증)을 알게 되었다.

다음 정거장 · 손으로 20분 →
3
손으로 · 20분

빈칸의 뜻을 읽고, 채우기를 채점한다

오늘의 장비

scikit-learn — 이 책에서 처음 부르는 기계학습 도구 상자

여기서는 빈칸 채우기 한 가지만 씁니다(SimpleImputer). 손으로 한 채우기를 도구로 다시 해 보고, 도구가 무엇을 대신해 주고 무엇을 모르는지 가르는 것이 목적이에요. 처음 실행은 몇 초 멈춥니다 — 고장이 아니라 scikit-learn 을 처음 받는 중입니다(쪽마다 한 번).

부르는 모양

from sklearn.impute import SimpleImputer

imp = SimpleImputer(strategy="mean")
채운표 = imp.fit_transform(표)
imp.statistics_   # fit 이 기억한 값

오늘 쓰는 것 넷

SimpleImputer
빈칸 채우기 — strategy로 방법을 고른다
fit
채울 값을 기억한다(열마다 하나)
transform
기억한 값으로 빈칸을 메운다
statistics_
기억한 값을 꺼내 본다 — 사람이 확인하는 자리

pandas 와 다른 셋

  1. 기억했다가 다시 쓴다fit이 기억한 값을 다른 표에도 그대로 쓸 수 있다(Ⅱ-8·Ⅲ에서 다시 나온다)
  2. 표를 받는다한 줄(Series)이 아니라 열이 있는 표를 받는다 — to_frame()
  3. 전략이 넷뿐mean · median · most_frequent · constant — 날짜 순서를 쓰는 방법이 없다

대가 — 도구는 빈칸의 뜻을 모릅니다. 강수량에 mean을 걸면 비 안 온 206일에 8.2mm씩 ‘내리게’ 합니다.

1

빈칸과 0.0 — 366일 전체에서 확인한다

3분

여는 장면에 적어 둔 내 예측입니다. 7월 31칸에서 본 것이 한 해 366일에서도 그대로일까요? 그리고 빈칸을 뜻대로 0으로 채우면 평균과 합계는 각각 어떻게 될까요 — 둘 다 바뀔까요?

기본 빈칸 ①에 ‘값이 비었는지 묻는’ 함수 이름을, 빈칸 ②에 ‘빈칸을 정한 값으로 메우는’ 함수 이름을 채우고 ▶ 실행합니다. 채우지 않고 실행하면 어디를 채워야 하는지 안내가 뜹니다.

도전 마지막 두 줄의 .mean()을 .median()으로 바꿔 보세요. 1.10과 0.00이 나옵니다 — 0으로 채우면 중앙값이 0이 되는 까닭을 366일 가운데 ‘0인 날’ 수로 설명해 보세요.

탐구 만약 강수 계속시간 열이 없었다면, 빈칸과 0.0의 뜻을 무엇으로 가렸을까요? 이 파일 안에서 쓸 수 있는 다른 단서를 하나 찾아 적어 보세요.

“올해 서울의 하루 평균 강수량은 8.2mm”라는 문장은 . 이 숫자의 분모는 이고, 366일로 나눈 값은 이기 때문이다. 그래서 고쳐 쓰면 .

확인 문제 2에 적어 제출 →
2

숨은 빈칸 — 빈칸처럼 보이지 않는 빈칸

2분

따릉이 대여이력 표본 2,000행의 ‘성별’ 칸입니다. 몇 행이 비어 있을 것 같나요? 그리고 pandas 의 isna()는 그 가운데 몇 개를 빈칸으로 셀까요? 두 숫자를 각각 짐작해 두세요.

기본 먼저 value_counts(dropna=False)가 찍는 값의 목록을 보세요. 거기 보이는 글자를 빈칸 ③에 그대로 적어 넣고 ▶ 실행합니다(따옴표 안에 넣습니다).

도전 read_csv에 na_values=["\N"]를 더해 다시 읽으면 pandas 가 둘 다 빈칸으로 셉니다 — isna()가 몇 행이 될지 먼저 말하고 확인하세요.

탐구 \N 말고도 ‘없음’ 노릇을 하는 표기(- · . · NA · 9999 · -99)를 이 파일의 다른 열에서 찾아보세요 — 생년 열부터 보면 좋습니다.

“이용자의 %가 여성”이라고 쓰려면 분모가 인지 인지 먼저 정해야 한다. 그래서 보고서에는 비율과 함께 를 적는다.

확인 문제 1에 적어 제출 →
3

출제자가 되어 본다 — 지울 날을 내가 고른다

6분

2-4 에서 7월 한가운데를 지웠을 때는 (d) 직선 보간이 이겼고 (a) 1년 평균은 꼴찌였습니다. 그렇다면 (a)가 1등이 되는 14칸 시험지가 이 366일 안에 있을까요, 없을까요? 실험실에서 예측 칩을 잠그기 전에 있다 / 없다를 먼저 정하세요.

실험실 시험지란 채점하려고 일부러 지운 14칸입니다 — 정답을 아는 칸을 지워야 채점할 수 있으니까요. 확대 창에서 날 기둥을 톡 쳐 14칸을 지우고, 1등이 될 방법 칩을 하나 잠근 뒤 [채점하기]를 켭니다. 도전 셋을 풀면 카드가 스스로 닫힙니다.

시뮬레이터

출제자의 가위

이 채점은 방법을 재는가, 빈자리를 재는가 — 시험지를 바꿔 순위를 뒤집어 본다

  1. 1확대 창에서 날 기둥을 톡 쳐 14칸을 지운다
  2. 21등이 될 방법 칩을 골라 예측을 잠근다
  3. 3[채점하기]를 켜고 점수판을 본다
자료
시험지 — 지운 14칸
확대 창
1등 예측 칩 — 고르면 예측이 잠긴다
공정한 시험지 — 200장을 한꺼번에
출제자의 가위 · 2024년 서울 기온지운 칸 14 / 14

채점 = 지운 14칸만 본다 — ‘채운 값 − 정답’의 절댓값을 평균한 값(평균 절대 오차, °C). 이 값이 가장 작은 방법이 1등이다

1월 1일 · 12월 31일에는 가위가 들어가지 않는다 — 앞이나 뒤가 없으면 (c) 전날 값과 (d) 직선 보간이 채울 수 없기 때문이다. 그 두 칸은 아래에 짧은 밑줄이 그어져 있다

파이썬으로 — 지금 시험지: hole = [] (코드 ③의 hole 두 줄을 이 한 줄로 바꾸면 점수판과 같은 네 숫자가 나온다)

채점 전—1등
(a) 1년 평균—
(b) 그 달 평균—
(c) 전날 값—
(d) 직선 보간—
지운 칸0 / 14
도전 1

(c) 전날 값이 (d) 직선 보간을 이기게 하라 — 기온이 오르내리며 꺾이는 자리를 눈여겨보라.

도전 2

(b) 그 달 평균을 1등으로 만들어라 — 한 달 안에서 14칸을 어떻게 흩어야 할까?

도전 3

(a) 1년 평균을 1등으로 만들어라 — 교과서 시험지에서 11.87로 꼴찌였던 그 방법이다. 채점할 때마다 되먹임이 아래에 쌓이고, 두 번째·세 번째 실패에 힌트가 뜬다.

자료: 기상청 종관기상관측(ASOS) 서울(108) 2024년 366일의 평균 · 최저 · 최고기온과 일강수량 · 강수 계속시간 (../data/asos_seoul_2024.csv) — 쪽 안에 실었다. 지우는 칸만 가상이다(정답을 알아야 채점할 수 있다). 교과서 시험지는 코드 ③이 random.seed(7)로 만드는 14칸과 같은 칸이고, 공정한 시험지 200장 둘은 원장이 구운 시험지다(흩어진 14칸 · 이어진 14일 덩어리).

같은 366일, 같은 네 방법인데 1등이 바뀌었다. 그러므로 채점표가 재는 것은 만이 아니라 이기도 하다. 그래서 “어느 방법이 가장 좋은가”라는 물음에는 를 붙여야 답할 수 있다.

확인 문제 6에 적어 제출 →
4

네 방법을 파이썬으로 채점한다

4분

실험실에서 본 것을 이제 코드로 확인합니다. 7월 15~21일 일곱 칸과 흩어진 일곱 칸, 모두 14칸을 지웁니다 — 실험실의 [교과서 시험지]와 같은 칸이에요. 네 방법 가운데 1등은 누구일까요? 그리고 7월 평균기온은 채우는 방법에 따라 얼마나 달라질까요?

기본 빈칸 ④에 ‘앞뒤를 잇는 직선으로 채우는’ 함수 이름을, 빈칸 ⑤에 ‘차이를 절댓값으로 바꾸는’ 부분을 채우고 ▶ 실행합니다.

도전 hole 두 줄을 실험실이 준 hole = [...] 한 줄로 바꿔 돌려 보세요. 점수판과 소수 둘째 자리까지 같은 네 숫자가 나옵니다. 도전 3을 푼 시험지를 넣으면 (a)가 1등이 됩니다.

탐구 선형 보간이 크게 빗나갈 상황을 이 자료에서 하나 찾아보세요 — 빈 구간이 길 때 · 그 사이에 급변이 있을 때 · 값이 날마다 들쭉날쭉할 때 가운데 무엇이 가장 위험할까요?

지우는 칸을 7월에서 4월로 옮기면 (a) 1년 평균 채우기의 오차는 . 4월 평균 기온은 °C이고 1년 평균은 °C이기 때문이다. 그러므로 방법의 좋고 나쁨은 에 달려 있다.

확인 문제 5에 적어 제출 →
5

같은 채우기를 scikit-learn 으로 — SimpleImputer

3분

이제 손으로 한 채우기를 도구에게 시켜 봅니다. SimpleImputer의 fit이 기억하는 값은 무엇일까요? 그 값은 pandas 의 무엇과 같을까요? 그리고 두 결과는 얼마나 다를까요 — 조금 다를까요, 한 칸도 안 다를까요?

기본 빈칸 ⑥에 평균으로 채우는 전략 이름을 따옴표째 채우고 ▶ 실행합니다. 이 칸은 처음 실행할 때 몇 초 멈춥니다 — scikit-learn 을 처음 받는 중이에요(고장이 아닙니다).

도전 strategy를 "median"으로 바꾸면 7월 채우기가 나아질까요? 오차가 11.87 → 11.30으로 조금 줄지만 여전히 꼴찌입니다 — 1년 중앙값도 봄·가을 기온이기 때문이에요.

탐구 전략 넷(mean · median · most_frequent · constant) 가운데 강수량에 맞는 것은 무엇이고 그 까닭은 무엇인가요? 이 선택은 도구가 아니라 설명서를 읽은 사람이 합니다.

도구가 대신해 준 것은 이고, 도구가 모르는 것은 와 이다.

확인 문제 3에 적어 제출 →
6

진짜로 빈 날 — 신상명세서의 ‘빈칸’ 칸을 고쳐 쓴다

2분

강수량의 빈칸은 ‘잴 일이 없었다’였습니다. 그렇다면 풍속은 어떨까요 — 바람이 안 부는 날은 없으니 빈칸이 있다면 그것은 다른 얼굴일 것입니다. 풍속이 빈 날은 몇 날일까요? 흩어져 있을까요, 몰려 있을까요?

기본 이 칸은 채워져 있습니다. 그대로 ▶ 실행해 빈 날의 날짜와 앞뒤 값을 보세요.

도전 열을 "합계 일조시간(hr)"으로 바꿔 같은 표를 보세요. 두 열의 빈 날이 같은 날인가요? (3월 11 · 14일은 둘 다, 3월 12일은 풍속만, 11월 16일은 일조만입니다.)

탐구 3차시 신상명세서의 ‘빈칸’ 칸을 뜻과 함께 고쳐 쓰세요 — 예: “강수 206일(비가 없던 날) + 0.0으로 적힌 50일(0.1mm 미만) · 풍속 3일(관측 빠짐) · 일조 3일”.

풍속의 빈 3일은 얼굴이므로, 나는 를 택하겠다. 까닭은 이다.

확인 문제 4에 적어 제출 →
체크포인트 3

빈칸의 뜻을 같은 파일 안에서 확인했고, 숨은 빈칸을 찾아냈고, 채우는 방법 넷을 직접 채점했고, 시험지를 바꿔 순위를 뒤집어 보았고, 같은 일을 도구로 다시 해 보았다.

다음 정거장 · 정리·확인 10분 →
4
정리·확인 · 10분

오늘의 탐험 일지

  1. 찾은 것

    빈칸에는 세 얼굴이 있고, 그 뜻은 대개 같은 파일의 다른 열이 증언한다 — 강수량 빈칸 206일은 ‘비가 없던 날’, 0.0 50일은 ‘0.1mm에 못 미친 날’이었다.

  2. 도구의 한계

    pandas 는 빈칸을 조용히 건너뛰고, SimpleImputer는 빈칸의 뜻도 날짜 순서도 모른다. 둘 다 오류를 내지 않는다.

  3. 보고의 규칙

    채우기는 채점할 수 있다 — 그러나 채점표는 방법만이 아니라 어디가 비었는가도 잰다. 그러니 방법 · 분모 · 시험지를 함께 적는다.

✍️ 문제마다 답을 쓰고 제출하기를 누르세요. 제출하면 모범 답안이 열리고, 제출한 답은 선생님께 전달됩니다.

1. 따릉이 대여이력 표본 2,000행의 ‘성별’ 칸에는 빈 칸과 \N이 둘 다 나온다(51행 · 494행). ① 이런 숨은 빈칸을 어떻게 찾아내는지 쓰고, ② “이용자의 39.7%가 여성”이라는 보고서 문장의 문제점과 고쳐 쓴 문장을 분모와 함께 쓰시오.
📖 모범 답안

① 합계나 평균을 내기 전에 value_counts(dropna=False)로 값의 목록부터 본다. 목록에 M · F 말고 \N이 섞여 있는 것이 보인다. pandas 는 빈 글자만 NaN으로 세므로 isna()는 51행만 센다. read_csv(..., na_values=["\N"])로 읽거나 글자로 직접 세면 성별을 모르는 기록이 545행(27.3%)임을 알 수 있다.

② “39.7%”는 M과 F만 센 분모 1,455에서 나온 값이다. 모름 545행을 분모에 넣으면 28.9%가 된다. 어느 쪽이 맞다기보다 분모를 밝히지 않은 것이 문제다. 고쳐 쓰면: “성별이 기록된 1,455건 가운데 여성이 39.7%였다. 전체 2,000건의 27.3%(545건)는 성별을 알 수 없었다.”

2. “올해 서울의 하루 평균 강수량은 8.2mm”라는 문장이 왜 오해를 부르는지 쓰고, 분모를 밝혀 고쳐 쓴 문장을 쓰시오. 그리고 .mean()은 8.20과 3.58로 달라지는데 .sum()은 둘 다 1311.4로 같은 까닭도 함께 쓰시오.
📖 모범 답안

8.20mm는 빈칸 206일을 건너뛴 평균이다. pandas 의 .mean()은 빈칸을 빼고 계산하므로 분모가 366이 아니라 160(= 366 − 206)이다. 곧 이 숫자의 정체는 ‘1년 하루 평균’이 아니라 ‘비가 내린 날의 하루 평균’이다.

고쳐 쓰면: “비가 내린 160일의 하루 평균은 8.2mm, 1년 366일로 나눈 하루 평균은 3.6mm였다(비가 없던 206일은 0으로 보았다).” 분모 160에는 0.0으로 적힌 50일도 들어간다 — 그날들은 0.1mm에 못 미쳤을 뿐 비가 내린 날이기 때문이다(110이 아니다).

.sum()이 같은 것은 0을 아무리 더해도 합이 변하지 않기 때문이다. 빈칸을 건너뛰는 것과 빈칸에 0을 넣는 것은 합계에는 같은 일이지만 평균에는 분모를 바꾸는 일이다.

3. SimpleImputer의 전략을 mean에서 median으로 바꾸면 7월 빈칸 채우기가 나아지는지 답하고 그 까닭을 쓰시오. 그리고 이 도구가 대신해 준 것 한 줄과 모르는 것 한 줄을 각각 쓰시오.
📖 모범 답안

거의 그대로다 — 평균 오차가 11.87 → 11.30°C로 조금 줄 뿐 여전히 네 방법 가운데 꼴찌다. 1년 중앙값도 결국 봄·가을 기온이어서 한여름 26.6°C와는 멀기 때문이다. 기온처럼 계절을 따라 크게 움직이는 시계열에서는 ‘한 값으로 모두 채우는’ 전략 자체가 맞지 않는다.

대신해 준 것 — 채울 값을 열마다 기억해 두었다가(statistics_ 14.72°C) 같은 값으로 모든 빈칸을 한 번에 메워 준다. 그 값은 pandas 의 masked.mean()과 366칸 가운데 가장 큰 차이가 0.000000일 만큼 똑같다.

모르는 것 — ① 빈칸의 뜻. 강수량에 mean을 걸면 비가 없던 206일마다 8.2mm씩 ‘내리게’ 해 연 강수량이 1,311.4 → 2,999.8mm가 된다(constant·0이면 1,311.4 그대로). ② 날짜 순서. 고를 수 있는 전략 넷(mean · median · most_frequent · constant)에는 (c) 전날 값도 (d) 보간도 없다. 전략은 설명서를 읽은 사람이 고른다.

4. 아래 표에 이 파일에서 빈칸이 있는 네 열의 얼굴과 내가 택할 처리를 적으시오. 그리고 풍속의 빈 3일처럼 선형 보간으로 채우는 것이 위험한 경우를 하나 들고 까닭을 쓰시오.
열 (빈 날)빈칸의 얼굴내가 택할 처리와 까닭
일강수량 (206일)
강수 계속시간 (206일)
평균 풍속 (3일)
합계 일조시간 (3일)
📖 모범 답안

표 — 일강수량 206일: 구조적 빈칸(비가 없었다) / 0으로 채우되 0.0으로 적힌 50일과 섞이지 않게 ‘채웠다’는 표시를 남긴다. 강수 계속시간 206일: 구조적 빈칸(같은 날 잴 비가 없었다) / 같은 처리. 평균 풍속 3일: 진짜 결측(관측이 빠졌다) / 3월 11 · 12일은 이어진 이틀이라 보간이 위태롭다 — 빈칸으로 두고 ‘3일 빠짐’을 적거나, 채운다면 채웠다고 밝힌다. 합계 일조시간 3일: 진짜 결측 / 같은 처리.

선형 보간이 위험한 경우 — ① 빈 구간이 길 때(한 달이 통째로 비면 직선 하나가 그 달을 대신한다), ② 그 사이에 급변이 있을 때(장마 시작 · 한파 — 앞뒤를 이은 직선이 그 사건을 지워 버린다), ③ 값이 날마다 들쭉날쭉할 때(강수량처럼. 비가 안 온 날 사이를 이으면 없던 비가 생긴다). 풍속 3월 11 · 12일이 바로 ①에 가깝다 — 앞(2.1)과 뒤(2.7) 사이 이틀을 직선으로 채우면 그 이틀의 바람 이야기는 사라진다.

5. 코드 ③에서 지우는 14칸을 7월에서 4월로 옮기면 (a) 1년 평균 채우기의 오차는 어떻게 될지 답하고 그 까닭을 숫자와 함께 쓰시오. 그리고 이 사실이 “어느 채우기 방법이 좋은가”라는 물음에 무엇을 말해 주는지 한 문장으로 쓰시오.
📖 모범 답안

오차가 크게 준다. (a)는 빈칸을 모두 1년 평균 14.72°C 한 값으로 채운다. 7월 평균기온은 26.60°C라 채운 값과 11.9°C나 떨어져 있고, 그래서 오차가 11.87°C까지 커졌다. 4월 평균기온은 16.34°C로 1년 평균 14.88°C와 가깝다 — 채운 값이 정답 근처이므로 오차가 작아진다.

실험실에서 본 대로, 봄·가을 가운데 1년 평균에 가까운 날만 골라 지우면 (a)가 0.94°C로 1등이 되고 (d) 2.45 · (c) 2.59 · (b) 4.61로 순서가 통째로 뒤집힌다.

그러므로 “어느 방법이 좋은가”는 시험지를 밝히지 않으면 답할 수 없는 물음이다. 방법은 실제로 비어 있는 자리와 닮은 시험지로 채점해야 하고, 보고서에는 방법과 함께 어디를 지워 채점했는지를 적는다.

6. 실험실 「출제자의 가위」에서 (a) 1년 평균을 1등으로 만든 시험지의 14칸이 1년 띠의 어디에 모여 있었는지 쓰고, 왜 그 자리에서 (a)가 이기는지 설명하시오. 그리고 [공정한 시험지] 200장 두 벌의 결과가 서로 다른 까닭을 쓰시오.
📖 모범 답안

봄과 가을, 그 가운데서도 기온이 1년 평균(14.72°C) 근처인 날에 모여 있다. (a)는 빈칸을 모두 그 한 값으로 채우므로, 지운 날의 정답이 이미 14.72°C 근처라면 오차가 거의 0이 된다. 반대로 그런 날들은 앞뒤 값이 크게 오르내려 (c) 전날 값과 (d) 보간이 오히려 빗나간다. 원장이 실제로 푼 한 답은 3월 24일 · 4월 16 · 20 · 24일 · 5월 6 · 15일 · 10월 2 · 6 · 20 · 22일 · 11월 1 · 4 · 14 · 16일이고, 이때 (a) 0.94 · (d) 2.45 · (c) 2.59 · (b) 4.61로 교과서 시험지의 순위가 통째로 뒤집힌다.

200장 두 벌이 다른 까닭 — 시험지의 모양이 다르기 때문이다. 빈칸이 하루씩 흩어져 있으면 양옆에 늘 성한 값이 있어 (d) 직선 보간이 193장을 이기고 (a)는 0장이다. 그런데 14일이 이어서 비면 이을 앞뒤가 멀어져 (d)의 힘이 빠지고, 판이 (d) 100 · (c) 45 · (b) 42 · (a) 13으로 갈린다. 곧 순위는 방법의 성질이 아니라 방법과 빈자리의 궁합이다. 방법을 고르기 전에 이 자료가 실제로 어떻게 비는지를 먼저 본다.

+
더 알아보기

빈칸이 만든 이야기 셋

주차 위반 기록고지서가 가는 곳가 지역 · 03-14NULL나 지역 · 04-027X1 2345다 지역 · 05-21NULL라 지역 · 06-09NULL마 지역 · 07-302B9 8712바 지역 · 08-17NULLNULL번호판을 단한 사람‘값이 없음’ 을 뜻하려고 쓴 글자가‘진짜 값’ 으로 읽히면청구서 1만 2천 달러
사고

‘NULL’ 번호판을 단 사람

데이터베이스에서 NULL은 ‘값이 없음’을 뜻하는 특별한 자리입니다. 그런데 그것이 글자로 적히는 순간 평범한 값이 되어 버립니다. 2019년, 한 보안 연구자가 미국 캘리포니아에서 자동차 번호판을 NULL로 신청했습니다. 시스템이 빈 번호판을 어떻게 다루는지 보려는 장난에 가까운 실험이었지요.

얼마 뒤 그에게 남의 주차 딱지가 몰려들기 시작했습니다. 번호판을 못 읽었거나 비워 둔 위반 기록에 단속 시스템이 NULL을 적어 두었는데, 고지서를 만드는 쪽에서는 그것을 진짜 번호판으로 읽은 것입니다. 청구액은 1만 2천 달러가 넘게 쌓였고, 그는 그해 DEF CON 보안 학회에서 이 일을 발표했습니다.

오늘 우리가 본 따릉이의 \N과 정확히 같은 사고입니다. 다만 그쪽은 숫자가 조금 틀리는 정도로 끝났고, 이쪽은 한 사람에게 남의 벌금이 갔습니다. ‘없음’을 나타내는 표기는 언젠가 값으로 읽힌다 — 그래서 파일을 받으면 값의 목록부터 보는 것입니다.

도해: 번호판 칸이 NULL인 위반 기록 여러 건이 한 사람에게 모이는 모습을 그린 것이다. 지역·날짜·번호판은 구조를 보이려고 지어낸 예시이고, 청구액은 발표에서 밝힌 값이다. · 출처: Joseph Tartaro, “NULL” 번호판 사례 발표, DEF CON 27(2019)

관측소에서 빈칸이 생기는 길풍향 · 풍속기온 · 습도일조장비 점검낙뢰 · 정전통신 끊김빈칸 한 칸이웃 관측소 값과 대어 본다 — 품질관리(QC)의심 값 표시그래서 포털은 값과 함께요소마다 결측률을 따로 알린다빈칸도 자료다
현장

관측소의 빈칸은 어떻게 생기고, 어떻게 표시되나

오늘 쓴 ASOS 자료의 풍속에 빈 날이 3일 있었습니다(3월 11 · 12 · 14일). 관측소는 사람이 눈으로 재는 곳이 아니라 자동기상관측장비가 쉬지 않고 재는 곳인데도 빈칸이 생깁니다 — 정기 점검으로 센서를 떼어 두는 동안, 낙뢰나 정전으로 장비가 멎었을 때, 통신이 끊겨 값이 도착하지 못했을 때입니다.

그래서 기상청은 값을 그대로 내보내지 않고 품질관리(QC)를 한 번 거칩니다. 물리적으로 불가능한 값인지, 앞뒤 시각과 견주어 갑자기 튀지 않는지, 이웃 관측소의 같은 시각 값과 크게 어긋나지 않는지를 보고 의심스러운 값에 표시를 답니다. 고쳐 쓰는 것이 아니라 표시를 남기는 것이 핵심이에요 — 쓰는 사람이 판단할 수 있도록.

기상자료개방포털이 요소마다 결측률을 따로 공개하는 까닭도 같습니다. 빈칸의 수는 자료의 흠이 아니라 자료에 대한 자료이고, 우리가 신상명세서에 ‘빈칸 206일’을 적은 것과 같은 일입니다.

도해: 자동기상관측장비의 센서 셋과 빈칸이 생기는 세 가지 까닭, 그리고 이웃 관측소 값과 대조해 표시를 다는 품질관리 흐름을 그린 것이다. · 출처: 기상청 기상자료개방포털 종관기상관측(ASOS) 자료 설명 및 품질관리 안내

한 번 채우기와 여러 번 채우기빈칸 하나채운 표 13.9채운 표 24.6채운 표 34.1채운 표 45.2채운 표 54.4평균과 범위한 벌만 채우면이 범위가사라진다채운 값은 추측이다 — 추측의 폭까지 보고한다
방법 더 깊이

한 번이 아니라 여러 번 채운다 — 다중 대체

오늘 우리는 빈칸을 한 번 채우고, 그 채우기를 채점했습니다. 그런데 채운 값은 어디까지나 추측입니다. 한 벌만 채워 놓고 분석하면, 결과를 보는 사람은 그 자리가 원래 비어 있었다는 사실도, 추측이 틀렸을 수 있다는 사실도 알 길이 없습니다. 불확실성이 조용히 사라지는 것이지요.

통계학자 도널드 루빈이 1987년에 정리한 다중 대체는 이 문제를 이렇게 풉니다 — 빈칸을 그럴듯한 값 여러 벌로 채워 표를 여러 개 만들고, 각각 똑같이 분석해 결과를 여러 개 얻은 뒤, 그 평균과 흩어진 정도를 함께 보고합니다. 결과 다섯 개가 3.9부터 5.2까지 퍼져 있다면 그 폭 자체가 “이만큼은 모른다”는 정직한 진술이 됩니다.

한 벌만 채우는 오늘의 방법이 틀린 것은 아닙니다. 다만 그때는 채웠다는 사실과 채운 방법을 반드시 적어 두어야 뒷사람이 그 폭을 가늠할 수 있어요. 채우기는 답을 만드는 일이 아니라 모르는 것을 다루는 방식이라는 점에서, 오늘의 마스킹 검증과 다중 대체는 같은 곳을 바라봅니다.

도해: 빈칸 하나를 다섯 벌로 채워 각각 분석하면 결과가 다섯 개 나오고, 그 평균과 범위를 함께 보고하는 흐름을 그린 것이다. 결과 다섯 값은 퍼진 모양을 보이려고 지어낸 예시다. · 출처: D. B. Rubin, Multiple Imputation for Nonresponse in Surveys, Wiley, 1987