종합 성취도 평가 해설.
A. SQL (Q1–Q4)
Q1. AVG와 NULL 🧰 필수
테이블 t_score가 아래와 같을 때, 결과로 올바른 것은?
| score |
| 5 |
| NULL |
| 3 |
SELECT AVG(score) AS avg_score
FROM t_score;
A. 2.666…
B. 4.0
C. 8.0
D. NULL
답) B
NULL은 COUNT() 외의 집계함수에는 포함 x
Q2. BETWEEN 동작 🧰 필수
MySQL에서 BETWEEN에 대한 설명으로 가장 올바른 것은?
A. 시작값만 포함하고 끝값은 포함하지 않는다
B. 시작값/끝값을 모두 포함한다
C. 문자열에서는 동작하지 않는다
D. NULL이 있으면 항상 에러가 난다

답) B
동일한 의미라 시작값, 끝값 포함
Q3. 2026-01-03 Comedy 평점 리스트 🧰 필수
아래 조건을 만족하는 평점 리스트를 출력하는 SQL을 작성하세요.
- 대상 날짜: rated_at의 날짜가 '2026-01-03'
- 영화 조건: movies.genre = 'Comedy' AND movies.is_available = 1
- 평점 조건: review_status IN ('OK','SUSPECT')
- 평점값 조건: rating이 NULL이 아니어야 함
- 출력 컬럼:
- rated_at, city, title, rating, review_status
- 정렬: city 오름차순, user_id 오름차순
사용 테이블: ratings r / movies m / users u
[실행 결과]

답)
select
r.rated_at,
u.city,
m.title,
r.rating,
r.review_status
from ratings r
join movies m
on r.movie_id = m.movie_id
join users u
on r.user_id = u.user_id
where DATE(r.rated_at) = '2026-01-03'
and m.genre = 'Comedy'
and m.is_available = 1
and r.review_status in ('OK','SUSPECT')
and r.rating is not null
order by
u.city asc,
r.user_id asc;
is not null 누락 -> 결과 동일해도 조건 불일치로 오답
Q4. 도시별 평균 평점 TOP 1 🚀 도전
Q3과 동일한 필터 조건으로, 도시별 평균 평점을 구한 뒤 평균이 가장 높은 도시 1개만 출력하세요.
- 출력 컬럼:
- city
- avg_rating (소수 1자리 반올림)
- rating_cnt (해당 조건에 포함된 평점 개수)
- 정렬: avg_rating 내림차순, city 오름차순
- 결과는 1행만
[실행 결과]

