단원 홈

Ⅰ. 데이터 과학의 이해7차시

두 표를 이으면
무엇이 생기고 무엇이 사라지나

짝이 없는 행은 오류 없이 사라진다

대여소가 몇 곳인지는 한 파일이, 주민이 몇 명인지는 다른 파일이 압니다. “대여소 한 곳이 주민 몇 명을 맡나”는 어느 파일 혼자서도 답하지 못해요. 두 표를 이어 그 답을 만들어 보고, 이으면 무엇이 새로 생기고 무엇이 조용히 사라지는지, 그리고 이어져서는 안 될 것이 이어지는 때는 언제인지 봅니다.

  • [12데과01-03]
  • 50분네 정거장
  • 새 도구merge — 표 잇기
  • 자료대여소 정보 2,789곳 · 주민등록 인구 26줄 · 가상 600명
Ⅰ 단원 지도7 / 9차시
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9

학습 목표

  1. 개념에서

    통합이 필요한 상황과 통합의 뜻을 말하고, 두 표의 한 행의 단위와 열쇠를 짚을 수 있다.

  2. 손으로

    두 공공데이터를 이어 어느 표에도 없던 열을 만들고, 잇기 전후의 행 수를 행 가계부에 적을 수 있다.

  3. 확인에서

    짝을 못 찾은 행을 고칠 것·버릴 것·적을 것으로 가르고, 이어져서는 안 될 것을 막을 방법을 쓸 수 있다.

1
여는 장면 · 5분

파일 두 개 — 어느 쪽도 혼자서는 답하지 못한다

자전거 대여소를 어느 구에 더 놓을지 정하려 합니다. 판단에 쓸 수치 하나가 떠오릅니다 — 대여소 한 곳이 주민 몇 명을 맡나. 그런데 이 수치는 어느 파일에도 들어 있지 않아요. 대여소 파일에는 주민 수가 없고, 인구 파일에는 대여소가 없습니다.

두 파일은 만든 기관도 목적도 다르고, 무엇보다 한 행이 뜻하는 것이 다릅니다. 한쪽은 한 행이 대여소 한 곳, 다른 쪽은 한 행이 구 하나예요. 게다가 인구 파일은 받은 모양 그대로입니다 — 다듬지 않은 채로 들여다봅니다.

두 파일의 첫 줄들을 나란히 놓아 봅시다. 두 칸 모두 '구'를 가리키는데 적힌 모양이 다르고, 인구 표에는 구가 아닌 줄도 한 줄 섞여 있어요. 이런 표 두 장을 이으면 무슨 일이 일어날까요?

받은 파일 둘서로 다른 두 기관
공공자전거 대여소 정보✓ 대여소 수✕ 주민 수주민등록 인구✓ 주민 수✕ 대여소 수대여소 한 곳이 맡는 주민은?어느 쪽도 혼자서는 답하지 못한다

자료: 서울 열린데이터광장 공공자전거 대여소 정보(OA-13252, 2026년 6월 기준, 공공누리 제1유형) · 행정안전부 주민등록 인구통계 서울 자치구(2024년 12월, 이용허락범위 제한 없음)

표 1두 파일을 나란히 놓으면열쇠가 될 칸의 첫 세 줄 — 받은 그대로
파일한 행이 뜻하는 것행 수열쇠가 될 칸의 첫 세 줄 — 받은 그대로
공공자전거 대여소 정보 대여소 한 곳 2,789 자치구 — 마포구 · 마포구 · 마포구
주민등록 인구 구 하나 + 맨 위 서울 합계 줄 26 행정구역 — 서울특별시  (1100000000) · 서울특별시 종로구 (1111000000) · 서울특별시 중구 (1114000000)

두 칸 모두 '구'를 가리키는데, 한쪽은 마포구이고 다른 쪽은 이름과 10자리 코드가 한 칸에 들어 있습니다. 인구 표 맨 위 한 줄은 구가 아니라 서울 전체의 합계예요. 자료: 서울 열린데이터광장 OA-13252(2026년 6월) · 행정안전부 주민등록 인구통계(2024년 12월) — 두 파일에서 그대로 옮긴 값

먼저 예측

두 표를 무엇으로 이을 수 있을까요? 그리고 이으면 몇 행이 남을까요? 대여소 2,789행과 인구 26행 그대로는 단위가 맞지 않으니, 먼저 대여소를 구마다 묶어 25행으로 만든 다음 이었다고 해 봅시다. 3정거장 「손으로」 미션 ①에서 여러분의 예측과 실제 결과를 맞대어 봅니다.

체크포인트 1

무엇으로 이을지와 몇 행이 남을지를 적어 두었다 — 아직 이어 보지는 않았다.

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

통합 — 공통 속성으로 행을 짝짓는 일

2-1무엇으로 잇나 — 열쇠와 '한 행'의 단위

통합은 서로 다른 표의 행을 공통 속성으로 짝지어 한 행에 모으는 일입니다. 그 공통 속성을 열쇠라고 부르기로 해요 — 오늘 두 표의 열쇠는 '구 이름'입니다. 통합이 필요한 상황은 묻고 싶은 것에 쓸 칸이 서로 다른 표에 흩어져 있을 때고요.

이으면 어느 표에도 없던 속성이 생깁니다. 대여소 수와 인구가 한 행에 나란히 놓이는 순간 대여소 한 곳이 맡는 주민 수를 계산할 수 있게 되지요 — 중구 1,310명부터 관악구 6,730명까지, 서울 전체로는 3,346명입니다. 이것이 “통합하면 1 + 1이 2보다 커진다”는 말의 뜻이에요.

