3장 수출 다각화를 측정해보자#

출처: UNCTAD (2012), A Practical Guide to Trade Policy Analysis, Chapter 1.

1. 내연적 마진과 외연적 마진#

Hummels와 Klenow(2005)는 무역 데이터 분석에서 내연적 마진(intensive margin)과 외연적 마진(extensive margin)이라는 개념을 도입했다.(Hummels, D., & Klenow, P. J. (2005). The variety and quality of a nation’s exports. American economic review, 95(3), 704-723.) 이 개념들은 나라들의 무역 성과를 더 정교하게 평가하기 위해 사용된다.

정의#

어떤 나라의 내연적 마진(intensive margin)은 그 나라가 이미 수출하고 있는 제품들에 있어서 시장 점유율이 어느 정도인지를 측정한 것이다. 어떤 나라 \(i\)의 내연적 마진을 식으로 표현하면 다음과 같다.

\[ IM_i = \frac{\sum_{k \in K_i} X_k^i}{\sum_{k \in K_i} X_k^W} \]

여기서, \(K_i\)\(i\)국이 수출하는 제품의 집합이고, \(X_{i,k}\)\(i\)국의 \(k\)재 수출액이며, \(X_{W,k}\)는 세계 전체의 \(k\)재 수출액이다. 따라서 위 식의 분자는 \(i\)국의 총 수출액이고, 분모는 \(i\)국 수출 상품에 대해 세계 각국의 수출액을 모두 합친 것이다.

외연적 마진(extensive margin)은 어떤 나라가 수출하는 제품들이 세계 무역에서 차지하는 비중을 측정한 것이다. 이는 해당 국가가 새로운 제품을 수출하거나 새로운 시장에 진출함으로써 무역을 확장할 수 있는 잠재력을 나타낸다. 식으로 표현하면 다음과 같다.

\[ XM_i = \frac{\sum_{k \in K_i} X_k^W}{\sum_{k \in K_W} X_k^W} \]

여기서, \(K_W\)는 모든 수출 상품의 집합이다. 따라서 위 식의 분자는 \(i\)국 수출 상품에 대해 세계 각국 수출액을 모두 합친 것이고, 분모는 모든 수출 상품에 대해 세계 각국 수출액을 모두 합친 것이다.

시장별 다각화#

Hummels와 Klenow의 접근 방식은 제품이 아니라 지리적 시장에 적용할 수도 있다. \(i\)국이 수출하는 목적지 시장의 집합을 \(D_i\)라 하자. 특정 목적지 \(d\)국에 대한 \(i\)국의 총수출액을 \(X_d^i\), 그리고 해당 목적지로의 세계 총수출액(즉, 해당 국가의 총 수입액)을 \(X_d^W\)라고 하자.

이 경우 (제품이 아니라 시장에 대한) 내연적 마진은 다음과 같이 정의된다.

\[ IM_i = \frac{\sum_{d \in D_i} X_d^i}{\sum_{d \in D_i} X_d^W} \]

여기서 \(D_W\)는 모든 목적지 국가의 집합이다. 즉, 이는 \(i\)국이 수출하는 목적지에서의 시장 점유율, 즉 해당 국가들의 전체 수입에서 차지하는 비중을 의미한다.

마찬가지로 (제품이 아니라 시장에 대한) 외연적 마진은 다음과 같이 정의된다.

\[ XM_i = \frac{\sum_{d \in D_i} X_d^W}{\sum_{d \in D_W} X_d^W} \]

이는 \(i\)국이 수출하는 목적지 시장들이 세계 무역에서 차지하는 비중(즉, 해당 목적지들의 세계 총수입에서 차지하는 비중)을 나타낸다.

의의#

Hummels와 Klenow의 내연적 마진과 외연적 마진은 전통적인 무역 측정 방법에 비해 몇 가지 중요한 이점을 제공한다.

  • 기존의 단순한 무역량 분석에서 벗어나, 특정 국가가 기존 수출품목을 통해 얼마나 많은 시장 점유율을 차지하고 있는지를 파악할 수 있다. 이는 특정 산업이나 제품군에서의 경쟁력을 평가하는 데도 유용하다.

  • 국가가 새로운 제품을 수출하거나 새로운 시장에 진출하는 능력을 평가할 수 있다. 이는 정책 결정자들이 무역 다변화 전략을 수립하는 데 중요한 정보를 제공한다.

  • 내연적 마진은 기존 제품 및 시장에 있어서의 점유율 증대를 목표로 하는 정책의 효과를 측정할 수 있으며, 외연적 마진은 새로운 제품과 시장을 개척(다각화)하는 정책의 효과를 평가하는 데 유용하다.

