{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2eacb71c",
   "metadata": {},
   "source": [
    "# 02 분석 — 대분류 취업계수, 추세 연장, 산업별 취업자 전망\n",
    "\n",
    "**계산 구조.** 대분류 $s$의 연도 $y$ 취업계수는 취업자 $L_{s,y}$(천 명)를 소속 산업 실질부가가치 합계(십억 원)로 나눈 값이다.\n",
    "\n",
    "$$c_{s,y} = \\frac{L_{s,y}}{\\sum_{i \\in s} Y_{i,y}}$$\n",
    "\n",
    "기준 수준 $b_s$는 2023–2025년 3개년 합계 취업자를 같은 기간 합계 부가가치로 나눈 값이고, 기준 기간의 중앙 연도인 2024년에 둔다.\n",
    "추세 $g_s$는 2013–2025년 $\\ln c_{s,y}$를 연도에 회귀한 최소제곱 기울기(연간 로그변화율)이다.\n",
    "\n",
    "$$b_s = \\frac{\\sum_{y=2023}^{2025} L_{s,y}}{\\sum_{y=2023}^{2025} \\sum_{i \\in s} Y_{i,y}}, \\qquad\n",
    "\\ln c_{s,y} = \\alpha_s + g_s\\, y + e_{s,y}, \\qquad\n",
    "c_{s,t} = b_s \\exp\\{g_s (t - 2024)\\}$$\n",
    "\n",
    "시나리오 $k$(S1–S5)의 산업 $i$ 취업자 전망은 소속 대분류의 계수 경로에 시나리오 실질부가가치를 곱한 값이다.\n",
    "\n",
    "$$\\hat L^{k}_{i,t} = c_{s(i),t} \\times Y^{k}_{i,t}, \\qquad t = 2026, \\dots, 2035$$\n",
    "\n",
    "같은 대분류에 속한 산업은 같은 계수를 쓰므로, 대분류 안의 산업별 취업자 비중은 실질부가가치 비중과 같다.\n",
    "2025년 산업별 실적도 같은 원칙으로 대분류 취업자를 2025년 실질부가가치 비중으로 나누어 정한다(대분류가 산업 하나이면 실측치와 같다).\n",
    "\n",
    "**2026-10 정비판.** 계수 경로(1–2절)는 이전 판과 같다. 주 산출물의 투입 부가가치만 5장 정비판 최종 전망으로 바뀌었다.\n",
    "\n",
    "| 산출물 | 투입 부가가치 | 파일 |\n",
    "|---|---|---|\n",
    "| **주 산출물(정비판)** | 보고서1 5장 2026-10 정비판 최종 전망(연간) | `labor_demand_36.csv`, `labor_demand_viewer_data.json`, `labor_actual_2025_36.csv` |\n",
    "| 이전 판(2026-10-08 판) 재현 | 정비 이전 5장 최종 전망(연간, 2026-09-03 판) | `labor_demand_36_prev.csv`, `labor_demand_viewer_data_prev.json` |\n",
    "| 최초 판(v0) 재현 | 정합화 이전 분기 전망(2026-08-04 게시) | `labor_demand_36_v0.csv`, `labor_demand_viewer_data_v0_pre-reconciliation.json` |\n",
    "\n",
    "그 밖의 산출물: `coef_history.csv`, `coef_params.csv`, `coef_path.csv`, `spec_comparison.csv`, `vintage_comparison.csv`\n",
    "\n",
    "> **재구성 안내.** 2026-08-04 게시 자료(최초 판)를 만든 프로그램은 프로젝트 폴더·작업 기록·포털 서버 어디에서도 찾지 못했다.\n",
    "> 이 노트북의 계산은 뷰어 설명문과 게시 수치에서 방법을 역산해 다시 작성한 것이다. 6절은 같은 방법에 최초 판 투입을 넣으면 게시 파일이 바이트 단위로 재현됨을,\n",
    "> 7절은 대안 명세 가운데 이 명세만 게시 수치를 그대로 재현함을 보인다. 이전 판과 정비판은 같은 방법에 투입 부가가치만 바꾼 것이며, 5절은 이전 판 산출 파일이 바이트 단위로 재현됨을 보인다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "54299b50",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:53.673517Z",
     "iopub.status.busy": "2026-10-08T00:07:53.673017Z",
     "iopub.status.idle": "2026-10-08T00:07:54.141291Z",
     "shell.execute_reply": "2026-10-08T00:07:54.141291Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python 3.12.10 · pandas 2.2.3 · numpy 2.4.6 · matplotlib 3.11.0\n",
      "  스위치: ONLINE=0 · FULL=0 · API_KEY_BOK 없음\n",
      "  취업자(분기)            있음  data\\inputs\\emp_section_q.csv\n",
      "  실질VA 이력(분기)        있음  data\\inputs\\va36_hist_q.csv\n",
      "  주 투입: 정비판 VA       있음  data\\inputs\\va36_reconciled_annual.csv\n",
      "  이전 판 투입: VA        있음  data\\published_prev\\va36_reconciled_annual_prev.csv\n",
      "  이전 판 산출 JSON       있음  data\\published_prev\\labor_demand_viewer_data_prev.json\n",
      "  최초 판 투입: 분기 VA     있음  data\\inputs\\scenario_viewer_39q_data.json\n",
      "  최초 판 게시 JSON       있음  data\\published\\labor_demand_viewer_data_v0_pre-reconciliation.json\n",
      "  산업 대응표             있음  data\\section_map_36_19.csv\n"
     ]
    }
   ],
   "source": [
    "import os, json\n",
    "import numpy as np, pandas as pd\n",
    "import config as C\n",
    "import labor_demand as F\n",
    "pd.set_option(\"display.float_format\", lambda v: f\"{v:,.3f}\")\n",
    "C.setup()\n",
    "emp_a = pd.read_csv(os.path.join(C.INTERIM, \"emp_section_annual_sa.csv\"), index_col=0)\n",
    "emp_n = pd.read_csv(os.path.join(C.INTERIM, \"emp_section_annual_nsa.csv\"), index_col=0)\n",
    "va_a = pd.read_csv(os.path.join(C.INTERIM, \"va36_hist_annual.csv\"), index_col=0)\n",
    "smap = pd.read_csv(C.SECTION_MAP, dtype={\"산업코드\": str})\n",
    "sec_of = dict(zip(smap[\"산업명\"], smap[\"대분류\"]))\n",
    "sec_name = dict(zip(smap[\"대분류\"], smap[\"대분류명\"]))\n",
    "def wide(path):\n",
    "    d = pd.read_csv(path)\n",
    "    return {s: g.pivot(index=\"연도\", columns=\"산업\", values=\"실질VA_십억원\") for s, g in d.groupby(\"시나리오\")}\n",
    "recon = wide(os.path.join(C.INTERIM, \"va36_recon_annual.csv\"))            # 주 투입(정비판)\n",
    "recon_prev = wide(os.path.join(C.INTERIM, \"va36_recon_prev_annual.csv\"))  # 이전 판 투입\n",
    "scen_a = wide(os.path.join(C.INTERIM, \"va36_scen_annual.csv\"))            # 최초 판 투입\n",
    "va_sec = F.section_va(va_a, sec_of)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad1dc7b4",
   "metadata": {},
   "source": [
    "## 1. 대분류별 취업계수 이력(2013–2025)\n",
    "\n",
    "표의 단위는 실질부가가치 10억 원당 취업자 수(명)이다(천 명/십억 원 × 1,000)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9d42970f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.142294Z",
     "iopub.status.busy": "2026-10-08T00:07:54.142294Z",
     "iopub.status.idle": "2026-10-08T00:07:54.152663Z",
     "shell.execute_reply": "2026-10-08T00:07:54.152163Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>연도</th>\n",
       "      <th>2013</th>\n",
       "      <th>2016</th>\n",
       "      <th>2019</th>\n",
       "      <th>2022</th>\n",
       "      <th>2023</th>\n",
       "      <th>2024</th>\n",
       "      <th>2025</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A 농업, 임업 및 어업</th>\n",
       "      <td>43.860</td>\n",
       "      <td>37.780</td>\n",
       "      <td>40.130</td>\n",
       "      <td>45.070</td>\n",
       "      <td>45.470</td>\n",
       "      <td>44.340</td>\n",
       "      <td>41.070</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>B 광업</th>\n",
       "      <td>7.090</td>\n",
       "      <td>8.770</td>\n",
       "      <td>8.220</td>\n",
       "      <td>5.040</td>\n",
       "      <td>4.290</td>\n",
       "      <td>4.960</td>\n",
       "      <td>6.410</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>C 제조업</th>\n",
       "      <td>9.140</td>\n",
       "      <td>9.110</td>\n",
       "      <td>8.200</td>\n",
       "      <td>7.670</td>\n",
       "      <td>7.500</td>\n",
       "      <td>7.080</td>\n",
       "      <td>6.760</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>D 전기, 가스, 증기 및 공기조절 공급업</th>\n",
       "      <td>3.110</td>\n",
       "      <td>2.880</td>\n",
       "      <td>2.310</td>\n",
       "      <td>2.310</td>\n",
       "      <td>2.490</td>\n",
       "      <td>2.430</td>\n",
       "      <td>2.560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>E 수도, 하수 및 폐기물 처리, 원료 재생업</th>\n",
       "      <td>7.540</td>\n",
       "      <td>8.240</td>\n",
       "      <td>9.980</td>\n",
       "      <td>11.260</td>\n",
       "      <td>10.750</td>\n",
       "      <td>10.150</td>\n",
       "      <td>10.900</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>F 건설업</th>\n",
       "      <td>19.750</td>\n",
       "      <td>17.310</td>\n",
       "      <td>18.240</td>\n",
       "      <td>19.250</td>\n",
       "      <td>19.290</td>\n",
       "      <td>19.500</td>\n",
       "      <td>20.170</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>G 도매 및 소매업</th>\n",
       "      <td>25.070</td>\n",
       "      <td>23.690</td>\n",
       "      <td>21.090</td>\n",
       "      <td>18.190</td>\n",
       "      <td>18.590</td>\n",
       "      <td>18.570</td>\n",
       "      <td>18.230</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>H 운수 및 창고업</th>\n",
       "      <td>21.790</td>\n",
       "      <td>20.420</td>\n",
       "      <td>18.590</td>\n",
       "      <td>20.000</td>\n",
       "      <td>17.010</td>\n",
       "      <td>15.760</td>\n",
       "      <td>15.490</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>I 숙박 및 음식점업</th>\n",
       "      <td>45.290</td>\n",
       "      <td>48.960</td>\n",
       "      <td>45.550</td>\n",
       "      <td>43.660</td>\n",
       "      <td>46.650</td>\n",
       "      <td>47.160</td>\n",
       "      <td>47.400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>J 정보통신업</th>\n",
       "      <td>10.260</td>\n",
       "      <td>10.520</td>\n",
       "      <td>10.050</td>\n",
       "      <td>9.810</td>\n",
       "      <td>9.910</td>\n",
       "      <td>10.430</td>\n",
       "      <td>10.510</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>K 금융 및 보험업</th>\n",
       "      <td>11.100</td>\n",
       "      <td>8.790</td>\n",
       "      <td>7.660</td>\n",
       "      <td>6.040</td>\n",
       "      <td>6.180</td>\n",
       "      <td>6.100</td>\n",
       "      <td>6.160</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>L 부동산업</th>\n",
       "      <td>3.390</td>\n",
       "      <td>3.380</td>\n",
       "      <td>3.580</td>\n",
       "      <td>3.440</td>\n",
       "      <td>3.300</td>\n",
       "      <td>3.220</td>\n",
       "      <td>3.250</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>M 전문, 과학 및 기술 서비스업</th>\n",
       "      <td>14.150</td>\n",
       "      <td>13.480</td>\n",
       "      <td>13.410</td>\n",
       "      <td>13.430</td>\n",
       "      <td>13.610</td>\n",
       "      <td>14.300</td>\n",
       "      <td>14.880</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>N 사업시설 관리, 사업 지원 및 임대 서비스업</th>\n",
       "      <td>23.820</td>\n",
       "      <td>22.970</td>\n",
       "      <td>18.720</td>\n",
       "      <td>21.070</td>\n",
       "      <td>20.140</td>\n",
       "      <td>19.750</td>\n",
       "      <td>19.650</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>O 공공행정, 국방 및 사회보장 행정</th>\n",
       "      <td>9.490</td>\n",
       "      <td>8.970</td>\n",
       "      <td>8.800</td>\n",
       "      <td>9.060</td>\n",
       "      <td>8.970</td>\n",
       "      <td>9.040</td>\n",
       "      <td>9.020</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>P 교육 서비스업</th>\n",
       "      <td>20.610</td>\n",
       "      <td>21.260</td>\n",
       "      <td>20.480</td>\n",
       "      <td>19.260</td>\n",
       "      <td>18.960</td>\n",
       "      <td>18.880</td>\n",
       "      <td>19.370</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Q 보건업 및 사회복지 서비스업</th>\n",
       "      <td>23.160</td>\n",
       "      <td>22.740</td>\n",
       "      <td>21.140</td>\n",
       "      <td>22.750</td>\n",
       "      <td>23.280</td>\n",
       "      <td>23.000</td>\n",
       "      <td>23.490</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>R 예술, 스포츠 및 여가관련 서비스업</th>\n",
       "      <td>17.600</td>\n",
       "      <td>18.170</td>\n",
       "      <td>18.240</td>\n",
       "      <td>19.350</td>\n",
       "      <td>18.170</td>\n",
       "      <td>18.640</td>\n",
       "      <td>19.830</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S 협회 및 단체, 수리 및 기타 개인 서비스업</th>\n",
       "      <td>43.460</td>\n",
       "      <td>40.480</td>\n",
       "      <td>42.330</td>\n",
       "      <td>40.940</td>\n",
       "      <td>39.590</td>\n",
       "      <td>37.890</td>\n",
       "      <td>38.610</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "연도                           2013   2016   2019   2022   2023   2024   2025\n",
       "A 농업, 임업 및 어업              43.860 37.780 40.130 45.070 45.470 44.340 41.070\n",
       "B 광업                        7.090  8.770  8.220  5.040  4.290  4.960  6.410\n",
       "C 제조업                       9.140  9.110  8.200  7.670  7.500  7.080  6.760\n",
       "D 전기, 가스, 증기 및 공기조절 공급업     3.110  2.880  2.310  2.310  2.490  2.430  2.560\n",
       "E 수도, 하수 및 폐기물 처리, 원료 재생업   7.540  8.240  9.980 11.260 10.750 10.150 10.900\n",
       "F 건설업                      19.750 17.310 18.240 19.250 19.290 19.500 20.170\n",
       "G 도매 및 소매업                 25.070 23.690 21.090 18.190 18.590 18.570 18.230\n",
       "H 운수 및 창고업                 21.790 20.420 18.590 20.000 17.010 15.760 15.490\n",
       "I 숙박 및 음식점업                45.290 48.960 45.550 43.660 46.650 47.160 47.400\n",
       "J 정보통신업                    10.260 10.520 10.050  9.810  9.910 10.430 10.510\n",
       "K 금융 및 보험업                 11.100  8.790  7.660  6.040  6.180  6.100  6.160\n",
       "L 부동산업                      3.390  3.380  3.580  3.440  3.300  3.220  3.250\n",
       "M 전문, 과학 및 기술 서비스업         14.150 13.480 13.410 13.430 13.610 14.300 14.880\n",
       "N 사업시설 관리, 사업 지원 및 임대 서비스업 23.820 22.970 18.720 21.070 20.140 19.750 19.650\n",
       "O 공공행정, 국방 및 사회보장 행정        9.490  8.970  8.800  9.060  8.970  9.040  9.020\n",
       "P 교육 서비스업                  20.610 21.260 20.480 19.260 18.960 18.880 19.370\n",
       "Q 보건업 및 사회복지 서비스업          23.160 22.740 21.140 22.750 23.280 23.000 23.490\n",
       "R 예술, 스포츠 및 여가관련 서비스업      17.600 18.170 18.240 19.350 18.170 18.640 19.830\n",
       "S 협회 및 단체, 수리 및 기타 개인 서비스업 43.460 40.480 42.330 40.940 39.590 37.890 38.610"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coef = F.coefficients(emp_a, va_sec, range(C.HIST_START, C.HIST_END + 1))\n",
    "coef.to_csv(os.path.join(C.OUTPUT, \"coef_history.csv\"), encoding=\"utf-8-sig\")\n",
    "(coef * 1000).T.rename(index=lambda s: f\"{s} {sec_name[s]}\")[[2013, 2016, 2019, 2022, 2023, 2024, 2025]].round(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2effab7c",
   "metadata": {},
   "source": [
    "## 2. 기준 수준과 추세\n",
    "\n",
    "$g_s$가 음수이면 같은 부가가치를 만드는 데 필요한 취업자가 해마다 줄어든다는 뜻이다(노동생산성 상승). 추세 결정계수($R^2$)가 낮은 대분류는\n",
    "2013–2025년 계수의 움직임이 직선 추세로 잘 설명되지 않는 경우이며, 이때도 추정 기울기를 그대로 연장한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8d13da35",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.153663Z",
     "iopub.status.busy": "2026-10-08T00:07:54.153163Z",
     "iopub.status.idle": "2026-10-08T00:07:54.165934Z",
     "shell.execute_reply": "2026-10-08T00:07:54.165934Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>대분류명</th>\n",
       "      <th>2025 실적 계수(명/10억원)</th>\n",
       "      <th>기준 수준(명/10억원, 2024)</th>\n",
       "      <th>연간 로그변화율(%)</th>\n",
       "      <th>추세 R²</th>\n",
       "      <th>2035 계수(명/10억원)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A</th>\n",
       "      <td>농업, 임업 및 어업</td>\n",
       "      <td>41.075</td>\n",
       "      <td>43.622</td>\n",
       "      <td>1.032</td>\n",
       "      <td>0.291</td>\n",
       "      <td>48.867</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>B</th>\n",
       "      <td>광업</td>\n",
       "      <td>6.414</td>\n",
       "      <td>5.147</td>\n",
       "      <td>-3.484</td>\n",
       "      <td>0.236</td>\n",
       "      <td>3.509</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>C</th>\n",
       "      <td>제조업</td>\n",
       "      <td>6.760</td>\n",
       "      <td>7.104</td>\n",
       "      <td>-2.600</td>\n",
       "      <td>0.944</td>\n",
       "      <td>5.337</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>D</th>\n",
       "      <td>전기, 가스, 증기 및 공기조절 공급업</td>\n",
       "      <td>2.559</td>\n",
       "      <td>2.493</td>\n",
       "      <td>-1.944</td>\n",
       "      <td>0.493</td>\n",
       "      <td>2.013</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>E</th>\n",
       "      <td>수도, 하수 및 폐기물 처리, 원료 재생업</td>\n",
       "      <td>10.897</td>\n",
       "      <td>10.594</td>\n",
       "      <td>3.433</td>\n",
       "      <td>0.738</td>\n",
       "      <td>15.455</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>F</th>\n",
       "      <td>건설업</td>\n",
       "      <td>20.174</td>\n",
       "      <td>19.636</td>\n",
       "      <td>0.341</td>\n",
       "      <td>0.068</td>\n",
       "      <td>20.387</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>G</th>\n",
       "      <td>도매 및 소매업</td>\n",
       "      <td>18.234</td>\n",
       "      <td>18.463</td>\n",
       "      <td>-3.274</td>\n",
       "      <td>0.946</td>\n",
       "      <td>12.879</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>H</th>\n",
       "      <td>운수 및 창고업</td>\n",
       "      <td>15.495</td>\n",
       "      <td>16.051</td>\n",
       "      <td>-2.206</td>\n",
       "      <td>0.509</td>\n",
       "      <td>12.593</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>I</th>\n",
       "      <td>숙박 및 음식점업</td>\n",
       "      <td>47.395</td>\n",
       "      <td>47.067</td>\n",
       "      <td>-0.117</td>\n",
       "      <td>0.012</td>\n",
       "      <td>46.466</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>J</th>\n",
       "      <td>정보통신업</td>\n",
       "      <td>10.511</td>\n",
       "      <td>10.287</td>\n",
       "      <td>-0.398</td>\n",
       "      <td>0.110</td>\n",
       "      <td>9.847</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>K</th>\n",
       "      <td>금융 및 보험업</td>\n",
       "      <td>6.163</td>\n",
       "      <td>6.149</td>\n",
       "      <td>-5.151</td>\n",
       "      <td>0.933</td>\n",
       "      <td>3.489</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>L</th>\n",
       "      <td>부동산업</td>\n",
       "      <td>3.254</td>\n",
       "      <td>3.258</td>\n",
       "      <td>-0.497</td>\n",
       "      <td>0.232</td>\n",
       "      <td>3.085</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>M</th>\n",
       "      <td>전문, 과학 및 기술 서비스업</td>\n",
       "      <td>14.875</td>\n",
       "      <td>14.259</td>\n",
       "      <td>0.317</td>\n",
       "      <td>0.101</td>\n",
       "      <td>14.765</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>N</th>\n",
       "      <td>사업시설 관리, 사업 지원 및 임대 서비스업</td>\n",
       "      <td>19.646</td>\n",
       "      <td>19.847</td>\n",
       "      <td>-1.471</td>\n",
       "      <td>0.561</td>\n",
       "      <td>16.883</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>O</th>\n",
       "      <td>공공행정, 국방 및 사회보장 행정</td>\n",
       "      <td>9.024</td>\n",
       "      <td>9.013</td>\n",
       "      <td>-0.205</td>\n",
       "      <td>0.094</td>\n",
       "      <td>8.811</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>P</th>\n",
       "      <td>교육 서비스업</td>\n",
       "      <td>19.374</td>\n",
       "      <td>19.072</td>\n",
       "      <td>-1.069</td>\n",
       "      <td>0.761</td>\n",
       "      <td>16.956</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Q</th>\n",
       "      <td>보건업 및 사회복지 서비스업</td>\n",
       "      <td>23.493</td>\n",
       "      <td>23.263</td>\n",
       "      <td>0.010</td>\n",
       "      <td>0.000</td>\n",
       "      <td>23.287</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>R</th>\n",
       "      <td>예술, 스포츠 및 여가관련 서비스업</td>\n",
       "      <td>19.825</td>\n",
       "      <td>18.877</td>\n",
       "      <td>0.666</td>\n",
       "      <td>0.076</td>\n",
       "      <td>20.312</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S</th>\n",
       "      <td>협회 및 단체, 수리 및 기타 개인 서비스업</td>\n",
       "      <td>38.612</td>\n",
       "      <td>38.686</td>\n",
       "      <td>-0.764</td>\n",
       "      <td>0.396</td>\n",
       "      <td>35.567</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                       대분류명  2025 실적 계수(명/10억원)  기준 수준(명/10억원, 2024)  \\\n",
       "A               농업, 임업 및 어업              41.075               43.622   \n",
       "B                        광업               6.414                5.147   \n",
       "C                       제조업               6.760                7.104   \n",
       "D     전기, 가스, 증기 및 공기조절 공급업               2.559                2.493   \n",
       "E   수도, 하수 및 폐기물 처리, 원료 재생업              10.897               10.594   \n",
       "F                       건설업              20.174               19.636   \n",
       "G                  도매 및 소매업              18.234               18.463   \n",
       "H                  운수 및 창고업              15.495               16.051   \n",
       "I                 숙박 및 음식점업              47.395               47.067   \n",
       "J                     정보통신업              10.511               10.287   \n",
       "K                  금융 및 보험업               6.163                6.149   \n",
       "L                      부동산업               3.254                3.258   \n",
       "M          전문, 과학 및 기술 서비스업              14.875               14.259   \n",
       "N  사업시설 관리, 사업 지원 및 임대 서비스업              19.646               19.847   \n",
       "O        공공행정, 국방 및 사회보장 행정               9.024                9.013   \n",
       "P                   교육 서비스업              19.374               19.072   \n",
       "Q           보건업 및 사회복지 서비스업              23.493               23.263   \n",
       "R       예술, 스포츠 및 여가관련 서비스업              19.825               18.877   \n",
       "S  협회 및 단체, 수리 및 기타 개인 서비스업              38.612               38.686   \n",
       "\n",
       "   연간 로그변화율(%)  추세 R²  2035 계수(명/10억원)  \n",
       "A        1.032  0.291           48.867  \n",
       "B       -3.484  0.236            3.509  \n",
       "C       -2.600  0.944            5.337  \n",
       "D       -1.944  0.493            2.013  \n",
       "E        3.433  0.738           15.455  \n",
       "F        0.341  0.068           20.387  \n",
       "G       -3.274  0.946           12.879  \n",
       "H       -2.206  0.509           12.593  \n",
       "I       -0.117  0.012           46.466  \n",
       "J       -0.398  0.110            9.847  \n",
       "K       -5.151  0.933            3.489  \n",
       "L       -0.497  0.232            3.085  \n",
       "M        0.317  0.101           14.765  \n",
       "N       -1.471  0.561           16.883  \n",
       "O       -0.205  0.094            8.811  \n",
       "P       -1.069  0.761           16.956  \n",
       "Q        0.010  0.000           23.287  \n",
       "R        0.666  0.076           20.312  \n",
       "S       -0.764  0.396           35.567  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "par = F.fit_params(emp_a, va_sec, C.BASE_YEARS, (C.HIST_START, C.HIST_END), base=\"ratio\", trend=\"ols\")\n",
    "path = F.coef_path(par, C.FORECAST_YEARS, C.ANCHOR)\n",
    "par.assign(대분류명=[sec_name[s] for s in par.index]).to_csv(os.path.join(C.OUTPUT, \"coef_params.csv\"), encoding=\"utf-8-sig\")\n",
    "path.to_csv(os.path.join(C.OUTPUT, \"coef_path.csv\"), encoding=\"utf-8-sig\")\n",
    "pd.DataFrame({\"대분류명\": [sec_name[s] for s in par.index],\n",
    "              \"2025 실적 계수(명/10억원)\": coef.loc[2025] * 1000,\n",
    "              \"기준 수준(명/10억원, 2024)\": par[\"기준수준_b\"] * 1000,\n",
    "              \"연간 로그변화율(%)\": par[\"연간로그변화율_g\"] * 100,\n",
    "              \"추세 R²\": par[\"추세_R2\"],\n",
    "              \"2035 계수(명/10억원)\": path.loc[2035] * 1000}, index=par.index).round(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9df398c6",
   "metadata": {},
   "source": [
    "## 3. 주 산출물 — 5장 정비판 최종 전망 투입(S1–S5, 2026–2035)\n",
    "\n",
    "반올림 전 값은 `labor_demand_36.csv`에, 포털 뷰어 형식(소수 첫째 자리 반올림, 산업 이름순, 시나리오 합계 포함)은 `labor_demand_viewer_data.json`에 저장한다.\n",
    "파일 구조(키·연도·시나리오·산업 이름과 순서)가 최초 판 게시 파일·이전 판 파일과 같은지 확인하므로, 포털 뷰어 페이지는 고치지 않고 이 파일로 바꾸어 쓸 수 있다.\n",
    "2025년 산업별 실적(대분류 취업자의 부가가치 비중 배분)은 `labor_actual_2025_36.csv`에 저장한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "34c25469",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.166939Z",
     "iopub.status.busy": "2026-10-08T00:07:54.166939Z",
     "iopub.status.idle": "2026-10-08T00:07:54.206391Z",
     "shell.execute_reply": "2026-10-08T00:07:54.206391Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "labor_demand_viewer_data.json: 17,220 bytes · SHA-256 776c43a570648a03… · 최초 판·이전 판 파일과 구조 동일\n",
      "2025년 실적(19개 대분류 합계): 28,681.5천 명\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>S1</th>\n",
       "      <th>S2</th>\n",
       "      <th>S3</th>\n",
       "      <th>S4</th>\n",
       "      <th>S5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2026</th>\n",
       "      <td>28,526.200</td>\n",
       "      <td>28,289.400</td>\n",
       "      <td>28,656.100</td>\n",
       "      <td>28,652.600</td>\n",
       "      <td>28,337.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2028</th>\n",
       "      <td>28,614.800</td>\n",
       "      <td>28,507.200</td>\n",
       "      <td>28,660.100</td>\n",
       "      <td>28,693.000</td>\n",
       "      <td>28,629.900</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2030</th>\n",
       "      <td>28,670.800</td>\n",
       "      <td>28,648.000</td>\n",
       "      <td>28,678.100</td>\n",
       "      <td>28,681.000</td>\n",
       "      <td>28,729.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2032</th>\n",
       "      <td>28,656.900</td>\n",
       "      <td>28,630.200</td>\n",
       "      <td>28,673.200</td>\n",
       "      <td>28,627.000</td>\n",
       "      <td>28,717.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2035</th>\n",
       "      <td>28,560.200</td>\n",
       "      <td>28,517.200</td>\n",
       "      <td>28,595.300</td>\n",
       "      <td>28,517.500</td>\n",
       "      <td>28,614.900</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             S1         S2         S3         S4         S5\n",
       "2026 28,526.200 28,289.400 28,656.100 28,652.600 28,337.000\n",
       "2028 28,614.800 28,507.200 28,660.100 28,693.000 28,629.900\n",
       "2030 28,670.800 28,648.000 28,678.100 28,681.000 28,729.000\n",
       "2032 28,656.900 28,630.200 28,673.200 28,627.000 28,717.100\n",
       "2035 28,560.200 28,517.200 28,595.300 28,517.500 28,614.900"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj = F.project(recon, path, sec_of)\n",
    "F.to_long(proj).to_csv(os.path.join(C.OUTPUT, \"labor_demand_36.csv\"), index=False, encoding=\"utf-8-sig\")\n",
    "main = F.viewer_json(proj)\n",
    "with open(C.OUT_JSON, \"wb\") as f:\n",
    "    f.write(F.dumps_viewer(main))\n",
    "v0_pub = json.load(open(C.V0_JSON, encoding=\"utf-8\"))\n",
    "prev_pub = json.load(open(C.PREV_JSON, encoding=\"utf-8\"))\n",
    "assert F.same_structure(main, v0_pub) and F.same_structure(main, prev_pub), \"주 산출물의 구조가 기존 파일과 다르다\"\n",
    "print(f\"labor_demand_viewer_data.json: {os.path.getsize(C.OUT_JSON):,d} bytes · SHA-256 {F.sha256(C.OUT_JSON)[:16]}… · 최초 판·이전 판 파일과 구조 동일\")\n",
    "act25 = F.actual_by_industry(emp_a, va_a, sec_of, C.ACTUAL_YEAR)\n",
    "act25.rename(\"취업자_천명\").rename_axis(\"산업\").to_csv(os.path.join(C.OUTPUT, \"labor_actual_2025_36.csv\"), encoding=\"utf-8-sig\")\n",
    "tot = pd.DataFrame({s: p.sum(axis=1) for s, p in proj.items()})\n",
    "print(f\"2025년 실적(19개 대분류 합계): {act25.sum():,.1f}천 명\")\n",
    "tot.loc[[2026, 2028, 2030, 2032, 2035]].round(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee642ca1",
   "metadata": {},
   "source": [
    "## 4. 대분류 합계 점검\n",
    "\n",
    "같은 대분류 안의 산업은 같은 계수를 쓰므로 산업별 취업자를 대분류로 더하면 대분류 계수 × 대분류 부가가치와 같아야 한다.\n",
    "2025년 산업별 실적의 대분류 합계도 대분류 실측치와 같아야 한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "afc0184a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.207894Z",
     "iopub.status.busy": "2026-10-08T00:07:54.207394Z",
     "iopub.status.idle": "2026-10-08T00:07:54.219978Z",
     "shell.execute_reply": "2026-10-08T00:07:54.219978Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "대분류 합계와 직접 계산의 최대 차이: 9.09e-13천 명 · 2025 실적 배분의 대분류 합계 차이: 2.27e-13천 명\n"
     ]
    }
   ],
   "source": [
    "chk = []\n",
    "for s in C.SCENARIOS:\n",
    "    by_sec = proj[s].T.groupby(pd.Series(sec_of)).sum().T\n",
    "    direct = path * F.section_va(recon[s], sec_of).loc[C.FORECAST_YEARS]\n",
    "    chk.append((by_sec[F.SECTIONS] - direct[F.SECTIONS]).abs().max().max())\n",
    "d25 = (act25.groupby(pd.Series(sec_of)).sum() - emp_a.loc[C.ACTUAL_YEAR, F.SECTIONS]).abs().max()\n",
    "print(f\"대분류 합계와 직접 계산의 최대 차이: {max(chk):.2e}천 명 · 2025 실적 배분의 대분류 합계 차이: {d25:.2e}천 명\")\n",
    "assert max(chk) < 1e-6 and d25 < 1e-6"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e73ffaef",
   "metadata": {},
   "source": [
    "## 5. 이전 판(2026-10-08 판) 재현\n",
    "\n",
    "같은 계수 경로에 이전 판 투입(정비 이전 5장 최종 전망)을 넣어 이전 판 산출 파일을 다시 만든다. 산출 파일의 SHA-256이 `data/published_prev/`에 보존한 파일과 같아야 한다.\n",
    "이 절은 정비판과 이전 판의 차이가 투입 부가가치에서만 생긴다는 것을 보인다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "20e51d88",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.220981Z",
     "iopub.status.busy": "2026-10-08T00:07:54.220981Z",
     "iopub.status.idle": "2026-10-08T00:07:54.256026Z",
     "shell.execute_reply": "2026-10-08T00:07:54.256026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "재현본 SHA-256 f3346aee10c08f89… · 보존 파일 f3346aee10c08f89… · 일치\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'연도 일치': True,\n",
       " '시나리오 일치': True,\n",
       " '산업 일치': True,\n",
       " '산업값 개수': 1800,\n",
       " '산업값 최대절대오차': 0.0,\n",
       " '합계 개수': 50,\n",
       " '합계 최대절대오차': 0.0}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj_prev = F.project(recon_prev, path, sec_of)\n",
    "F.to_long(proj_prev).to_csv(os.path.join(C.OUTPUT, \"labor_demand_36_prev.csv\"), index=False, encoding=\"utf-8-sig\")\n",
    "prev = F.viewer_json(proj_prev)\n",
    "with open(C.OUT_PREV_JSON, \"wb\") as f:\n",
    "    f.write(F.dumps_viewer(prev))\n",
    "h = F.sha256(C.OUT_PREV_JSON)\n",
    "print(f\"재현본 SHA-256 {h[:16]}… · 보존 파일 {F.sha256(C.PREV_JSON)[:16]}… · {'일치' if h == F.sha256(C.PREV_JSON) else '불일치'}\")\n",
    "F.compare_viewer(prev, prev_pub)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fd78a58",
   "metadata": {},
   "source": [
    "## 6. 최초 판(v0, 정합화 이전 부가가치 사용) 재현\n",
    "\n",
    "같은 계수 경로에 2026-08-04 게시 당시의 투입(정합화 이전 분기 전망)을 넣어 게시 파일을 다시 만든다. 산출 파일의 SHA-256이 게시 파일과 같아야 한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e7c2ba27",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.257032Z",
     "iopub.status.busy": "2026-10-08T00:07:54.257032Z",
     "iopub.status.idle": "2026-10-08T00:07:54.292011Z",
     "shell.execute_reply": "2026-10-08T00:07:54.292011Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "재현본 SHA-256 31c1c9c5dfadd831… · 게시 파일 31c1c9c5dfadd831… · 일치\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'연도 일치': True,\n",
       " '시나리오 일치': True,\n",
       " '산업 일치': True,\n",
       " '산업값 개수': 1800,\n",
       " '산업값 최대절대오차': 0.0,\n",
       " '합계 개수': 50,\n",
       " '합계 최대절대오차': 0.0}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "proj_v0 = F.project(scen_a, path, sec_of)\n",
    "F.to_long(proj_v0).to_csv(os.path.join(C.OUTPUT, \"labor_demand_36_v0.csv\"), index=False, encoding=\"utf-8-sig\")\n",
    "v0 = F.viewer_json(proj_v0)\n",
    "with open(C.OUT_V0_JSON, \"wb\") as f:\n",
    "    f.write(F.dumps_viewer(v0))\n",
    "h = F.sha256(C.OUT_V0_JSON)\n",
    "print(f\"재현본 SHA-256 {h[:16]}… · 게시 파일 {F.sha256(C.V0_JSON)[:16]}… · {'일치' if h == F.sha256(C.V0_JSON) else '불일치'}\")\n",
    "F.compare_viewer(v0, v0_pub)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5df8e923",
   "metadata": {},
   "source": [
    "## 7. 재구성 근거 — 대안 명세 비교(최초 판 게시 파일 기준)\n",
    "\n",
    "뷰어 설명문은 '2023–2025년 평균 취업계수', '2013–2025년 계수 변화추세(연간 로그변화율)', '경제활동인구조사 19개 대분류'만 밝힌다.\n",
    "취업자 계열(계절조정·원계열), 기준 수준의 평균 방식, 추세 추정 방식, 기준 연도를 바꾸어 가며 최초 판 게시 수치와의 차이를 계산한다.\n",
    "기본 실행은 16개 명세를 비교하고, `FULL=1`이면 기준 수준 3종과 추세 기간 4종으로 넓힌 96개 명세를 비교한다.\n",
    "\n",
    "| 선택지 | 후보 |\n",
    "|---|---|\n",
    "| 취업자 계열 | 계절조정(분기 평균) · 원계열(분기 평균) |\n",
    "| 기준 수준 | ratio: 3개년 합계 비율 · mean: 연도별 계수의 산술평균 · geo: 기하평균(FULL) |\n",
    "| 추세 추정 | ols: 로그 계수의 최소제곱 기울기 · endpoint: 양 끝 연도 로그 차이 |\n",
    "| 추세 기간 | 2013–2025 · 2014–2025 · 2015–2025 · 2013–2024(FULL) |\n",
    "| 기준 연도 | 2024(기준 기간 중앙) · 2025 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "86f67c41",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.293014Z",
     "iopub.status.busy": "2026-10-08T00:07:54.293014Z",
     "iopub.status.idle": "2026-10-08T00:07:54.710194Z",
     "shell.execute_reply": "2026-10-08T00:07:54.710194Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "비교한 명세: 16개 · 게시 수치를 모두 재현한 명세: 1개\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>취업자 계열</th>\n",
       "      <th>기준 수준</th>\n",
       "      <th>추세 추정</th>\n",
       "      <th>추세 기간</th>\n",
       "      <th>기준연도</th>\n",
       "      <th>최대절대오차(천명)</th>\n",
       "      <th>일치 비율</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>계절조정</td>\n",
       "      <td>ratio</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2024</td>\n",
       "      <td>0.000</td>\n",
       "      <td>1.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>원계열</td>\n",
       "      <td>ratio</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2024</td>\n",
       "      <td>5.100</td>\n",
       "      <td>0.566</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>원계열</td>\n",
       "      <td>mean</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2024</td>\n",
       "      <td>5.400</td>\n",
       "      <td>0.115</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>계절조정</td>\n",
       "      <td>mean</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2024</td>\n",
       "      <td>5.600</td>\n",
       "      <td>0.187</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>계절조정</td>\n",
       "      <td>ratio</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2025</td>\n",
       "      <td>105.500</td>\n",
       "      <td>0.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>원계열</td>\n",
       "      <td>ratio</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2025</td>\n",
       "      <td>105.500</td>\n",
       "      <td>0.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>계절조정</td>\n",
       "      <td>mean</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2025</td>\n",
       "      <td>105.600</td>\n",
       "      <td>0.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>원계열</td>\n",
       "      <td>mean</td>\n",
       "      <td>ols</td>\n",
       "      <td>2013–2025</td>\n",
       "      <td>2025</td>\n",
       "      <td>105.600</td>\n",
       "      <td>0.000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  취업자 계열  기준 수준 추세 추정      추세 기간  기준연도  최대절대오차(천명)  일치 비율\n",
       "0   계절조정  ratio   ols  2013–2025  2024       0.000  1.000\n",
       "1    원계열  ratio   ols  2013–2025  2024       5.100  0.566\n",
       "2    원계열   mean   ols  2013–2025  2024       5.400  0.115\n",
       "3   계절조정   mean   ols  2013–2025  2024       5.600  0.187\n",
       "4   계절조정  ratio   ols  2013–2025  2025     105.500  0.000\n",
       "5    원계열  ratio   ols  2013–2025  2025     105.500  0.000\n",
       "6   계절조정   mean   ols  2013–2025  2025     105.600  0.000\n",
       "7    원계열   mean   ols  2013–2025  2025     105.600  0.000"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid = F.spec_grid({\"계절조정\": emp_a, \"원계열\": emp_n}, va_sec, scen_a, sec_of, v0_pub, full=C.FULL)\n",
    "grid.to_csv(os.path.join(C.OUTPUT, \"spec_comparison.csv\"), index=False, encoding=\"utf-8-sig\")\n",
    "print(f\"비교한 명세: {len(grid)}개 · 게시 수치를 모두 재현한 명세: {int((grid['최대절대오차(천명)'] < 0.05).sum())}개\")\n",
    "grid.head(8)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b25ba3e",
   "metadata": {},
   "source": [
    "1,800개 값(36개 산업 × 10년 × 5개 시나리오)을 모두 재현하는 명세는 하나뿐이다. 원계열을 쓰면 계절성이 큰 농림어업·공공행정 등에서 최대 5천 명 안팎의 차이가 남고,\n",
    "기준 연도를 2025년에 두면 전 산업이 한 해 추세만큼 어긋난다."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bed8e926",
   "metadata": {},
   "source": [
    "## 8. 판본 비교 — 최초 판, 이전 판, 정비판\n",
    "\n",
    "세 판은 계수 경로가 같고 투입 부가가치만 다르다. 최초 판은 정합화 이전 산업 합산 경로(2025–2035년 연평균 약 4.0–4.3%)를, 이전 판은 정비 이전 5장 최종 전망을,\n",
    "정비판은 2026-10 정비판 최종 전망을 투입했다. 투입 부가가치의 수준과 증가율은 `01_입수.ipynb` 4절의 표에 있다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "15bd65a4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:07:54.711198Z",
     "iopub.status.busy": "2026-10-08T00:07:54.711198Z",
     "iopub.status.idle": "2026-10-08T00:07:54.719009Z",
     "shell.execute_reply": "2026-10-08T00:07:54.719009Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>최초 판(천명)</th>\n",
       "      <th>이전 판(천명)</th>\n",
       "      <th>정비판(천명)</th>\n",
       "      <th>정비판 − 이전 판(천명)</th>\n",
       "      <th>정비판 − 최초 판(천명)</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>시나리오</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>S1</th>\n",
       "      <td>36,284.800</td>\n",
       "      <td>29,040.100</td>\n",
       "      <td>28,560.200</td>\n",
       "      <td>-479.900</td>\n",
       "      <td>-7,724.600</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S2</th>\n",
       "      <td>35,703.400</td>\n",
       "      <td>28,988.900</td>\n",
       "      <td>28,517.200</td>\n",
       "      <td>-471.700</td>\n",
       "      <td>-7,186.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S3</th>\n",
       "      <td>36,569.300</td>\n",
       "      <td>29,079.600</td>\n",
       "      <td>28,595.300</td>\n",
       "      <td>-484.300</td>\n",
       "      <td>-7,974.000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S4</th>\n",
       "      <td>36,450.600</td>\n",
       "      <td>29,110.800</td>\n",
       "      <td>28,517.500</td>\n",
       "      <td>-593.300</td>\n",
       "      <td>-7,933.100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>S5</th>\n",
       "      <td>36,076.500</td>\n",
       "      <td>29,046.200</td>\n",
       "      <td>28,614.900</td>\n",
       "      <td>-431.300</td>\n",
       "      <td>-7,461.600</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       최초 판(천명)   이전 판(천명)    정비판(천명)  정비판 − 이전 판(천명)  정비판 − 최초 판(천명)\n",
       "시나리오                                                                 \n",
       "S1   36,284.800 29,040.100 28,560.200        -479.900      -7,724.600\n",
       "S2   35,703.400 28,988.900 28,517.200        -471.700      -7,186.100\n",
       "S3   36,569.300 29,079.600 28,595.300        -484.300      -7,974.000\n",
       "S4   36,450.600 29,110.800 28,517.500        -593.300      -7,933.100\n",
       "S5   36,076.500 29,046.200 28,614.900        -431.300      -7,461.600"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tot_prev = pd.DataFrame({s: p.sum(axis=1) for s, p in proj_prev.items()})\n",
    "tot_v0 = pd.DataFrame({s: p.sum(axis=1) for s, p in proj_v0.items()})\n",
    "rows = []\n",
    "for s in C.SCENARIOS:\n",
    "    for y in (2026, 2030, 2035):\n",
    "        rows.append({\"시나리오\": s, \"연도\": y, \"최초 판(천명)\": tot_v0.loc[y, s], \"이전 판(천명)\": tot_prev.loc[y, s],\n",
    "                     \"정비판(천명)\": tot.loc[y, s], \"정비판 − 이전 판(천명)\": tot.loc[y, s] - tot_prev.loc[y, s],\n",
    "                     \"정비판 − 최초 판(천명)\": tot.loc[y, s] - tot_v0.loc[y, s]})\n",
    "vc = pd.DataFrame(rows)\n",
    "vc.to_csv(os.path.join(C.OUTPUT, \"vintage_comparison.csv\"), index=False, encoding=\"utf-8-sig\")\n",
    "vc[vc[\"연도\"] == 2035].set_index(\"시나리오\").drop(columns=\"연도\").round(1)"
   ]
  }
 ],
 "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.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