다만 이름이 같은 칸이 있다고 바로 이으면 안 됩니다. '한 행'의 단위가 서로 달라서예요. 대여소 표는 한 행이 대여소 한 곳, 인구 표는 한 행이 구 하나입니다. 단위를 맞추지 않고 대여소 2,789행에 구 인구를 그대로 붙이면, 같은 구 인구가 그 구의 대여소 수만큼 되풀이되어 서울 인구가 11억 2,983만 명이 됩니다(실제는 933만 명). 오류는 나지 않아요 — 숫자만 틀립니다.

규칙잇기 전에 두 표의 '한 행'이 각각 무엇인지 적는다. 단위가 다르면 한쪽을 먼저 묶어 맞춘다.

단위를 안 맞추면서울 인구
9,331,8281,129,828,606
실제 933만안 맞추면 11억

자료: 대여소 2,789행에 구 인구를 그대로 이었을 때의 인구 합 1,129,828,606명 — 원장 실측값(코드 ③ 도전)

Ⅰ-6 에서 가져옴6차시 도전에서 외래키를 껐더니 이을 때 한 행이 조용히 빠졌습니다. 오늘은 같은 일이 서로 다른 기관이 다른 목적으로 만든 표 두 장 사이에서 일어납니다 — 이번엔 한 행이 아니라 전부가 빠질 수도 있어요.

2-2이으면 무엇이 조용히 사라지나 — 행 가계부

구별 대여소 수 25행과 인구 26행을 '구 이름'으로 이었더니 결과는 0행이었습니다. 오류 메시지는 한 줄도 나오지 않았어요. 잇기는 짝을 못 찾은 행을 조용히 버리는 일이라, 한 줄도 짝을 못 찾으면 그냥 빈 표가 됩니다.

까닭은 글자였습니다. 대여소 쪽은 종로구인데 인구 쪽은 서울특별시 종로구 (1111000000)이라 한 글자도 같지 않았던 거예요.

그래서 잇기에는 습관이 하나 필요합니다. 행 가계부 — 잇기 전후의 행 수와, 짝을 못 찾아 사라진 행을 적어 두는 줄이에요. 가계부를 적지 않으면 사라진 줄을 알아챌 방법이 없습니다. 0행이 되어도 아무도 말해 주지 않으니까요.

규칙잇기 전후의 행 수를 가계부에 적고, 짝을 못 찾은 행을 고칠 것·버릴 것·적을 것으로 가른다.

행 가계부2,789 → 25
2,789대여소 정보 — 한 행 = 대여소 한 곳자치구로 묶기 · 빠진 대여소 025구별 대여소 수 — 한 행 = 구 하나'자치구' ⋈ '행정구역' · 짝 00오류 없음 · 한 줄도 안 남았다둘째 낱말을 뽑고 다시 · left25+ 새 열 주민/대여소인구 쪽 합계 줄 1줄은 결과에 없다— 어느 쪽을 기준으로 잇느냐가 정한다

자료: 대여소 정보 2,789곳 × 주민등록 인구 26줄 — 원장 실측값(코드 ① · ② · ③이 찍는 행 수와 같다)

그림 1열쇠의 글자를 맞대면 — 이름을 뽑는 두 가지 방법진한 칸이 남기는 부분
방법 가 — '서울특별시 ' 를 지운다.str.replace("서울특별시 ", "")서울특별시␣종로구␣(1111000000)뽑은 값'종로구 (1111000000)'대여소 쪽'종로구'✕ 한 글자도 같지 않다0행25행 ⋈ 26행의 결과빈칸 뒤에 코드가 그대로 남는다.오류는 없다 — 한 줄도 안 남을 뿐이다. 방법 나 — 둘째 낱말을 뽑는다.str.split().str[1]서울특별시␣종로구␣(1111000000)뽑은 값'종로구'대여소 쪽'종로구'= 같다25행+ 새 열 주민/대여소합계 줄 '서울특별시 (1100000000)'→ 같은 규칙이 '(1100000000)' 을 남긴다 · 끝내 짝 없음 방법 가 — '서울특별시 ' 를 지운다.str.replace("서울특별시 ", "")서울특별시␣종로구␣(1111000000)뽑은 값'종로구 (1111000000)'대여소 쪽'종로구'✕ 한 글자도 같지 않다0행25행 ⋈ 26행의 결과빈칸 뒤에 코드가 그대로 남는다.오류는 없다 — 한 줄도 안 남을 뿐이다. 방법 나 — 둘째 낱말을 뽑는다.str.split().str[1]서울특별시␣종로구␣(1111000000)뽑은 값'종로구'대여소 쪽'종로구'= 같다25행+ 새 열 주민/대여소합계 줄 '서울특별시 (1100000000)'→ 같은 규칙이 '(1100000000)' 을 남긴다 · 끝내 짝 없음

같은 '고칠 것'이라도 고치는 방법을 고르는 일이 남습니다. '서울특별시 '만 지우면 코드가 그대로 남아 여전히 0행이고, 둘째 낱말을 뽑아야 25행이 됩니다. 그리고 어느 방법으로도 짝을 못 찾는 줄이 하나 남아요 — 서울 합계 줄입니다. 자료: 주민등록 인구 26줄의 '행정구역' 칸 — 원장 실측값(코드 ②의 두 방법이 찍는 행 수와 같다)