답)
select
u.city,
round(avg(r.rating) ,1) as avg_rating,
count(*) as rating_cnt
from ratings r
join movies m
on r.movie_id = m.movie_id
join users u
on r.user_id = u.user_id
where DATE(r.rated_at) = '2026-01-03'
and m.genre = 'Comedy'
and m.is_available = 1
and r.review_status in ('OK','SUSPECT')
and r.rating is not null
group by u.city
order by
avg_rating desc,
u.city asc
limit 1;
is not null 누락 -> 결과 동일해도 조건 불일치로 오답
B. Python (Q5–Q8)
Q5. set의 길이 🧰 필수
s = {"a", "b", "a"}
print(len(s))
A. 3
B. 2
C. 1
D. 에러
답) B
집합 자료형은 갯수를 셀 때 중복을 제거한다.
Q6. 기본 인자 함정 🚀 도전
def add_item(x, items=[]):
items.append(x)
return items
print(add_item(1))
print(add_item(2))
A. [1] / [2]
B. [1] / [1, 2]
C. [] / [1, 2]
D. 에러
답) B
함수에서 기본 인자값이 리스트의 형태로 지정되어 있기에 함수 정의할 때, 처음 호출하면 할당, 그 이후에는 값이 누적으로 삽입된다.
Q7. 리뷰 상태가 BAD인지 판별 🧰 필수
아래 조건을 만족하는 함수 is_bad(review_status, rating)를 작성하세요.
- review_status == "BAD" 이면 True
- rating이 None이면 True
- 그 외는 False
예:
- is_bad("OK", 4) → False
- is_bad("BAD", 5) → True
- is_bad("OK", None) → True
답)
## Q7 튜터님 풀이
def is_bad(review_status, rating):
if review_status == "BAD":
return True
if rating == None:
return True
return False
Q8. None을 무시하고 합 구하기 🧰 필수
리스트 values에서 None은 무시하고 나머지 숫자만 합을 반환하는 함수 sum_ignore_none(values)를 작성하세요.
예:
- sum_ignore_none([1, None, 3]) → 4
답)
def sum_ignore_none(values):
total = 0
for value in values:
if value is None:
continue
total += value
return total
C. 전처리(Pandas) (Q9–Q14)
Q9. to_numeric + errors="coerce" 🧰 필수
import pandas as pd
s = pd.Series(["3", "x", "5"])
out = pd.to_numeric(s, errors="coerce")
print(out.tolist())
A. [3, 0, 5]
B. [3, "x", 5]
C. [3.0, nan, 5.0]
D. 에러
답) C
errors="coerce"는 숫자로 변환 불가능한 값을 nan으로 강제 변환
Q10. duplicated의 기본 keep 🧰 필수
import pandas as pd
df = pd.DataFrame({"user_id": ["U1", "U1", "U2"]})
print(df.duplicated(subset=["user_id"]).sum())
A. 0
B. 1
C. 2
D. 3
답) B
duplicated의 기본값 keep=first이다. (처음 나온 것은 유지, 나머지는 중복이라고 명시)
첫등장은 False라서 0, 중복 등장은 True라서 1이기에 0,1,0되서 sum()하면 1이 된다.
Q11. fillna(inplace=True) 반환값 🚀 도전
import pandas as pd
df = pd.DataFrame({"x": [1, None]})
result = df["x"].fillna(0, inplace=True)
print(result)
A. 0
B. [1, 0]
C. None
D. 에러
답) C
(함정문제) inplace=True는 원본을 바로 대체해서 작업할 것이라는 뜻
그래서 result로 받으면 None이 나온다. result로 받기 위해서는 fillna(0)이라고만 입력하면 된다.
inplace 쓰려면 result 제거, inplace 안쓰면 result 필요
Q12. 데이터 로드 & 기본 확인 🧰 필수
users.csv, movies.csv, ratings.csv를 불러오고 아래를 수행하세요.
- 각 데이터프레임의 shape 출력
- ratings에서 head(2) 출력
- (권장: ratings는 parse_dates=["rated_at"])
[실행결과]

답)
## Q12 튜터님 풀이
import pandas as pd
users_df = pd.read_csv("users.csv")
movies_df = pd.read_csv("movies.csv")
ratings_df = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
print(users_df.shape, movies_df.shape, ratings_df.shape)
ratings_df.head(2)
Q13. 중복 제거 + 숫자 변환 + 병합 + 필터 🧰 필수
아래 순서대로 처리하세요.
- ratings에서 (user_id, movie_id, rated_at) 기준 중복 개수 출력
- 위 기준으로 drop_duplicates(keep="first") 적용
- rating_num 컬럼 생성: pd.to_numeric(rating, errors="coerce")
- movies, users를 차례대로 left merge 해서 df_full 생성
- 아래 조건으로 필터링하여 df_clean 생성
- is_available == 1
- review_status가 OK 또는 SUSPECT
- rating_num이 결측치가 아님
- df_clean의 행 개수 출력
[실행 결과]