2. 간단한 숫자 예#

마진예

한국(KOR)

  • 내연적 마진: 한국의 수출 품목(자동차)만을 대상으로 한국의 수출이 차지하는 비율을 계산함. 즉, \(\frac{5}{5+3}=0.625\), 즉 62.5%.

  • 외연적 마진: 전체 품목(자동차, 농산물)을 대상으로 한국이 참여하는 품목(자동차)이 전체 품목에서 차지하는 비율을 계산함. 즉, \(\frac{5+3}{5+3+2}=0.8\), 즉 80%.

미국(USA)

  • 내연적 마진: 미국의 수출 품목(자동차, 농산물)을 대상으로 미국의 수출이 차지하는 비율을 계산함. 즉, \(\frac{3+2}{5+3+2}=0.5\), 즉 50%.

  • 외연적 마진: 전체 품목(자동차, 농산물)을 대상으로 미국이 참여하는 품목(자동차, 농산물)이 전체 품목에서 차지하는 비율을 계산함. \(\frac{5+3+2}{5+3+2}=1\), 즉 100%.

IM & EM 계산 코딩#

import pandas as pd
import numpy as np

# Creating the DataFrame
data = {
    'reporter': ['KOR', 'USA', 'USA', 'All', 'All'],
    'partner': ['WLD', 'WLD', 'WLD', 'WLD', 'WLD'],
    'year': [2000, 2000, 2000, 2000, 2000],
    'product': ['자동차', '자동차', '농산물', '자동차', '농산물'],
    'trade_value': [5, 3, 2, 8, 2]
}
df = pd.DataFrame(data)
df
reporter partner year product trade_value
0 KOR WLD 2000 자동차 5
1 USA WLD 2000 자동차 3
2 USA WLD 2000 농산물 2
3 All WLD 2000 자동차 8
4 All WLD 2000 농산물 2
# 'trade_value를 x_i_k'로
df['x_i_k'] = df['trade_value']

# 각 reporter와 year별, 모든 제품에 대한 수출액 합계: sum_i_x_i_k
df['sum_i_x_i_k'] = df.groupby(['reporter', 'year'])['x_i_k'].transform('sum')

# 연도별로, reporter가 "All"인 행에서(만) temp1 생성 (즉, 해당 product의 세계 수출액)
df['temp1'] = np.where(df['reporter'] == "All", df['x_i_k'], np.nan)

# 연도와 product별로 temp1의 최댓값을 구해, 해당 product의 세계 수출액(temp2) 산출
df['temp2'] = df.groupby(['year', 'product'])['temp1'].transform('max')

# 각 reporter와 year별로, 자신이 수출하는 모든 제품에 대한 세계 수출액의 합: sum_i_x_w_k
df['sum_i_x_w_k'] = df.groupby(['reporter', 'year'])['temp2'].transform('sum')

# 연도별로, 모든 제품의 세계 수출액 합계: sum_w_x_w_k
df['sum_w_x_w_k'] = df.groupby('year')['temp1'].transform('sum')

# Intensive margin: im_i = (자국의 수출액 합계) / (해당 국가가 수출하는 제품의 세계 수출액 합계)
df['im_i'] = df['sum_i_x_i_k'] / df['sum_i_x_w_k']

# Extensive margin: em_i = (해당 국가가 수출하는 제품의 세계 수출액 합계) / (전세계 수출액 합계)
df['em_i'] = df['sum_i_x_w_k'] / df['sum_w_x_w_k']