표 2짝을 못 찾은 행을 가르는 세 갈래
갈래무엇인가오늘의 예무엇을 하나
고칠 것 같은 것을 다르게 적은 글자 서울특별시 종로구 (1111000000) ↔ 종로구 · 쉼표 든 숫자 '557,345' 규칙을 하나 정해 표 전체에 퍼뜨린다
버릴 것 애초에 짝이 있을 수 없는 행 서울 합계 줄 서울특별시  (1100000000) — 구가 아니라 25개 구의 합 왜 버렸는지 적고 뺀다
적을 것 고칠 수도 버릴 수도 없는 차이 대여소는 2026년 6월 · 인구는 2024년 12월(그 사이 설치된 대여소 77곳) · 자치구 열과 주소의 구가 다른 대여소 9곳 보고서에 한 줄로 밝힌다

셋 가운데 '적을 것'이 가장 자주 빠집니다. 고칠 수도 버릴 수도 없으니 손댈 일이 없고, 손댈 일이 없으면 잊히거든요. 그런데 결론을 읽는 사람에게는 이 줄이 가장 필요합니다. 자료: 원장 1단계 실측(PHENOMENA 11) — 설치일이 2024-12-31 뒤인 대여소 77곳 · 자치구 열과 상세주소의 구가 다른 대여소 9곳

2-3이어서는 안 되는 것이 이어진다

잇기는 가치만 만들지 않습니다. 어떤 병원이 진료 기록을 공개하면서 이름을 지우고 출생연도·성별·동·진료과만 남겼다고 해 봅시다. 기록은 60건이에요. 그리고 세상에는 이미 두 명부가 공개되어 있습니다 — 아파트 관리 명부(이름·동)와 동창회 연락망(이름·출생연도·성별), 각각 600명입니다.

명부를 하나씩 대 보면 아무 일도 일어나지 않아요. 동만으로 이으면 기록 하나에 적어도 137명이 붙고, 출생연도와 성별만으로 이으면 적어도 2명이 붙습니다. 한 사람으로 좁혀지는 기록은 0건 — 두 표 모두 '안전'해 보입니다.

그런데 두 명부를 '이름'으로 먼저 이으면 이름·출생연도·성별·동이 한 행에 놓인 표가 생깁니다. 이 표로 병원 기록을 공격하면 60건 가운데 24건(40%)의 이름이 되살아나요. 위험은 어느 표 안에도 없었습니다. 잇는 손짓에서 생긴 거예요.

막는 방법은 한 칸에 여러 사람이 들어가게 하는 것입니다. 출생연도를 5년 단위로 묶어 공개하면 한 사람과만 이어지는 기록은 0건이 되고(가장 적게 2명), 10년이면 5명이 됩니다. 대신 분석에 쓸 수 있는 정밀도가 줄어요. 사생활과 쓸모를 맞바꾸는 눈금이 여기에 있습니다.

그림 2위험은 어느 표 안에도 없었다같은 60건을 세 번 이어 본 결과
표 하나씩 이으면이름 지운 병원 기록 60건 · 칸 하나 = 기록 하나아파트 관리 명부 ⋈ 동열쇠 = 동한 사람과만 이어진 기록0건가장 적게 137명동창회 연락망 ⋈ 출생연도·성별열쇠 = 출생연도 · 성별한 사람과만 이어진 기록0건가장 적게 2명어느 표도 혼자서는 사람을 가리키지 못했다. 두 명부를 이름으로 먼저 이으면아파트 명부 ⋈ 동창회 연락망 → 600행 (이름·동·출생연도·성별)병원 기록 ⋈ 출생연도·성별·동열쇠 셋 — 어느 표에도 함께 있지 않던 세 칸24건이 한 사람과만 이어졌다60건 가운데 40% · 이름이 되살아났다1명 — 이름이 하나로 좁혀졌다여럿 — 아직 누구인지 모른다0명 — 명부에 짝이 없다60건을 나눠 보면24건한 사람과만 이어졌다36건여럿과 이어졌다0건아무와도 이어지지 않았다위험은 어느 표 안에도 없었다 —잇는 손짓에서 생겼다. 표 하나씩 이으면이름 지운 병원 기록 60건 · 칸 하나 = 기록 하나아파트 관리 명부 ⋈ 동열쇠 = 동한 사람과만 이어진 기록0건가장 적게 137명동창회 연락망 ⋈ 출생연도·성별열쇠 = 출생연도 · 성별한 사람과만 이어진 기록0건가장 적게 2명어느 표도 혼자서는 사람을 가리키지 못했다. 두 명부를 이름으로 먼저 이으면아파트 명부 ⋈ 동창회 연락망 → 600행 (이름·동·출생연도·성별)병원 기록 ⋈ 출생연도·성별·동열쇠 셋 — 어느 표에도 함께 있지 않던 세 칸24건이 한 사람과만 이어졌다60건 가운데 40% · 이름이 되살아났다1명 — 이름이 하나로 좁혀졌다여럿 — 아직 누구인지 모른다0명 — 명부에 짝이 없다60건을 나눠 보면24건한 사람과만 이어졌다36건여럿과 이어졌다0건아무와도 이어지지 않았다위험은 어느 표 안에도 없었다 —잇는 손짓에서 생겼다.

왼쪽 두 줄은 표 하나씩 검사한 결과입니다 — 둘 다 0건이라 '안전'으로 보고되겠지요. 오른쪽은 두 표를 먼저 이은 뒤의 결과예요. 표를 하나씩 검사해서는 이 위험이 보이지 않습니다. 자료: 가상 600명(random.seed(11)) · 기록 60건 — 원장 실측값(코드 ④의 0 · 0 · 24건과 같다)