답)
result = (
df_clean.groupby(['city','genre'])
.agg(
rating_cnt = ('rating_num','size'),
avg_rating = ('rating_num', 'mean')
)
.reset_index()
)
result['avg_rating'] = result['avg_rating'].round(1)
result = result.sort_values(['city','genre'], ascending=[True, True])
result
D. 시각화(Matplotlib/Seaborn) (Q15–Q18)
Q15. boxplot 해석 🧰 필수
boxplot(박스플롯)에 대한 설명으로 가장 올바른 것은?
A. 박스는 평균을 의미한다
B. 박스는 사분위수(분포의 일부)를, 수염은 나머지 분포(이상치 제외)를 표현한다
C. 수염은 항상 최소/최대값이다
D. boxplot은 범주형 데이터에만 쓸 수 있다
답) B
박스 = 사분위수
수염 = 이상치 제외 나머지 분포
수염 밖 값 = 이상치
Q16. x축 라벨 겹침 해결 🧰 필수
날짜 라벨이 겹칠 때 가장 흔한 해결 방법은?
A. plt.xticks(rotation=45) 또는 ax.tick_params(rotation=45)
B. df.reset_index()
C. df.astype(int)
D. plt.legend()
답) A
라벨이 겹치면 각도 조절 혹은 공간을 넓혀야 한다.
B,C 는 판다스
D는 범례 설정에 사용
Q17. 평점 분포 히스토그램 🧰 필수
ratings.csv를 불러온 뒤, 아래 조건에 맞는 평점(rating)의 분포를 히스토그램으로 시각화하세요.
- 데이터 로드
- ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"]) 권장
- 포함 조건(필터)
- review_status가 "OK" 또는 "SUSPECT"
- rating이 결측치가 아닌 행만
- 중복 제거는 하지 않습니다(그대로 사용)
- 그래프 요구사항
- 히스토그램(histogram) 형태 (seaborn의 histplot 사용 가능)
- 제목/축 라벨 포함
- (권장) plt.tight_layout() 적용, bin = 5 권장
[실행 결과] - bin에 따라 모양은 달라질 수 있음.

답)
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
df = ratings[
ratings["review_status"].isin(["OK", "SUSPECT"]) &
ratings["rating"].notna()
].copy()
plt.figure(figsize=(6, 4))
sns.histplot(data=df, x="rating", bins=5)
plt.title("Rating Distribution (OK/SUSPECT)")
plt.xlabel("Rating")
plt.ylabel("Count")
plt.tight_layout()
plt.show()
Q18. 리뷰 상태별 평점 개수 막대그래프 🧰 필수
ratings.csv를 불러온 뒤, review_status별 평점(리뷰) 개수를 막대그래프로 시각화하세요.
요구사항
- 데이터 로드
- ratings = pd.read_csv("ratings.csv")
- (선택) parse_dates=["rated_at"]를 사용해도 OK
- 집계/그래프
- x: review_status
- y: 각 상태의 개수(count)
- seaborn의 countplot 사용 권장 (사전 집계 없이 자동 count)
- 그래프 꾸미기(최소)
- 제목(title), x/y 축 라벨(label) 포함
- plt.tight_layout() 적용
- 다만, 그래프가 보여질 때 왼쪽부터 OK, SUSPECT, BAD 순이어야 한다.
[실행 결과]

답)
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
ratings = pd.read_csv("ratings.csv", parse_dates=["rated_at"])
plt.figure(figsize=(6,4))
sns.countplot(data=ratings, x='review_status', order=['OK','SUSPECT','BAD'])
plt.title('Count of Ratings By Review Status')
plt.xlabel('review_status')
plt.ylabel('count')
plt.tight_layout()
plt.show()'내일배움캠프' 카테고리의 다른 글
| [내일배움캠프] TIL 26일차 26.02.05(목) (0) | 2026.02.05 |
|---|---|
| [내일배움캠프] TIL 25일차 26.02.04(수) (0) | 2026.02.04 |
| [내일배움캠프] TIL 23일차 26.01.23(금) (0) | 2026.01.23 |
| [내일배움캠프] TIL 22일차 26.01.22(목) (0) | 2026.01.22 |
| [내일배움캠프] TIL 21일차 26.01.21(수) (0) | 2026.01.21 |