{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2025학년도 1학기 중간고사 - 데이터과학\n\n**서울과학고등학교** | 2025년 4월 17일 2교시 시행\n\n- 문항수: 서술/논술형 (4)\n- 코드의 컴파일 환경은 Google Colaboratory를 기준으로 하며, 라이브러리는 이미 import 된 것으로 간주합니다.\n- 총점: 100점"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\n# 한글 폰트 설정 (Google Colab 환경)\nplt.rcParams['font.family'] = 'DejaVu Sans'\n# 로컬 환경에서는 아래 주석을 해제하세요\n# plt.rcParams['font.family'] = 'Malgun Gothic'  # Windows\n# plt.rcParams['font.family'] = 'AppleGothic'    # Mac\nplt.rcParams['axes.unicode_minus'] = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n## 1번 문제 [서술형 10점]\n\n다음 <기사>를 참고하여 **(가)**의 의미와 **데이터 시각화**의 의미를 서술하시오.\n이 외에도 데이터로 할 수 있는 일을 **<보기>**와 연관지어 **두 가지**로 설명하시오.\n\n### <기사>\n> **디즈니 애니메이션의 성별 대사 비중 논란: 팬의 목소리**\n>\n> 최근 디즈니 애니메이션의 성별 대사 비중에 대한 논란이 일고 있다.\n> 한 디즈니 애니메이션 팬은 이 문제에 대해 깊은 우려를 표명하며,\n> **(가)** 을 지적했다.\n> 이 팬은 특히 자신이 좋아하는 여자 캐릭터가 주인공인 영화에서도\n> **(가)** 라는 사실을 강조했다.\n> 그는 \"디즈니 애니메이션을 좋아하는 팬으로서, 영화를 보면 남녀 성우의 비율을 확인할 수 있다\"며,\n> 이러한 불균형이 팬들에게 미치는 영향을 우려했다.\n\n### <디즈니 애니메이션의 성별 대사 비중 다이어그램>\n| 작품 | 남자성우비율 | 여자성우비율 |\n|------|------------|------------|\n| 겨울왕국 | 57 | 43 |\n| 미녀와야수 | 70 | 30 |\n| 인어공주 | 71 | 29 |\n| 뮬란 | 74 | 26 |\n\n### <보기>\n- **1854년 Broad 가의 콜레라 발병 맵**: 존 스노우는 런던의 콜레라 발병 원인을 시각화하여 오염된 우물과 질병 간의 관계를 밝혀냄.\n- **크림 전쟁 당시 사망 원인**: 나이팅게일은 크림 전쟁 중 비위생적인 병원 상태가 군인 사망률 증가의 주요 원인임을 데이터 시각화를 통해 밝혀냄."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1번 답안 작성\n\n# (가)의 의미:\n# 답: \n\n# 데이터 시각화의 의미:\n# 답: \n\n# 데이터로 할 수 있는 일 (보기와 연관지어 두 가지):\n# 1) \n# 2) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n## 2번 문제 [서술형 13점]\n\n다음은 넘파이 배열(ndarray)을 활용해 작성된 코드이다.\n(1) ~ (3)를 순서대로 실행할 때, 각 물음에 답하시오."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2번 공통 코드\na = np.arange(9).reshape(3, -1)\nb = np.ones((3, 3), dtype=int)\nprint('a =', a)\nprint('b =', b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2-(1) [4점]\n다음 <코드>의 실행 결과를 작성하시오.\n```python\n2*a + 7*b\n```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2-(1) 실행 결과를 예측한 후, 아래 코드를 실행하여 확인하세요.\n\n# 예측한 답:\n# \n\n# 실행하여 확인\n2*a + 7*b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2-(2) [4점]\n다음 <코드>를 실행한 후, c, d에 저장되는 값을 작성하시오.\n```python\nc = a[0::2, 0:2:]\nd = a[[0, 2], [0, 1]].reshape(-1, 2)\n```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2-(2) c, d의 값을 예측한 후, 아래 코드를 실행하여 확인하세요.\n\n# c의 예측값:\n# \n# d의 예측값:\n# \n\n# 실행하여 확인\nc = a[0::2, 0:2:]\nd = a[[0, 2], [0, 1]].reshape(-1, 2)\nprint('c =', c)\nprint('d =', d)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2-(3) [5점]\n다음 <코드>의 실행 결과를 작성하시오.\n```python\na[np.where(a[0:2, [0,1]] >= 3)]\n```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2-(3) 실행 결과를 예측한 후, 아래 코드를 실행하여 확인하세요.\n\n# 예측한 답:\n# \n\n# 실행하여 확인\na[np.where(a[0:2, [0,1]] >= 3)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n## 3번 문제 [서술형 37점]\n\n다음은 미국 전역에서 판매된 물건 데이터 `sales.csv`의 일부이다.\ncsv파일의 값을 Pandas DataFrame 변수 `df`에 저장하였을 때, 각 물음에 대한 답을 구하시오.\n\n단, (1) ~ (6) 순서대로 실행하며, DataFrame df의 명시적 인덱스(Explicit Index)는 설정하지 않았다.\n\n| 컬럼 | 설명 |\n|------|------|\n| Order ID | 주문 아이디 |\n| Order Date, Ship Date | 주문날짜, 배송날짜 (일/월/연도 형식) |\n| Customer ID | 고객 아이디 |\n| City, State | 주문 도시, 주문 주(행정구역) |\n| Product ID | 제품 아이디 |\n| Category, Sub-Category | 범주, 하위 범주 |\n| Sales | 판매량 |\n\n\\* Sales 칼럼은 float64 타입, 그 외 칼럼은 모두 object 타입임."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 데이터 로드\ndf = pd.read_csv('sales.csv')\ndf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(1) [4점]\n\n인덱스 1행의 결측값을 채우려고 한다. 동일한 Order ID를 가진 행의 Order Date값을 대입하는 코드를 작성하시오.\n(단, `.iloc[]` 표기를 사용할 것.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(1) 아래에 코드를 작성하세요.\n\n\n\n# 확인\ndf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(2) [5점]\n\nOrder Date 칼럼에서 결측값이 들어있는 행을 삭제하고 <결과>와 같이 변수 df에 반영하는 코드를 작성하시오."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(2) 아래에 코드를 작성하세요.\n\n\n\n# 확인\ndf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(3) [6점]\n\nOrder Date, Ship Date 칼럼의 자료형을 datetime으로 변환하시오.\n(단, 매개변수 `dayfirst`를 사용할 것.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(3) 아래에 코드를 작성하세요.\n\n\n\n# 확인\ndf.dtypes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(4) [8점]\n\n다음은 Maine주의 Sub-Category 칼럼별로 최소 배송 시간을 구하는 과정을 두 단계로 구분한 것이다.\n각 단계별로 필요한 코드를 작성하시오.\n\n**<단계1>** delivery time 칼럼을 추가하고, Maine주에 해당하는 데이터프레임을 선언한다.\n- 배송 시간 칼럼: 배송 날짜 칼럼에서 주문 날짜 칼럼을 뺌\n- `df_Maine = df[df['State'] == 'Maine']`\n\n**<단계2>** 각 서브 카테고리별 최소 배송 시간을 계산하고, 최소 배송 시간을 기준으로 오름차순으로 정렬"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(4) 아래에 코드를 작성하세요.\n\n# <단계1> delivery time 칼럼 추가 및 Maine 데이터프레임 생성\n\n\n\n# <단계2> 서브 카테고리별 최소 배송 시간 (오름차순 정렬)\n\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(5) [6점]\n\nOrder Date 칼럼을 이용하여 Year, Month, Day 칼럼을 생성한 후, 변수 df에 반영하는 코드를 작성하시오.\n(단, 새롭게 만든 칼럼들은 정수형 자료형으로 생성할 것.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(5) 아래에 코드를 작성하세요.\n\n\n\n\n# 확인\ndf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3-(6) [8점]\n\na 문자가 있는 State별 최고 판매액을 파악하고자 다음 단계를 차례로 수행한다.\n\n- **<단계1>** State별 최대 Sales를 `max_df`에 저장한다. 기본 정수 인덱스로 재설정하며, `max_df`의 칼럼의 이름을 변경한다.\n- **<단계2>** `max_df`에서 Max_Sales를 기준으로 내림차순으로 정렬한다.\n- **<단계3>** State 칼럼에 `a`를 포함하고 `Max_Sales`의 값이 10499.970이상인 `max_df`의 내용을 출력한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3-(6) 아래에 코드를 작성하세요.\n\n# <단계1>\n\n\n# <단계2>\n\n\n# <단계3>\n\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n## 4번 문제 [서술형 40점]\n\n다음은 서울시내에 위치한 공영주차장에 대한 정보를 제공하는 **서울시공영주차장안내정보.csv**의 일부이다.\ncsv 파일의 값을 Pandas DataFrame 변수 `df`에 저장하였을 때, 각 물음에 대한 답을 구하시오.\n\n단, (1) ~ (6) 순서대로 실행되고, DataFrame df의 명시적 인덱스(Explicit Index)는 설정하지 않았다.\n\n| 컬럼 | 타입 |\n|------|------|\n| 주차장코드 | int64 |\n| 주차장명, 주소 | object |\n| 그 외 칼럼 | float64 |\n\n\\* 유무료구분 칼럼의 값은 Y 또는 N 임.\n\n출처: 서울 열린데이터 광장"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 데이터 로드\ndf = pd.read_csv('서울시공영주차장안내정보.csv')\ndf.head(6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(1) [4점]\n\n주차장명 칼럼의 (시), (구)는 주차장 종류를 구분한다.\n주차장 이름만 드러나도록 (시)와 (구)를 제거하여 df에 반영하는 코드를 작성하시오."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(1) 아래에 코드를 작성하세요.\n# 힌트: str.replace()를 사용하세요.\n\n\n\n# 확인\ndf.head(6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(2) [4점]\n\ndf에 주소 칼럼을 토대로 새로운 **지역구** 칼럼을 생성하는 코드를 작성하시오.\n\n(예: \"노원구 상계동 770-2\" → \"노원구\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(2) 아래에 코드를 작성하세요.\n\n\n\n# 확인\ndf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(3) [9점]\n\ndf의 중복된 주차장코드가 존재하는 <현재 상태>를 <목표 상태>로 전처리하려고 한다.\n다음 <규칙>에 따라 df가 주차장코드별 하나의 대표 행으로만 이루어져있도록 코드를 작성하시오.\n\n**<규칙>**\n- 위도나 경도 중 하나라도 결측치가 있는 행은 삭제한다.\n- 대표 행의 위도, 경도는 주차장코드가 같은 그룹의 위도, 경도 중간값으로 한다.\n- 대표 행의 총 주차면은 주차장코드가 같은 그룹의 총 주차면 합계로 계산한다.\n- 대표 행의 나머지 속성은 주차장코드가 같은 그룹의 첫 번째 값을 그대로 유지한다. (단, lambda와 .iloc[] 사용할 것)\n- 인덱스는 다시 0부터 시작하여 재설정한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(3) 아래에 코드를 작성하세요.\n\n\n\n\n\n\n\n\n\n\n\n\n# 확인\ndf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(4) [6점]\n\n지역구 칼럼별 총 주차면이 가장 많은 주차장을 찾아 정보를 추출하는 코드를 작성하시오.\n(단, `.loc[]`를 사용할 것.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(4) 아래에 코드를 작성하세요.\n\n\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(5) [8점]\n\n<결과>와 같이 지역구 칼럼의 값이 **중구**인 곳의 유료 주차장과 무료 주차장의 비율을 시각화하는 코드를 작성하시오.\n\n- 파이 차트 사용\n- 비율은 소수점 둘째 자리까지 표시 (예: 67.80%)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(5) 아래에 코드를 작성하세요.\n\n\n\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4-(6) [9점]\n\n각 주차장에서 1시간(60분) 주차할 경우 내야 하는 요금 정보를 계산하려고 한다.\n주차 요금을 계산할 때 <예시>와 같이 기본 주차 시간이 주차시간보다 작거나 같은 경우에는 기본 요금만 부과하고,\n초과한 시간에 대해서는 추가 단위 시간마다 추가 요금을 올림 처리하여 계산한다.\n\n각 <단계>별 설명에 따라 필요한 코드를 작성하시오.\n\n| | 기본 주차 요금 | 기본 주차 시간(분 단위) | 추가 단위 요금 | 추가 단위 시간(분 단위) |\n|---|---|---|---|---|\n| A주차장 | 3000.0 | 30.0 | 1000.0 | 10.0 |\n| B주차장 | 10000.0 | 90.0 | 100.0 | 10.0 |\n\nA주차장에서의 주차시간이 55분일 때 요금은 6000원이고, B주차장에서의 주차시간이 70분일 때 요금은 10000원임.\n\n**<단계1>** 유무료구분이 N인 경우(무료 주차장)나 추가 단위 시간(분 단위)과 추가 단위 요금 중 하나라도 0인 행을 제외한 새로운 데이터프레임 `df_fee`를 생성한다.\n\n**<단계2>** `df_fee`에 각 주차장에 대한 주차요금을 계산한 **1시간 요금(원)** 칼럼을 추가한다. (단, `np.where()`를 사용할 것.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4-(6) 아래에 코드를 작성하세요.\n\n# <단계1>\n\n\n\n# <단계2>\n\n\n\n# 확인\ndf_fee[['주차장명', '기본 주차 요금', '기본 주차 시간(분 단위)', '추가 단위 요금', '추가 단위 시간(분 단위)', '1시간 요금(원)']].head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n## Numpy & Pandas Cheat Sheet\n\n### <numpy>\n| 함수 | 설명 |\n|------|------|\n| `np.zeros(3)` | 0으로 채운 배열 |\n| `np.ones((3,4))` | 1로 채운 배열 |\n| `np.eye(5)` | 단위행렬 |\n| `np.linspace(0,100,6)` | 등간격 배열 |\n| `np.arange(0,10,3)` | range 배열 |\n| `np.full((2,3),8)` | 특정값 배열 |\n| `arr.reshape(3,4)` | 형태 변환 |\n| `arr.T` | 전치 |\n| `np.where(조건)` | 조건 인덱스 |\n| `np.ceil()` | 올림 |\n| `arr[0:3]` | 슬라이싱 |\n\n### <pandas>\n| 함수 | 설명 |\n|------|------|\n| `df.head()` | 상위 행 |\n| `df.info()` | 정보 |\n| `df.describe()` | 통계 |\n| `df.iloc[0:3, 0:2]` | 위치 인덱싱 |\n| `df.loc[:, ['col1','col2']]` | 레이블 인덱싱 |\n| `df.dropna(subset=['col'])` | 결측치 삭제 |\n| `df.fillna(value)` | 결측치 채우기 |\n| `df.groupby('c1')['c2'].mean()` | 그룹별 평균 |\n| `df.sort_values('col')` | 정렬 |\n| `s.str.replace('a','b')` | 문자열 치환 |\n| `s.str.split(' ')` | 문자열 분리 |\n| `s.str.contains('val')` | 문자열 포함 |\n| `s.dt.year` | 연도 추출 |\n| `pd.to_datetime(col)` | datetime 변환 |\n| `df.plot(kind='pie')` | 파이 차트 |"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}