2-4같아야 할 두 숫자가 다를 때

잇기에서 잘못은 대개 오류 메시지 없이 옵니다. 그래서 숫자 둘을 나란히 놓고 같아야 하는데 다른가를 보는 버릇이 필요해요. 아래 넷은 오늘 나온 모든 사고를 두 숫자로 줄인 것입니다.

이을 수 있다고 본 행 · 실제로 이어진 행
25예상한 행
vs
0실제로 남은 행
⋈짝 0

오류는 없었다 — 짝이 없으면 조용히 사라진다.

이름을 뽑는 두 방법
0가 '서울특별시 ' 지우기
vs
25나 둘째 낱말 뽑기
가나가 0행나 25행

'고칠 것'이라고 알아채도 고치는 방법이 또 갈린다.

단위를 맞추고 이었을 때 · 안 맞추고 이었을 때
933만서울 인구(실제)
→
11억대여소마다 구 인구를 붙이면
9,331,8281,129,828,606

같은 구 인구가 대여소 수만큼 되풀이됐다.

표 하나씩 검사할 때 · 두 표를 이은 뒤
0명부 하나씩(건)
→
24둘을 이은 뒤(건)

위험은 표 안이 아니라 잇는 손짓에서 생긴다.

자료: 위 네 쌍의 숫자는 모두 3정거장 코드 ① ~ ④가 찍는 값이다(원장 실측).

두 표를 잇기 전에 — 네 방향을 차례로

  1. 한 행두 표의 한 행이 각각 무엇인가 — 단위가 다르면 한쪽을 먼저 묶는다
  2. 열쇠두 표에 함께 있는 칸은 무엇인가 — 글자가 정말 같은가
  3. 가계부잇기 전후 행 수는 — 사라진 행은 고칠 것·버릴 것·적을 것 가운데 어느 갈래인가
  4. 금지이어서는 안 될 것이 이어지지 않는가 — 이름을 지워도 세 칸이면 한 사람이 된다

그래서 '오류가 안 났으니 잘 이어졌다'도 틀릴 수 있습니다. 0행도, 11억도, 40%도 모두 오류 없이 나온 결과였어요.

체크포인트 2

잇기 전에 볼 네 가지(한 행 · 열쇠 · 가계부 · 금지)를 말할 수 있다. 이제 직접 이어서 확인한다.

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

두 공공데이터를 잇고, 이어서는 안 될 것을 직접 이어 본다

오늘의 장비

merge — 두 표를 열쇠로 짝짓는 한 줄

6차시에서 데이터베이스가 표 안에서 하던 일을, 오늘은 우리가 파일 두 개 사이에서 합니다. 처음 실행은 몇 초 멈춰요 — 고장이 아니라 pandas 를 처음 받는 중입니다(쪽마다 한 번).

부르는 모양

왼쪽.merge(오른쪽, on="열쇠 칸")

# 왼쪽 행은 하나도 안 버리고 싶으면
왼쪽.merge(오른쪽, on="열쇠 칸",
           how="left")

오늘 쓰는 함수 넷

merge
두 표를 on 의 칸으로 짝짓는다
groupby
한 칸의 값이 같은 행을 한 행으로 묶는다 — 단위 맞추기(Ⅰ-5 에서 썼다)
str.split
한 칸의 글자를 낱말로 가른다 — .str[1] 로 둘째 낱말
str.replace
글자를 바꾼다 — 쉼표 떼기에도 쓴다

6차시 JOIN 과 다른 셋

  1. 지켜 주는 사람이 없다데이터베이스의 외래키가 막아 주던 일을 우리가 직접 본다
  2. 글자가 안 맞는다같은 기관이 만든 표가 아니라 열쇠의 모양부터 다르다
  3. 오류 없이 0행짝이 하나도 없어도 프로그램은 말해 주지 않는다

대가 — 잇는 힘이 세질수록 이어서는 안 될 것도 잘 이어집니다(미션 ④).

1

단위를 맞추고, 작업대에서 직접 이어 본다

11.5분

여는 장면에 적어 둔 내 예측입니다. 코드 ①을 돌려 단위부터 맞춘 뒤, 실험실에서 직접 이어 이 문장을 확인합니다.

기본 빈칸 ①에 무엇으로 묶어야 '구 하나 = 한 행'이 되는지를 채우고 ▶ 실행하세요. 두 표의 '한 행'이 각각 무엇인지, 인구 표의 첫 두 줄이 받은 그대로 어떻게 생겼는지 함께 찍힙니다.

도전 묶기 전후의 합을 견주세요 — 구별["대여소수"].sum() 이 2,789 그대로인가요? 묶기도 잇기처럼 행을 버릴 수 있습니다(자치구가 빈 대여소가 있었다면 그 행이 사라집니다).

탐구 인구 표의 첫 줄 '서울특별시  (1100000000)'은 왜 구가 아닌 줄이 한 줄 더 들어 있을까요? 표를 만든 쪽의 목적으로 설명해 보세요.

이제 작업대에서 직접 잇습니다. 작업대는 표 카드를 올려놓고 잇는 자리고, 카드 위의 이름표가 열 칩이에요 — 칩 둘을 맞대면 그 두 칸이 잇기의 열쇠가 됩니다. 0판에서 실데이터 두 표를 이어 행 가계부를 읽고, 1~3판에서는 이름 지운 병원 기록으로 모의 공격(이름이 되살아나는지 우리가 직접 해 보는 점검)을 합니다. 열쇠의 글자가 안 맞을 때는 글자 현미경(두 칸의 글자를 낱말로 갈라 맞대 보는 창)을 열고, 한 사람으로 좁혀진 기록에는 도장(그 지목을 얼마나 믿는지 — 확실 · 의심)을 찍습니다. 도전 셋을 풀면 카드가 스스로 닫혀요.

