난이도별 연습문제집 — 편의점 간식 데이터 분석¶
수업·숙제 외에 추가로 연습하고 싶을 때 사용하는 문제 은행입니다. 총 18문제, 수준에 맞게 골라 푸세요.
| 난이도 | 문제 | 범위 | 언제 |
|---|---|---|---|
| 기초 (E) | 6문제 | Day 1 수업 내용 그대로 | Day 1 수업 후 언제든 |
| 중급 (M) | 6문제 | Day 1 + 조합·심화 | Day 1 수업 후 언제든 |
| 심화 (H) | 6문제 | groupby · 그래프 · 상관계수 | Day 2 수업 후 |
진행 규칙: ① 파일 → Drive에 사본 저장 ② [준비] 셀부터 실행 ③ 5분 고민해도 막히면 정답 보기를 확인하고, 그 문제는 표시해 두었다가 나중에 다시 풀기
In [ ]:
Copied!
# [준비] 이 셀 먼저 실행! — 도구 + 그래프 한글 설정 + 편의점 데이터
import sys, platform
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
try:
if "google.colab" in sys.modules:
import subprocess
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "koreanize-matplotlib"], check=True)
import koreanize_matplotlib
else:
fam = {"Darwin": "AppleGothic", "Windows": "Malgun Gothic"}.get(platform.system())
if fam:
matplotlib.rcParams["font.family"] = fam
matplotlib.rcParams["axes.unicode_minus"] = False
except Exception:
pass
# 어느 편의점의 하루 판매 기록 (12개 제품)
snack = pd.DataFrame({
"제품": ["새우깡", "초코파이", "감자칩", "콜라", "사이다", "이온음료",
"바나나우유", "메로나", "월드콘", "붕어싸만코", "젤리", "에너지바"],
"카테고리": ["과자", "과자", "과자", "음료", "음료", "음료",
"음료", "아이스크림", "아이스크림", "아이스크림", "과자", "과자"],
"가격": [1500, 1800, 2200, 2000, 1900, 2500, 1700, 1200, 2500, 2000, 1000, 2800],
"판매량": [45, 38, 25, 52, 48, 30, 65, 70, 55, 42, 58, 15],
})
print("준비 완료! 제품", len(snack), "개")
snack
# [준비] 이 셀 먼저 실행! — 도구 + 그래프 한글 설정 + 편의점 데이터
import sys, platform
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
try:
if "google.colab" in sys.modules:
import subprocess
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "koreanize-matplotlib"], check=True)
import koreanize_matplotlib
else:
fam = {"Darwin": "AppleGothic", "Windows": "Malgun Gothic"}.get(platform.system())
if fam:
matplotlib.rcParams["font.family"] = fam
matplotlib.rcParams["axes.unicode_minus"] = False
except Exception:
pass
# 어느 편의점의 하루 판매 기록 (12개 제품)
snack = pd.DataFrame({
"제품": ["새우깡", "초코파이", "감자칩", "콜라", "사이다", "이온음료",
"바나나우유", "메로나", "월드콘", "붕어싸만코", "젤리", "에너지바"],
"카테고리": ["과자", "과자", "과자", "음료", "음료", "음료",
"음료", "아이스크림", "아이스크림", "아이스크림", "과자", "과자"],
"가격": [1500, 1800, 2200, 2000, 1900, 2500, 1700, 1200, 2500, 2000, 1000, 2800],
"판매량": [45, 38, 25, 52, 48, 30, 65, 70, 55, 42, 58, 15],
})
print("준비 완료! 제품", len(snack), "개")
snack
기초 (E-1 ~ E-6) — Day 1 내용 그대로¶
In [ ]:
Copied!
# E-1: 오늘 본 쪽지시험 점수 [88, 72, 95, 60, 83]으로 NumPy 배열을 만들고,
# 평균과 최고 점수를 출력하세요.
# 힌트: np.array([...]) → .mean() 과 .max()
# E-1: 오늘 본 쪽지시험 점수 [88, 72, 95, 60, 83]으로 NumPy 배열을 만들고,
# 평균과 최고 점수를 출력하세요.
# 힌트: np.array([...]) → .mean() 과 .max()
In [ ]:
Copied!
# E-2: 위 배열에서 80점 이상인 점수만 골라내세요. (불린 마스킹)
# 힌트: scores[scores >= ??]
# E-2: 위 배열에서 80점 이상인 점수만 골라내세요. (불린 마스킹)
# 힌트: scores[scores >= ??]
In [ ]:
Copied!
# E-3: snack 데이터의 앞 3행을 확인하세요.
# 힌트: snack.head(??)
# E-3: snack 데이터의 앞 3행을 확인하세요.
# 힌트: snack.head(??)
In [ ]:
Copied!
# E-4: 전체 제품의 평균 가격을 구하세요.
# 힌트: snack["??"].mean()
# E-4: 전체 제품의 평균 가격을 구하세요.
# 힌트: snack["??"].mean()
In [ ]:
Copied!
# E-5: 하루 50개 이상 팔린 "인기 제품"만 골라내세요.
# 힌트: snack[snack["??"] >= ??]
# E-5: 하루 50개 이상 팔린 "인기 제품"만 골라내세요.
# 힌트: snack[snack["??"] >= ??]
In [ ]:
Copied!
# E-6: 가격이 싼 순서로 상위 3개 제품을 확인하세요.
# 힌트: 싼 순(작은→큰)은 기본값이라 ascending 생략 가능 → snack.sort_values("??").head(3)
# E-6: 가격이 싼 순서로 상위 3개 제품을 확인하세요.
# 힌트: 싼 순(작은→큰)은 기본값이라 ascending 생략 가능 → snack.sort_values("??").head(3)
기초 정답 보기 (E-1 ~ E-6)
scores = np.array([88, 72, 95, 60, 83])
print(scores.mean(), scores.max()) # E-1 (79.6 / 95)
print(scores[scores >= 80]) # E-2
snack.head(3) # E-3
print(snack["가격"].mean()) # E-4 (1925.0)
snack[snack["판매량"] >= 50] # E-5 (5개 제품)
snack.sort_values("가격").head(3) # E-6 (젤리·메로나·새우깡)
중급 (M-1 ~ M-6) — 조합해서 풀기¶
이제 두 가지 이상을 이어 붙여야 합니다. 편의점 사장님이 되었다고 생각하고 분석해 보세요.
In [ ]:
Copied!
# M-1: 카테고리가 "음료"인 제품만 골라내세요.
# 힌트: 문자열 비교는 == 연산자
# M-1: 카테고리가 "음료"인 제품만 골라내세요.
# 힌트: 문자열 비교는 == 연산자
In [ ]:
Copied!
# M-2: 새 열 "매출"을 만드세요. 매출 = 가격 × 판매량
# 힌트: snack["매출"] = snack["??"] * snack["??"]
# M-2: 새 열 "매출"을 만드세요. 매출 = 가격 × 판매량
# 힌트: snack["매출"] = snack["??"] * snack["??"]
In [ ]:
Copied!
# M-3: 매출 1위 제품은 무엇일까요? (예상과 같은지 확인해 보세요!)
# 힌트: snack.sort_values("??", ascending=False).head(1)
# M-3: 매출 1위 제품은 무엇일까요? (예상과 같은지 확인해 보세요!)
# 힌트: snack.sort_values("??", ascending=False).head(1)
In [ ]:
Copied!
# M-4 (3단 콤보): "음료" 제품들만의 평균 판매량을 구하세요.
# 힌트: 골라서 → 열 뽑아 → 평균 → snack[조건]["판매량"].mean()
# M-4 (3단 콤보): "음료" 제품들만의 평균 판매량을 구하세요.
# 힌트: 골라서 → 열 뽑아 → 평균 → snack[조건]["판매량"].mean()
In [ ]:
Copied!
# M-5: 카테고리별로 제품이 몇 개씩 있는지 세어 보세요.
# 힌트: snack["??"].value_counts()
# M-5: 카테고리별로 제품이 몇 개씩 있는지 세어 보세요.
# 힌트: snack["??"].value_counts()
In [ ]:
Copied!
# M-6 (다중 조건): 가격 1500원 이하 "그리고" 판매량 50개 이상 — 가성비 제품을 찾으세요.
# 힌트: snack[(조건1) & (조건2)] — 각 조건을 괄호로!
# M-6 (다중 조건): 가격 1500원 이하 "그리고" 판매량 50개 이상 — 가성비 제품을 찾으세요.
# 힌트: snack[(조건1) & (조건2)] — 각 조건을 괄호로!
중급 정답 보기 (M-1 ~ M-6)
snack[snack["카테고리"] == "음료"] # M-1 (4개)
snack["매출"] = snack["가격"] * snack["판매량"] # M-2
snack.sort_values("매출", ascending=False).head(1) # M-3 (월드콘 137,500원!)
print(snack[snack["카테고리"] == "음료"]["판매량"].mean()) # M-4 (48.75)
snack["카테고리"].value_counts() # M-5 (과자5·음료4·아이스크림3)
snack[(snack["가격"] <= 1500) & (snack["판매량"] >= 50)] # M-6 (메로나·젤리)
M-3 해석 포인트: 가장 비싸지도, 가장 많이 팔리지도 않은 월드콘이 매출 1위 — 두 값의 곱이 만드는 결과는 직관과 다를 수 있습니다.
심화 (H-1 ~ H-6) — Day 2 수업 후¶
groupby(그룹별 집계) · 그래프 · 상관계수까지 모두 사용하는 문제입니다.
In [ ]:
Copied!
# [심화 준비] 매출 열이 없다면 만들어 둡니다 (M-2를 건너뛰었어도 OK)
snack["매출"] = snack["가격"] * snack["판매량"]
snack.head(2)
# [심화 준비] 매출 열이 없다면 만들어 둡니다 (M-2를 건너뛰었어도 OK)
snack["매출"] = snack["가격"] * snack["판매량"]
snack.head(2)
In [ ]:
Copied!
# H-1: 카테고리별 평균 매출을 구하세요. 어느 카테고리가 장사가 제일 잘될까요?
# 힌트: snack.groupby("??")["매출"].mean()
# H-1: 카테고리별 평균 매출을 구하세요. 어느 카테고리가 장사가 제일 잘될까요?
# 힌트: snack.groupby("??")["매출"].mean()
In [ ]:
Copied!
# H-2: 카테고리별 판매량의 평균·최대·표준편차를 한 번에 구하세요.
# 힌트: snack.groupby("??")["판매량"].agg(["mean", "max", "std"])
# H-2: 카테고리별 판매량의 평균·최대·표준편차를 한 번에 구하세요.
# 힌트: snack.groupby("??")["판매량"].agg(["mean", "max", "std"])
In [ ]:
Copied!
# H-3: 제품별 매출 랭킹 차트 — 매출 높은 순으로 정렬해 막대 그래프로 그리세요.
# (제품명이 겹치지 않게 x축 글자를 45도 기울이기!)
# 힌트: top = snack.sort_values("??", ascending=False)
# plt.bar(top["제품"], top["매출"]) → 제목·축 이름 → plt.xticks(rotation=45)
# H-3: 제품별 매출 랭킹 차트 — 매출 높은 순으로 정렬해 막대 그래프로 그리세요.
# (제품명이 겹치지 않게 x축 글자를 45도 기울이기!)
# 힌트: top = snack.sort_values("??", ascending=False)
# plt.bar(top["제품"], top["매출"]) → 제목·축 이름 → plt.xticks(rotation=45)
In [ ]:
Copied!
# H-4: "비싸면 덜 팔릴까?" — 가격과 판매량의 산점도를 그리고 상관계수를 출력하세요.
# 힌트: plt.scatter(snack["가격"], snack["판매량"]) + 제목·축 이름
# 상관계수: snack["가격"].corr(snack["판매량"])
# H-4: "비싸면 덜 팔릴까?" — 가격과 판매량의 산점도를 그리고 상관계수를 출력하세요.
# 힌트: plt.scatter(snack["가격"], snack["판매량"]) + 제목·축 이름
# 상관계수: snack["가격"].corr(snack["판매량"])
In [ ]:
Copied!
# H-5 (비율 트릭): 하루 매출이 10만 원 이상인 제품은 전체의 몇 %일까요?
# 힌트: (snack["매출"] >= ??).mean() — True=1, False=0
# H-5 (비율 트릭): 하루 매출이 10만 원 이상인 제품은 전체의 몇 %일까요?
# 힌트: (snack["매출"] >= ??).mean() — True=1, False=0
H-6 (자유 문제) — 사장님에게 한 가지 제안하기¶
이 데이터를 근거로 "어떤 제품을 더 들여놓거나 빼야 할지" 스스로 질문을 만들고, 코드로 근거를 찾은 뒤, 아래 셀 마지막에 제안 한 문장을 주석으로 쓰세요. (예: "잘 안 팔리는 에너지바를 빼고 아이스크림을 늘리자")
이 문제의 답변 구조가 그대로 면접 답변입니다: 데이터 → 근거 → 결론
In [ ]:
Copied!
# H-6: 나만의 질문 → 코드로 근거 → 제안 한 문장 (자유!)
# 내 질문:
# 코드:
# 제안(한 문장):
# H-6: 나만의 질문 → 코드로 근거 → 제안 한 문장 (자유!)
# 내 질문:
# 코드:
# 제안(한 문장):
심화 정답 보기 (H-1 ~ H-5)
snack.groupby("카테고리")["매출"].mean() # H-1 (아이스크림이 1위!)
snack.groupby("카테고리")["판매량"].agg(["mean", "max", "std"]) # H-2
top = snack.sort_values("매출", ascending=False) # H-3
plt.bar(top["제품"], top["매출"])
plt.title("제품별 매출 랭킹")
plt.ylabel("매출(원)")
plt.xticks(rotation=45)
plt.show()
plt.scatter(snack["가격"], snack["판매량"]) # H-4
plt.title("가격과 판매량의 관계")
plt.xlabel("가격(원)")
plt.ylabel("판매량(개)")
plt.show()
print("상관계수:", snack["가격"].corr(snack["판매량"]).round(2))
print((snack["매출"] >= 100000).mean()) # H-5 (0.25 = 25%)
H-4 해석 포인트: 상관계수는 음수지만 -1만큼 강하지 않습니다 — 월드콘처럼 비싼데 잘 팔리는 예외가 있기 때문입니다. "대체로 음의 관계지만 예외가 있다"라고 해석할 수 있습니다. H-6은 정답이 없습니다. 데이터 → 근거 → 결론 구조로 작성하면 됩니다.
완료한 노트북과 그래프는 파일 → 다운로드로 보관할 수 있습니다.