# 결과 확인
df
reporter partner year product trade_value x_i_k sum_i_x_i_k temp1 temp2 sum_i_x_w_k sum_w_x_w_k im_i em_i
0 KOR WLD 2000 자동차 5 5 5 NaN 8.0 8.0 10.0 0.625 0.8
1 USA WLD 2000 자동차 3 3 5 NaN 8.0 10.0 10.0 0.500 1.0
2 USA WLD 2000 농산물 2 2 5 NaN 2.0 10.0 10.0 0.500 1.0
3 All WLD 2000 자동차 8 8 10 8.0 8.0 10.0 10.0 1.000 1.0
4 All WLD 2000 농산물 2 2 10 2.0 2.0 10.0 10.0 1.000 1.0

3. 제품 기준 IM & EM 계산 사례#

데이터#

  • 2000년 161개국

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 데이터 불러오기 
df = pd.read_stata("../Data/comtrade_exports_all_countries_2000.dta")
df
reporter reporter_name partner partner_name year product_name flow_name trade_value product
0 AIA Anguila WLD World 2000 Bananas, including plantains, fresh Gross Exp. 0.346000 080300
1 AIA Anguila WLD World 2000 Coconut copra oil (excl. crude) and Gross Exp. 2.240000 151319
2 AIA Anguila WLD World 2000 Margarine (excl. liquid) Gross Exp. 3.332000 151710
3 AIA Anguila WLD World 2000 Prepared or preserved fish (excl. m Gross Exp. 0.001000 160419
4 AIA Anguila WLD World 2000 Mixtures of juices, unfermented, no Gross Exp. 1.252000 200990
... ... ... ... ... ... ... ... ... ...
358866 ZWE Zimbabwe WLD World 2000 Original engravings, prints and lit Gross Exp. 1.230000 970200
358867 ZWE Zimbabwe WLD World 2000 Original sculptures and statuary, i Gross Exp. 5650.151855 970300
358868 ZWE Zimbabwe WLD World 2000 Used postage or revenue stamps and Gross Exp. 0.003000 970400
358869 ZWE Zimbabwe WLD World 2000 Coll & coll pce of zoo,bot,mineral, Gross Exp. 10756.884766 970500
358870 ZWE Zimbabwe WLD World 2000 Antiques of an age exceeding one hu Gross Exp. 0.358000 970600

358871 rows × 9 columns

변수 설명

  • reporter: 무역 거래를 보고한 국가의 코드

  • reporter_name: 무역 거래를 보고한 국가의 이름

  • partner: 거래 상대국의 코드 (WLD는 전세계)

  • partner_name: 거래 상대국의 이름

  • year: 무역 거래가 발생한 연도

  • product_name: 제품 이름

  • flow_name: 무역 흐름의 유형(Gross Exp.는 총수출)

  • trade_value: 거래 금액

  • product: 상품 분류 코드

df['reporter'].unique()
array(['AIA', 'ALB', 'All', 'AND', 'ARG', 'ARM', 'ATG', 'AUS', 'AUT',
       'AZE', 'BDI', 'BEL', 'BEN', 'BFA', 'BGD', 'BGR', 'BHR', 'BHS',
       'BLR', 'BLZ', 'BOL', 'BRA', 'BRB', 'BWA', 'CAF', 'CAN', 'CHE',
       'CHL', 'CHN', 'CIV', 'CMR', 'COL', 'COM', 'CPV', 'CRI', 'CUB',
       'CYP', 'CZE', 'DEU', 'DMA', 'DNK', 'DZA', 'ECU', 'EGY', 'ESP',
       'EST', 'ETH', 'EUN', 'FIN', 'FJI', 'FRA', 'FRO', 'GAB', 'GBR',
       'GEO', 'GHA', 'GIN', 'GMB', 'GRC', 'GRD', 'GRL', 'GTM', 'GUY',
       'HKG', 'HND', 'HRV', 'HUN', 'IDN', 'IND', 'IRL', 'IRN', 'ISL',
       'ISR', 'ITA', 'JAM', 'JOR', 'JPN', 'KAZ', 'KEN', 'KGZ', 'KHM',
       'KNA', 'KOR', 'KWT', 'LBN', 'LCA', 'LSO', 'LTU', 'LUX', 'LVA',
       'MAC', 'MAR', 'MDA', 'MDG', 'MDV', 'MEX', 'MKD', 'MLI', 'MLT',
       'MNG', 'MOZ', 'MRT', 'MSR', 'MUS', 'MWI', 'MYS', 'MYT', 'NAM',
       'NCL', 'NER', 'NGA', 'NIC', 'NLD', 'NOR', 'NPL', 'NZL', 'OMN',
       'PAN', 'PER', 'PHL', 'PNG', 'POL', 'PRT', 'PRY', 'PYF', 'QAT',
       'ROM', 'RUS', 'SAU', 'SDN', 'SEN', 'SER', 'SGP', 'SLV', 'STP',
       'SUR', 'SVK', 'SVN', 'SWE', 'SWZ', 'SYC', 'TCA', 'TGO', 'THA',
       'TKM', 'TON', 'TTO', 'TUN', 'TUR', 'TWN', 'TZA', 'UGA', 'UKR',
       'URY', 'USA', 'VCT', 'VEN', 'VNM', 'ZAF', 'ZMB', 'ZWE'],
      dtype=object)
  • 보고국 중에 나라가 아닌 All(세계 전체), EUN(유럽연합)이 포함돼있는 것에 유의해야 함(IM & EM 계산 코드 작성에서).

IM & EM 계산#

# 'trade_value를 x_i_k'로
df['x_i_k'] = df['trade_value']

# 각 reporter와 year별, 모든 제품에 대한 수출액 합계: sum_i_x_i_k
df['sum_i_x_i_k'] = df.groupby(['reporter', 'year'])['x_i_k'].transform('sum')

# 연도별로, reporter가 "All"인 행에서(만) temp1 생성 (즉, 해당 product의 세계 수출액)
df['temp1'] = np.where(df['reporter'] == "All", df['x_i_k'], np.nan)

# 연도와 product별로 temp1의 최댓값을 구해, 해당 product의 세계 수출액(temp2) 산출
df['temp2'] = df.groupby(['year', 'product'])['temp1'].transform('max')

# 각 reporter와 year별로, 자신이 수출하는 모든 제품에 대한 세계 수출액의 합: sum_i_x_w_k
df['sum_i_x_w_k'] = df.groupby(['reporter', 'year'])['temp2'].transform('sum')

# 연도별로, 모든 제품의 세계 수출액 합계: sum_w_x_w_k('x_i_k'가 아닌 'temp1'을 합쳐야 함)
df['sum_w_x_w_k'] = df.groupby('year')['temp1'].transform('sum')

# Intensive margin: im_i = (자국의 수출액 합계) / (해당 국가가 수출하는 제품의 세계 수출액 합계)
df['im_i'] = df['sum_i_x_i_k'] / df['sum_i_x_w_k']

# Extensive margin: em_i = (해당 국가가 수출하는 제품의 세계 수출액 합계) / (전세계 수출액 합계)
df['em_i'] = df['sum_i_x_w_k'] / df['sum_w_x_w_k']

# 데이터 확인
df.tail()
reporter reporter_name partner partner_name year product_name flow_name trade_value product x_i_k sum_i_x_i_k temp1 temp2 sum_i_x_w_k sum_w_x_w_k im_i em_i
358866 ZWE Zimbabwe WLD World 2000 Original engravings, prints and lit Gross Exp. 1.230000 970200 1.230000 1924812.875 NaN 1.737249e+05 4.551984e+09 5.946530e+09 0.000423 0.765486
358867 ZWE Zimbabwe WLD World 2000 Original sculptures and statuary, i Gross Exp. 5650.151855 970300 5650.151855 1924812.875 NaN 7.558062e+05 4.551984e+09 5.946530e+09 0.000423 0.765486
358868 ZWE Zimbabwe WLD World 2000 Used postage or revenue stamps and Gross Exp. 0.003000 970400 0.003000 1924812.875 NaN 1.566295e+05 4.551984e+09 5.946530e+09 0.000423 0.765486
358869 ZWE Zimbabwe WLD World 2000 Coll & coll pce of zoo,bot,mineral, Gross Exp. 10756.884766 970500 10756.884766 1924812.875 NaN 3.472393e+05 4.551984e+09 5.946530e+09 0.000423 0.765486
358870 ZWE Zimbabwe WLD World 2000 Antiques of an age exceeding one hu Gross Exp. 0.358000 970600 0.358000 1924812.875 NaN 2.053812e+06 4.551984e+09 5.946530e+09 0.000423 0.765486

결과 요약#

# 필요한 변수만 선택 및 중복 제거
df_sector = df[['reporter', 'year', 'im_i', 'em_i']].drop_duplicates()

# 백분율로 환산
df_sector['im_i'] = df_sector['im_i'] * 100
df_sector['em_i'] = df_sector['em_i'] * 100

print("=== Sectoral Decomposition Summary ===")
print(df_sector.describe())
=== Sectoral Decomposition Summary ===
         year        im_i        em_i
count   161.0  161.000000  161.000000
mean   2000.0    1.402866   61.412716
std       0.0    8.043442   29.487625
min    2000.0    0.000124    0.169205
25%    2000.0    0.021842   36.418358
50%    2000.0    0.074172   62.131310
75%    2000.0    0.581469   89.974213
max    2000.0  100.000000  100.000000

4. 시장 기준 IM & EM 계산 사례#

데이터#

# UNCTAD (2012) 원래 데이터세트가 용량이 너무 큼
# BilateralTrade.dta 파일 불러오기
BilateralTrade = pd.read_stata("../Data/BilateralTrade.dta")
BilateralTrade = BilateralTrade[BilateralTrade['year'] > 2000]
BilateralTrade.to_csv("../Data/BilateralTrade.csv")
# BilateralTrade.csv 파일 불러오기
df = pd.read_csv("../Data/BilateralTrade.csv")
df
Unnamed: 0 ccode pcode year isic2_3d imp_tv imp_q imp_uv exp_tv exp_q exp_uv id
0 0 ABW AIA 2002 311 0.000 NaN NaN 773.574 433812.0 1.783201 1.0
1 1 ABW AIA 2003 311 0.000 NaN NaN 63.463 50000.0 1.269260 1.0
2 2 ABW ALB 2004 351 8.452 11125.0 NaN 0.000 NaN NaN 2.0
3 3 ABW ALB 2004 352 1.363 1312.0 NaN 0.000 NaN NaN 3.0
4 28 ABW ARE 2003 311 0.000 NaN NaN 79.050 127609.0 NaN 10.0
... ... ... ... ... ... ... ... ... ... ... ... ...
1189499 5563250 ZWE ZMB 2002 385 52.346 NaN NaN 518.514 NaN NaN 545571.0
1189500 5563251 ZWE ZMB 2004 385 46.147 942.0 48.988320 121.252 19096.0 6.206012 545571.0
1189501 5563265 ZWE ZMB 2001 390 61.541 NaN NaN 7.266 NaN NaN 545572.0
1189502 5563266 ZWE ZMB 2002 390 32.965 NaN NaN 720.208 NaN NaN 545572.0
1189503 5563267 ZWE ZMB 2004 390 51.433 18167.0 2.831122 195.610 127486.0 1.534365 545572.0

1189504 rows × 12 columns

df['year'].unique()
array([2002, 2003, 2004, 2001], dtype=int64)

변수 설명

  • ccode: 보고국 코드

  • pcode: 상대국(파트너) 코드

  • year: 연도

  • isic2_3d: 국제표준산업분류(ISIC)의 3자리 코드

  • imp_tv: 수입 무역 가치(import trade value)

  • imp_q: 수입 수량(import quantity)

  • imp_uv: 수입 단위 가치(import unit value)

  • exp_tv: 수출 무역 가치(export trade value)

  • exp_q: 수출 수량(export quantity)

  • exp_uv: 수출 단위 가치(export unit value)

IM & EM 계산#

# (collapse) reporter, pcode, year별로 exp_tv, imp_tv의 합계 계산
df = df.groupby(['ccode', 'pcode', 'year'], as_index=False)[['exp_tv', 'imp_tv']].sum()

# x_i_d = exp_tv (각 행에서 정의)
df['x_i_d'] = df['exp_tv']

# 각 ccode, year별로, 해당 국가(ccode)가 모든 목적지에 대해 수출한 exp_tv 합계: sum_i_x_i_d
df['sum_i_x_i_d'] = df.groupby(['ccode', 'year'])['exp_tv'].transform('sum')

# 각 pcode, year별로, 해당 목적지에 대해 전세계의 exp_tv 합계: x_w_d
df['x_w_d'] = df.groupby(['pcode', 'year'])['exp_tv'].transform('sum')

# 각 ccode, year별로, 자신이 수출한 각 목적지의 x_w_d 합계: sum_i_x_w_d
df['sum_i_x_w_d'] = df.groupby(['ccode', 'year'])['x_w_d'].transform('sum')

# 연도별로, 전세계 모든 목적지에 대한 exp_tv 합계: sum_w_x_w_d
df['sum_w_x_w_d'] = df.groupby('year')['exp_tv'].transform('sum')

# 데이터 확인
df.tail()
ccode pcode year exp_tv imp_tv x_i_d sum_i_x_i_d x_w_d sum_i_x_w_d sum_w_x_w_d
85671 ZWE ZAR 2002 20254.741 131.937 20254.741 1512363.342 646382.879 5.037634e+09 5.192053e+09
85672 ZWE ZAR 2004 9353.682 227.687 9353.682 886468.378 919016.986 6.976600e+09 7.205177e+09
85673 ZWE ZMB 2001 9792.664 12135.245 9792.664 423323.647 832394.133 4.882801e+09 5.044125e+09
85674 ZWE ZMB 2002 175256.749 17891.871 175256.749 1512363.342 938409.948 5.037634e+09 5.192053e+09
85675 ZWE ZMB 2004 59845.738 18475.594 59845.738 886468.378 1168250.907 6.976600e+09 7.205177e+09

결과 요약#

# Geographical margins: 
# Extensive margin (em_i_geo) = sum_i_x_w_d / sum_w_x_w_d
# Intensive margin (im_i_geo) = sum_i_x_i_d / sum_w_x_w_d
df['em_i_geo'] = df['sum_i_x_w_d'] / df['sum_w_x_w_d']
df['im_i_geo'] = df['sum_i_x_i_d'] / df['sum_w_x_w_d']

# 필요한 변수만 선택 및 중복 제거
df_geo = df[['ccode', 'year', 'im_i_geo', 'em_i_geo']].drop_duplicates()

# 백분율로 환산
df_geo['im_i_geo'] = df_geo['im_i_geo'] * 100
df_geo['em_i_geo'] = df_geo['em_i_geo'] * 100

print("=== Geographical Decomposition Summary ===")
print(df_geo.describe())
=== Geographical Decomposition Summary ===
              year    im_i_geo    em_i_geo
count   576.000000  576.000000  576.000000
mean   2002.397569    0.694444   95.994293
std       1.100163    1.762331    5.154997
min    2001.000000    0.000000   52.361689
25%    2001.000000    0.005416   95.758290
50%    2002.000000    0.033377   97.642437
75%    2003.000000    0.360029   98.684235
max    2004.000000   13.005763   99.936176

4개국(ARG, COL, MEX, ESP) 결과 그림#

countries = ['ARG', 'COL', 'MEX', 'ESP'] 

for country in countries:
    subset = df_geo[df_geo['ccode'] == country]
    if not subset.empty:
        fig, ax1 = plt.subplots(figsize=(6, 4), dpi=500)
        ax1.scatter(subset['year'], subset['im_i_geo'], marker='D', color='navy', label="IM")
        ax1.set_xlabel("Year")
        ax1.set_ylabel("Intensive Margin (IM) [%]", color='navy')
        ax1.tick_params(axis='y', labelcolor='navy')
        
        # Set x-ticks to only those years present in the subset
        ax1.set_xticks(sorted(subset['year'].unique()))
        
        ax2 = ax1.twinx()
        ax2.scatter(subset['year'], subset['em_i_geo'], marker='s', color='darkred', label="EM")
        ax2.set_ylabel("Extensive Margin (EM) [%]", color='darkred')
        ax2.tick_params(axis='y', labelcolor='darkred')
        
        plt.title(f"Geographical Decomposition for {country}")
        plt.show()
../_images/02a9f39ecabf05a5177b69f49b67f89d7f3bfba20eb8e8bc349e0d00733c6002.png ../_images/a342df4084c9bc10d16ac21d6be7aa2c81a4850c045d26a154579ac8ec385372.png ../_images/77432a02ebab38fab8a1f16478c374968b6682a045d458cb50d1501618e6ce5d.png ../_images/0147ff086d193d7417c9b516b1458fc9b123db1a64dd9f3d99898b614d7aa9ab.png