시뮬레이터

모자이크 감사판

안전한 표 두 장이 만나면 — 무엇이 생기고 무엇이 사라지나

  1. 1카드의 열 칩을 끌어(또는 톡 치고 다른 칩을 톡 쳐) 다른 카드의 칩에 놓는다
  2. 2잇기 전에 왼쪽에서 '내 예측'을 고른다 — 고르면 칩이 풀린다
  3. 3행 가계부를 읽는다 — 가계부를 톡 치면 그 잇기가 풀린다
작업대
내 예측
동창회 연락망 — 몇 명이 실려 있나
병원이 공개하는 출생연도
작업대0판 · 실데이터 두 표

행 가계부 = 왼쪽 행 ⋈ 오른쪽 행 → 남은 행 · 짝을 못 찾아 사라진 행 · 한 사람과만 이어진 기록 = 기록 하나에 이어진 사람이 정확히 1명(이름이 하나로 좁혀졌다고 본다)

0행이어도 오류는 없다 — 잇기는 짝이 없는 행을 조용히 버린다. 그래서 잇기 전후의 행 수를 늘 적어 둔다

이은 결과—행
사라진 행 ㉯—
사라진 행 ㉰—
가장 적은 구—
가장 많은 구—
서울 전체—
도전 1

0판 — 이으면 0행이 나온다. 글자 현미경으로 남길 낱말을 찾아 25행을 만들고, 그래도 끝내 짝이 없는 한 줄이 무엇인지 확인하라.

도전 2

2판 — 명부 하나씩으로는 0건이었다. 두 명부를 '이름'으로 먼저 이어 세 칸 열쇠로 공격하면 60건 가운데 몇 건의 이름이 되살아나나?

도전 3

흐리기 — 연락망 420명 판에서 병원이 흐린다면: 출생연도를 10년씩 공개할 때와 동 칸을 빼고 공개할 때, 어느 쪽이 0건이 되나?

자료: 0판 = 서울 열린데이터광장 공공자전거 대여소 정보(OA-13252, 2026년 6월) · 행정안전부 주민등록 인구통계(2024년 12월) — 받은 모양 그대로 쪽에 실었다. 1~3판 = 가상 600명(random.seed(11)) — 실제 개인으로 재식별을 시연하지 않는다. 진료과는 작업대에만 있는 가상 칸이다. 모든 숫자는 코드 ① ~ ④가 찍는 값과 같다(쪽이 열릴 때 스스로 검산한다).

대여소 곳에서 출발해 행이 되기까지, 행이 사라진 자리는 와 였다. 그리고 안전해 보이던 표 둘이 만나자 건의 이름이 되살아났는데, 그 위험은 에 있었다.

확인 문제 2에 행 가계부를 적어 제출 → 확인 문제 5에 통합의 두 얼굴과 도장의 까닭을 적어 제출 →
2

공통 속성으로 잇는다 — 몇 행이 남나

3.5분

작업대에서 본 것을 코드로 다시 확인합니다. 두 표를 '자치구'로 이으면 몇 행이 될까요? 그리고 이름만 뽑는 두 가지 방법 가운데 어느 쪽이 짝을 찾을까요?

기본 빈칸 ②에 두 표에 모두 있는 칸의 이름을 채우고 ▶ 실행하세요. 틀린 길을 일부러 한 번 겪습니다 — 0행이 나와도 오류는 없습니다.

도전 방법 '가'가 왜 0행인지 표['자치구'][1] 로 확인하세요. 겉으로는 고친 것처럼 보이는데 무엇이 남아 있나요?

탐구 글자.split().str[1] 대신 글자.extract(r"(\S+구)") 로 뽑으면 합계 줄은 어떻게 될까요? 뽑는 규칙을 바꾸면 버릴 것이 자동으로 걸러지기도 합니다 — 그것이 좋은 일인지도 함께 생각해 보세요.

두 표가 0행이 된 까닭은 이고, 이것은 갈래다. '나'로도 남은 '(1100000000)'은 갈래다.

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

이어서 생긴 새 속성 — 대여소 한 곳이 맡는 주민

2.5분

이제 두 표가 이어졌으니 인구 ÷ 대여소수를 계산할 수 있습니다. 그런데 그냥 나누면 어떻게 될까요? 인구 칸이 받은 그대로 쉼표가 든 글자라는 것을 떠올려 보세요.

기본 빈칸 ③에 대여소 한 곳이 맡는 주민 수를 내는 식을 채우고 ▶ 실행하세요. 왼쪽 기준(how="left")으로 이었으니 대여소 쪽 25개 구는 하나도 빠지지 않습니다.

도전 마지막 주석대로 구로 묶지 않고 대여소.merge(인구, on="자치구") 로 바로 이어, ["인구"].sum() 을 찍어 보세요. 1,129,828,606명(약 11억)이 나옵니다 — 서울 실제 인구는 9,331,828명이에요.

탐구 이 새 열로 '대여소를 어느 구에 더 놓을까'를 정한다면, 주민 수 말고 무엇으로 나누는 것이 더 나을까요?(출퇴근 인구 · 면적 · 자전거도로 길이 …) 등수 매기기와 잣대 고르기는 Ⅱ-12에서 본격적으로 다룹니다.

