-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_dataset.py
More file actions
175 lines (175 loc) · 6.71 KB
/
generate_dataset.py
File metadata and controls
175 lines (175 loc) · 6.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
{
"cells": [
{
"cell_type": "code",
"execution_count": 42,
"id": "ed71965b",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"\n",
"def simulate_corsia_mrv_fuel_burn(\n",
" n_airlines: int = 600,\n",
" years=range(2019, 2026),\n",
" seed: int = 42,\n",
"\n",
" # Fuel burn 분포(heavy-tail): lognormal(mean=ln_mu, sigma=ln_sigma)\n",
" # exp(ln_mu)는 2019년 중앙값 근처의 연료소모량(ton fuel)\n",
" ln_mu: float = 12.8, # exp(12.8) ≈ 363k ton fuel (중앙값 느낌)\n",
" ln_sigma: float = 1.20, # 쏠림 정도 (1.0~1.5면 강한 상위 집중)\n",
"\n",
" # MRV 대상처럼 \"너무 작은 사업자\" 제거(연간 최소 연료소모량)\n",
" mrv_min_annual_tfuel: float = 80_000,\n",
"\n",
" # 항공사별 연평균 성장률(연료소모 성장)\n",
" g_mean: float = 0.03,\n",
" g_sd: float = 0.04,\n",
"\n",
" # 연도 공통 충격(글로벌 수요/유가/운항환경)\n",
" shock_sd: float = 0.08,\n",
"\n",
" # 항공사-연도 특이 변동(소규모 noise)\n",
" idio_sd: float = 0.05,\n",
"):\n",
" rng = np.random.default_rng(seed)\n",
"\n",
" # 간단 국가/지역 더미(항공사 국적 = AOC 발급국)\n",
" countries = [\n",
" (\"United States\", \"NAM\"), (\"China\", \"APAC\"), (\"United Kingdom\", \"EUR\"),\n",
" (\"Germany\", \"EUR\"), (\"France\", \"EUR\"), (\"United Arab Emirates\", \"MEA\"),\n",
" (\"Qatar\", \"MEA\"), (\"Turkey\", \"EUR\"), (\"Singapore\", \"APAC\"),\n",
" (\"Japan\", \"APAC\"), (\"Korea, Rep.\", \"APAC\"), (\"Australia\", \"APAC\"),\n",
" (\"India\", \"APAC\"), (\"Ethiopia\", \"AFR\"), (\"South Africa\", \"AFR\"),\n",
" (\"Brazil\", \"LAM\"), (\"Mexico\", \"LAM\"), (\"Chile\", \"LAM\"),\n",
" (\"Kenya\", \"AFR\"), (\"Canada\", \"NAM\")\n",
" ]\n",
" country_names = np.array([c[0] for c in countries])\n",
" country_regions = {c[0]: c[1] for c in countries}\n",
"\n",
" # 국가 가중치(대형 시장에 항공사 더 배치되는 느낌)\n",
" weights = np.array([\n",
" 0.16, 0.14, 0.06, 0.06, 0.05, 0.05,\n",
" 0.04, 0.04, 0.04, 0.04, 0.04, 0.03,\n",
" 0.06, 0.02, 0.02, 0.04, 0.03, 0.02,\n",
" 0.02, 0.04\n",
" ])\n",
" weights = weights / weights.sum()\n",
"\n",
" # 항공사 식별자 + 국적 부여\n",
" airline_ids = [f\"AL{str(i).zfill(4)}\" for i in range(1, n_airlines + 1)]\n",
" operator_state = rng.choice(country_names, size=n_airlines, p=weights)\n",
" region = np.array([country_regions[s] for s in operator_state])\n",
"\n",
" # 2019 기준 \"기본 연료소모\" (heavy-tail)\n",
" base_fuel_2019 = rng.lognormal(mean=ln_mu, sigma=ln_sigma, size=n_airlines)\n",
"\n",
" # MRV 대상처럼 최소 컷 적용 (부족하면 추가 샘플로 채움)\n",
" mask = base_fuel_2019 >= mrv_min_annual_tfuel\n",
" while mask.sum() < n_airlines:\n",
" extra = rng.lognormal(mean=ln_mu, sigma=ln_sigma, size=n_airlines)\n",
" base_fuel_2019 = np.where(mask, base_fuel_2019, extra)\n",
" mask = base_fuel_2019 >= mrv_min_annual_tfuel\n",
"\n",
" # 항공사별 성장률\n",
" g_i = rng.normal(loc=g_mean, scale=g_sd, size=n_airlines)\n",
" g_i = np.clip(g_i, -0.10, 0.20)\n",
"\n",
" # 연도별 공통 충격(로그 스케일)\n",
" years = list(years)\n",
" year_shocks = {y: rng.normal(loc=0.0, scale=shock_sd) for y in years}\n",
"\n",
" rows = []\n",
" for idx in range(n_airlines):\n",
" al_id = airline_ids[idx]\n",
" st = operator_state[idx]\n",
" reg = region[idx]\n",
" f0 = base_fuel_2019[idx]\n",
" gi = g_i[idx]\n",
"\n",
" for y in years:\n",
" t = y - 2019\n",
" eps = rng.normal(0.0, idio_sd)\n",
"\n",
" # FuelBurn = f0 * (1+gi)^t * exp(year_shock) * exp(idio_noise)\n",
" fuel = f0 * ((1.0 + gi) ** t) * np.exp(year_shocks[y]) * np.exp(eps)\n",
"\n",
" rows.append({\n",
" \"airline_id\": al_id,\n",
" \"operator_state\": st,\n",
" \"region\": reg,\n",
" \"year\": y,\n",
" \"fuel_burn_tonnes\": float(fuel),\n",
" \"g_i\": float(gi),\n",
" \"year_shock\": float(year_shocks[y])\n",
" })\n",
"\n",
" df = pd.DataFrame(rows).sort_values([\"airline_id\", \"year\"]).reset_index(drop=True)\n",
"\n",
" # 연도별 점유율(상위 집중 확인용)\n",
" df[\"fuel_share_in_year\"] = df.groupby(\"year\")[\"fuel_burn_tonnes\"].apply(lambda s: s / s.sum()).reset_index(level=0, drop=True)\n",
"\n",
" return df\n",
"\n",
"\n",
"\n",
"if __name__ == \"__main__\":\n",
" df_fuel = simulate_corsia_mrv_fuel_burn(\n",
" n_airlines=600,\n",
" years=range(2019, 2026),\n",
" seed=7,\n",
" ln_mu=12.8,\n",
" ln_sigma=1.25,\n",
" mrv_min_annual_tfuel=100_000\n",
" )\n",
"\n",
" print(df_fuel.head(10))\n",
"\n",
" print(\"\\nYearly totals (million tonnes fuel):\")\n",
" print((df_fuel.groupby(\"year\")[\"fuel_burn_tonnes\"].sum() / 1e6).round(2))\n",
"\n",
" top10_share = (\n",
" df_fuel.sort_values([\"year\", \"fuel_burn_tonnes\"], ascending=[True, False])\n",
" .groupby(\"year\").head(10)\n",
" .groupby(\"year\")[\"fuel_burn_tonnes\"].sum()\n",
" / df_fuel.groupby(\"year\")[\"fuel_burn_tonnes\"].sum()\n",
" )\n",
" print(\"\\nTop-10 airline fuel share by year:\")\n",
" print(top10_share.round(3))\n",
"\n",
"# df_fuel[df_fuel['year'] == 2019].to_csv('./dataset/fuel_burn_2019_랜덤생성.csv', index=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fe95fd9c",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "bibiml",
"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.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}