이 열은 두 표 어디에도 없었는데 때문에 생겼다. 이 열로 판단할 때 보고서에 함께 적을 것은 와 다.

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

이어서는 안 되는 것이 이어진다 — 직접 재 본다

2.5분

작업대에서 본 0 · 0 · 24건을 코드로 다시 잽니다. 표 하나씩 이을 때와 둘을 이름으로 이은 뒤 이을 때, 한 사람과만 이어지는 기록은 각각 몇 건일까요?

기본 코드 ④는 채워져 있습니다. 그대로 ▶ 실행해 세 줄의 숫자를 확인하세요. 자료는 가상 600명입니다 — 실제 사람이 아니에요.

도전 STEP 을 5 와 10 으로 바꿔 보세요 — 둘 다 0건이 되고, 기록 하나에 이어지는 사람이 가장 적게 2명 · 5명이 됩니다. 대가로 출생연도의 정밀도가 줄어요.

탐구 FRAC 을 0.7 로 바꿔 보세요(연락망 420명). 한 사람과만 이어진 기록이 27건으로 늘고, 그 가운데 진짜는 20건입니다 — 7명은 가 본 적 없는 진료과의 환자로 지목됩니다. random_state 를 2 · 3 으로 바꾸면 32건(진짜 24) · 30건(진짜 30)이에요.

명부를 하나씩 검사하면 건이라 '안전'으로 보고되지만, 하면 건이 된다. 병원에 권할 것은 이고, 그 대가는 다.

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

두 공공데이터를 이어 새 열을 만들었고, 사라진 행을 세 갈래로 갈랐고, 이어서는 안 될 것이 이어지는 것을 직접 보았다.

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

오늘의 탐험 일지

  1. 찾은 것

    공통 속성으로 이으면 어느 표에도 없던 열이 생긴다 — 대여소 한 곳이 맡는 주민 1,310 ~ 6,730명.

  2. 도구의 한계

    잇기는 짝이 없는 행을 오류 없이 버린다. 0행도, 11억도, 40%도 모두 오류 없이 나왔다.

  3. 보고의 규칙

    행 가계부를 적고, 사라진 행을 고칠 것·버릴 것·적을 것으로 가른다. 그리고 이어서는 안 될 것을 먼저 본다.

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

1. [B]에서 '자치구'로 그대로 이었더니 0행이 나왔고, 오류 메시지는 없었다. 짝을 못 찾은 까닭을 인구 표의 실제 글자로 설명하고, 이름만 뽑은 뒤에도 남은 '(1100000000)'을 무엇으로 판정할지, 쉼표 든 인구 칸('557,345')은 어떻게 처리할지 쓰시오.
📖 모범 답안

인구 쪽 칸은 '서울특별시 종로구 (1111000000)'처럼 이름과 10자리 코드가 한 칸에 들어 있어 대여소 쪽의 '종로구'와 한 글자도 같지 않다. 열쇠는 값이 글자까지 같아야 짝이 되므로 한 줄도 이어지지 않았고, 그래도 오류는 나지 않는다 — 잇기는 짝이 없는 행을 조용히 버리기 때문이다. 이것은 고칠 것이다.

다만 고치는 방법도 골라야 한다. '서울특별시 '만 지우면 '종로구 (1111000000)'이 남아 여전히 0행이고, 둘째 낱말을 뽑아야(.str.split().str[1]) 25행이 된다.

'(1100000000)'은 인구 표 맨 위의 서울 합계 줄에서 나온 것이다 — 구가 아니라 25개 구의 합이므로 이을 수 있는 짝이 애초에 없다. 버릴 것으로 판정하고, 왜 버렸는지 적어 둔다.

쉼표 든 '557,345'는 숫자가 아니라 글자라서 그대로 나누면 TypeError가 난다. 쉼표를 떼고 정수로 바꾼다(.str.replace(",", "").astype(int)) — 역시 고칠 것이다.

2. 행 가계부를 채우시오. 대여소 2,789곳에서 출발해 새 속성이 붙은 25행이 되기까지 어디서 몇 행이 왜 빠지거나 되살아났는지 표에 적고, 잇기 전후의 행 수를 적어 두는 습관이 왜 필요한지 쓰시오.
단계몇 행이 되나어디서 왜 빠졌나 (갈래)
① 받은 그대로
② 자치구로 묶기
③ 그대로 잇기
④ 낱말 뽑고 잇기
📖 모범 답안

표 — ① 2,789행(한 행 = 대여소 한 곳) / 빠진 것 없음. ② 25행 — 자치구로 묶었다. 묶음 안 대여소는 2,789곳 그대로이고 자치구가 빈 대여소가 0곳이라 빠진 대여소가 없다(묶기도 값이 비면 행을 버린다). ③ 0행 — 인구 쪽 열쇠가 이름 + 코드 한 칸이라 25개 구 전부가 짝을 못 찾았다(고칠 것). ④ 25행 — 둘째 낱말을 뽑고 왼쪽 기준으로 이어 대여소 쪽 25개 구는 하나도 안 빠졌고 인구 빈칸도 0곳이다. 대신 인구 쪽 서울 합계 줄 1줄은 결과에 없다(버릴 것).

묶기와 잇기는 오류 없이 행을 버린다. ③에서 0행이 되어도 프로그램은 아무 말도 하지 않았다. 그래서 행 수를 적어 두지 않으면 사라진 줄을 알아챌 방법이 없다 — 결과가 비어 있는 것과 '원래 그런 것'을 구별할 수 없게 된다. 게다가 사라진 행은 결론을 조금 틀리게 하는 데 그치지 않고, 남은 짝이 가짜가 되게 만들기도 한다(문제 5).

3. [C]의 새 속성(대여소 한 곳이 맡는 주민 수 — 중구 1,310명 ~ 관악구 6,730명)은 대여소 표에도 인구 표에도 없던 열이다. 이 열이 생긴 까닭과, 이 열로 '대여소를 어느 구에 더 놓을까'를 정할 때 보고서에 함께 적어야 할 것 두 가지를 쓰시오.
📖 모범 답안

두 표가 공통 속성(자치구)으로 짝지어져 대여소 수와 인구가 한 행에 나란히 놓였기 때문이다. 같은 행에 있어야 나눌 수 있으므로, 이 열은 이었기 때문에 비로소 생긴 속성이다.

함께 적을 것 ① — 두 표의 시점이 다르다. 대여소는 2026년 6월 기준, 인구는 2024년 12월 기준이고 그 사이 설치된 대여소가 77곳 있다. 최근 설치된 대여소가 많은 구는 실제보다 좋아 보일 수 있다.

함께 적을 것 ② — 어느 기준으로 구를 정했는지. 자치구 열과 상세주소의 구가 다른 대여소가 9곳 있어 둘 중 하나를 골라야 했고, 여기서는 자치구 열을 따랐다.

한계도 하나 덧붙일 수 있다 — 분모가 주민등록 인구라서 사는 사람만 센 값이다. 출퇴근·관광으로 들어오는 사람이 많은 구(중구·종로구)는 실제 수요보다 대여소가 넉넉해 보인다.

4. [D]에서 두 명부를 이름으로 이은 뒤 출생연도 + 성별 + 동으로 이었을 때 한 사람과만 이어진 기록이 40%(24건)였다. 병원이 “이름을 지웠으니 안전하다”며 출생연도·성별·동·진료과를 공개하려 한다. 무엇을 바꾸라고 권하겠는가? STEP 을 바꿔 본 결과를 근거로 쓰시오.
📖 모범 답안

한 칸에 여러 사람이 들어가게 흐린다. 출생연도를 5년(또는 10년) 단위로 묶어 공개하거나, 동을 구로 넓힌다. 이렇게 하면 같은 값을 가진 사람이 여럿이 되어 한 사람으로 좁혀지지 않는다(k-익명성).

근거 — STEP = 1 일 때 한 사람과만 이어진 기록은 24건(40%)이고 기록 하나에 가장 적게 1명이 이어졌다. STEP = 5 로 바꾸면 0건이 되고 가장 적게 2명, STEP = 10 이면 0건에 가장 적게 5명이다.

대가도 함께 적는다 — 출생연도의 정밀도가 준다. 나이와 관련된 분석은 그만큼 거칠어진다. 사생활과 쓸모를 맞바꾸는 눈금을 어디에 둘지는 공개하는 쪽이 정하고 적어야 한다.

그리고 검사 방법 자체를 바꾸라고 권한다. 명부를 하나씩 대 보면 둘 다 0건이라 '안전'으로 보고된다. 공개되어 있는 표들을 먼저 이은 뒤 검사해야 하고, 흐린 뒤에도 다시 이어 0건인지 확인해야 한다.

5. “통합하면 1 + 1이 2보다 커진다”와 “통합하면 1 + 1이 위험을 만든다”를 둘 다 오늘의 숫자로 설명하시오. 그리고 연락망이 420명뿐일 때(FRAC = 0.7) 한 사람과만 이어진 기록 27건 가운데 7건이 엉뚱한 사람이었다는 결과가 무엇을 더 말해 주는지 쓰시오. (작업대에서 도장을 찍어 보았다면, 왜 그렇게 찍었는지도 함께 적으시오.)
📖 모범 답안

2보다 커진다 — 대여소 표와 인구 표를 이어 어느 표에도 없던 '대여소 한 곳이 맡는 주민 수'가 생겼다 (중구 1,310명 ~ 관악구 6,730명, 서울 전체 3,346명). 각 표 혼자서는 답할 수 없던 물음에 답할 수 있게 된 것이다.

위험을 만든다 — 같은 원리로, 이름을 지운 기록 60건이 두 공개 명부와 이어져 24건(40%)의 이름이 되살아났다. 명부 하나씩으로는 0건 · 0건이었으니 위험은 어느 표 안에도 없었고 잇는 손짓에서 생겼다.

27건 가운데 7건 — 행이 빠진 표로 이으면 '한 사람과만 이어졌다'가 '그 사람이다'는 아니다. 참 주인이 연락망에서 빠지면 엉뚱한 한 사람만 남아 그 사람이 지목된다. 7명은 가 본 적 없는 진료과의 환자로 지목됐다. 사라진 행은 결론을 틀리게 할 뿐 아니라 틀린 사람을 가리킨다. 그래서 27건 모두에 '의심' 도장을 찍는 것이 맞다 — 가계부가 '180명이 빠졌다'고 말하고 있으므로, 한 명으로 좁혀졌다는 사실만으로는 그 사람이라는 보장이 없다.

덧붙이면, 연락망을 random_state 2 · 3 으로 바꾸면 32건(틀린 지목 8) · 30건(틀린 지목 0)이 된다 — 누가 빠졌느냐에 따라 결과가 달라진다는 것까지 보고서에 적어야 한다.

+
더 알아보기

탐험 밖의 이야기 셋

'익명' 이라던 두 표공무원 건강보험 기록이름을 지웠다투표인 명부돈을 주고 샀다진단명처방진료일이름주소정당우편번호생년월일성별겹치는 세 칸이 열쇠가 된다→ 한 사람의 진료 기록이 이름과 이어졌다묶어 놓으면 흔한 칸도, 함께 놓이면한 사람을 가리키는 열쇠가 된다.
역사

주지사의 진료 기록을 찾아낸 대학원생

1997년, 미국 매사추세츠주는 공무원 건강보험의 진료 기록을 연구용으로 공개했습니다. 이름과 주소를 지웠으니 누구인지 알 수 없다는 것이 공개의 근거였지요. 당시 대학원생이던 라타냐 스위니는 같은 주의 투표인 명부를 돈을 주고 샀습니다.

두 표에는 겹치는 칸이 셋 있었어요 — 우편번호 · 생년월일 · 성별. 이 셋으로 이었더니 당시 주지사의 진료 기록이 그의 이름과 이어졌습니다. 스위니는 그 기록을 주지사 사무실로 보냈고, 이 일은 미국의 의료정보 보호 규칙을 다시 쓰게 한 계기 가운데 하나가 됩니다. 「정보」 교과에서 한 문장으로 지나갔던 '우편번호 + 생년월일 + 성별'이 바로 이 이야기예요 — 오늘 우리가 출생연도·성별·동 세 칸으로 해 본 것과 같은 일입니다.

도해: 이름을 지운 기록과 공개 명부가 세 칸에서 겹치는 모습을 그렸다. 겹치는 칸의 이름은 사건에서 실제로 쓰인 셋이고, 그림의 나머지 칸 이름은 이해를 돕기 위한 예시다. · 출처: L. Sweeney, “Simple Demographics Often Identify People Uniquely”(2000) 등 후속 연구

한 칸에 다섯 사람 — 그런데출생연도를 10년으로 묶어 한 칸에 5명이 들어가게 했다(k = 5)출생연도성별동진료과1950년대여망원동정신건강의학과1950년대여망원동정신건강의학과1950년대여망원동정신건강의학과1950년대여망원동정신건강의학과1950년대여망원동정신건강의학과이름은 끝내 모른다 ✓그런데 진료과는 다섯 줄이 모두 같다→ 이 칸에 든 사람이라면 누구든 그 과에 갔다는 뜻 — 누구인지 몰라도 무엇으로 갔는지는 샌다(동질성 공격).
방법 더 깊이

흐렸는데도 새는 경우 — 동질성 공격

오늘 우리는 출생연도를 묶어 한 칸에 적어도 몇 사람이 들어가게 했습니다. 이것을 k-익명성이라고 불러요 — 같은 값을 가진 사람이 언제나 k명 이상이 되게 만드는 것입니다. 5년 단위로 묶었더니 기록 하나에 가장 적게 2명, 10년이면 5명이 이어졌지요.

그런데 한 칸에 든 다섯 사람의 진료과가 모두 같다면 어떻게 될까요? 누구인지는 끝내 모르지만 무엇으로 병원에 갔는지는 샙니다. 이것을 동질성 공격이라고 하고, 그래서 '한 칸에 몇 명'만이 아니라 '한 칸에 민감한 값이 몇 가지'인지도 따져야 한다는 생각(l-다양성)이 나왔습니다.

묶기만으로는 부족하다고 보고 아예 결과표에 계산된 잡음을 섞는 방법도 쓰입니다(차분 프라이버시). 정확도와 사생활을 맞바꾸는 눈금을 숫자로 정해 공개한다는 것이 이 방법의 핵심이에요.

도해: 출생연도를 10년 단위로 묶어 한 칸에 다섯 사람이 든 표를 그렸다. 값은 오늘의 가상 명부에서 가져온 예시이고, 실제 사람의 기록이 아니다.

두 기관의 자료를 합치는 길가명정보는 지정된 결합전문기관에서만 결합한다기관 ㉮가명처리한 표기관 ㉯가명처리한 표결합키 — 두 표를 짝지을 값(이름·주민번호가 아니다)결합전문기관여기서만 두 표를 잇는다 — 기관 ㉮·㉯ 는 결과를 보지 못한다반출 심사내보낼 표가 다시 한 사람을 가리키지 않는지 본다→ 분석가에게는 심사를 통과한 표만 간다
현장

두 기관의 자료를 합치는 데도 절차가 있다

오늘 [D]에서 우리가 해 본 일 — 서로 다른 곳의 표 둘을 이어 한 사람을 찾아내는 것 — 은 현실에서도 똑같이 일어납니다. 그래서 우리나라는 2020년 이른바 데이터 3법 개정 뒤, 서로 다른 기관의 가명정보를 아무 데서나 잇지 못하게 했습니다.

잇는 일은 지정된 결합전문기관에서만 합니다. 기관들은 이름이나 주민등록번호가 아니라 따로 만든 결합키를 넘기고, 결합된 표를 밖으로 가져나갈 때는 다시 한 사람을 가리키지 않는지 반출 심사를 받습니다.

오늘 배운 것으로 다시 읽으면 이렇습니다 — 잇기의 힘은 쓰되, 열쇠를 아무나 못 만들게 하고, 이은 결과를 밖에 내놓기 전에 한 번 더 센다는 것이지요. 우리가 작업대에서 도장을 찍어 본 일이 제도에서는 '반출 심사'라는 이름으로 있습니다.

도해: 가명정보 결합의 흐름(기관 → 결합키 → 결합전문기관 → 반출 심사 → 분석가)을 단계로 그렸다. 단계 이름은 개인정보 보호법령의 결합 절차에서 쓰는 말이고, 그림은 그 뼈대만 보인 것이다.