초안입니다. 과거 프로젝트의 분석방법을 남기기 위한 기록이며, 원자료와 최종 결과 파일은 블로그에 포함하지 않습니다. 아래 코드는 모두 구조를 보여주는 예시이며 실행하지 않습니다.
1 총평
이 분석은 기업의 재무·혁신 지표를 시장성과 혁신성이라는 두 축으로 축약한 뒤, 두 축의 상대적 위치로 기업군을 분류한 사례다. 단일 지표로 기업을 줄 세우지 않고, 상관행렬과 요인분석으로 지표 묶음을 확인한 점이 장점이다.
다만 원 코드는 산업별 반복 블록이 많고, 요인적재량 가중치를 행 번호로 참조하는 부분이 있다. 인수인계용으로는 변수명 기준 가중치 적용 방식이 더 안전하다.
2 분석 흐름
정밀의료바이오헬스 사례는 다음 순서로 진행했다.
- 기업 DB와 재무자료를 결합한다.
- 법인기업만 남기고 개인기업·대기업은 제외한다.
- 평균, CAGR, 비율지표를 만든다.
- 상관행렬로 후보 변수를 고른다.
- 아이젠밸류와 스크리도표로 요인 수를 정한다.
- 요인적재량으로 시장성·혁신성 점수식을 만든다.
- 백분위 기준으로 기업군을 분류한다.
3 요인분석
요인분석은 여러 관측변수 뒤에 숨어 있는 소수의 공통요인을 찾는 방법이다. 예를 들어 매출액, 종업원수, 자본금이 함께 움직인다면, 세 변수를 각각 따로 쓰기보다 시장성·규모라는 하나의 요인으로 요약할 수 있다.
\[ X_j = \lambda_{j1}F_1 + \lambda_{j2}F_2 + \cdots + \lambda_{jm}F_m + \epsilon_j \]
여기서 \(X_j\)는 관측변수, \(F_m\)은 공통요인, \(\lambda_{jm}\)은 요인적재량, \(\epsilon_j\)는 고유오차다. 요인적재량은 특정 변수가 특정 요인과 얼마나 강하게 연결되는지를 뜻한다.
flowchart LR A1[매출액] --> F1[시장성 요인] A2[종업원수] --> F1 A3[자본금] --> F1 B1[특허출원] --> F2[혁신성 요인] B2[특허등록] --> F2 B3[R&D 성장] --> F2
4 1. 상관행렬
먼저 정밀의료바이오헬스 기업만 남긴 뒤, 기업-지표 행렬의 상관행렬을 계산했다. 이 단계에서는 다른 변수와 거의 연결되지 않는 고립 변수를 제외하고, 요인으로 묶일 가능성이 있는 변수만 후보로 남겼다.
cor_bio <- cor(
df_bio[, -1],
use = "pairwise.complete.obs"
)
varlist_bio <- cor_bio |>
as.data.frame() |>
tibble::rownames_to_column("variable") |>
dplyr::mutate(
dplyr::across(
-1,
~ ifelse(.x == 1, NA, .x)
)
) |>
dplyr::rowwise() |>
dplyr::mutate(
max_abs_cor = max(
abs(dplyr::c_across(-1)),
na.rm = TRUE
)
) |>
dplyr::ungroup() |>
dplyr::filter(max_abs_cor >= 0.5) |>
dplyr::pull(variable)5 2. 요인 수 결정
요인 수는 상관행렬의 아이젠밸류를 보고 정했다. 아이젠밸류는 각 요인이 설명하는 분산의 크기다. 보고서 흐름에서는 스크리도표에서 꺾이는 지점과 해석 가능성을 함께 보고 3개 요인을 선택했다.
cor_mat <- cor(df_bio_final[, -1])
eigen_value <- eigen(cor_mat)$values
scree_bio <- data.table(
factor = seq_along(eigen_value),
eigenvalue = eigen_value
)
ggplot(
scree_bio,
aes(x = factor, y = eigenvalue)
) +
geom_point(size = 3) +
geom_line(linewidth = 0.8) +
labs(
x = "요인 번호",
y = "아이젠밸류"
) +
theme_classic()정밀의료바이오헬스의 최종 요인 해석은 다음과 같다.
| 요인 | 주요 적재 변수 | 해석 |
|---|---|---|
| ML1 | 특허출원건수 평균, 특허등록건수 평균 | 혁신성과 |
| ML2 | 연구개발비 CAGR, 연구개발비비중 CAGR | 혁신투입 성장성 |
| ML3 | 매출액 평균, 종업원수 평균, 자본금 평균 | 시장성·규모 |
6 3. 요인적재량과 가중치
요인분석은 psych::fa()를 사용했다. 회전은 varimax, 추정방법은 ml을 적용했다. 요인적재량 절대값이 0.5 미만인 값은 해석에서 제외했다.
변수 가중치는 같은 요인 안에서 요인적재량 합이 1이 되도록 표준화했다.
\[ w_{jk} = \frac{\lambda_{jk}}{\sum_j \lambda_{jk}} \]
최종 시장성·혁신성 점수에는 요인 수준 가중치도 적용했다. 요인 수준 가중치는 각 요인의 설명비율, 즉 아이젠밸류 기반 분산 설명력을 이용했다.
7 4. 점수식
먼저 모든 지표를 0-1 범위로 스케일링했다.
\[ x' = \frac{x - min(x)}{max(x) - min(x)} \]
정밀의료바이오헬스의 요인별 점수식은 다음 구조다.
\[ ML1 = 특허출원건수평균' \cdot w_{특허출원,ML1} + 특허등록건수평균' \cdot w_{특허등록,ML1} \]
\[ ML2 = 연구개발비CAGR' \cdot w_{R\&D,ML2} + 연구개발비비중CAGR' \cdot w_{R\&D비중,ML2} \]
\[ ML3 = 매출액평균' \cdot w_{매출,ML3} + 종업원수평균' \cdot w_{고용,ML3} + 자본금평균' \cdot w_{자본,ML3} \]
최종 축은 다음처럼 재조합했다.
\[ 시장성 = ML3 \cdot W_{ML3} \]
\[ 혁신성 = ML1 \cdot W_{ML1} + ML2 \cdot W_{ML2} \]
코드로 표현하면 아래와 같다. 원 코드의 행 번호 참조 방식보다, 변수명으로 가중치를 가져오는 방식이 더 안전하다.
df_bio_final <- df_bio_final |>
dplyr::mutate(
ML1 =
특허출원건수_평균_스케일링 *
w["특허출원건수_평균", "ML1"] +
특허등록건수_평균_스케일링 *
w["특허등록건수_평균", "ML1"],
ML2 =
연구개발비_CAGR_스케일링 *
w["연구개발비_CAGR", "ML2"] +
연구개발비비중_CAGR_스케일링 *
w["연구개발비비중_CAGR", "ML2"],
ML3 =
매출액_평균_스케일링 *
w["매출액_평균", "ML3"] +
종업원수_평균_스케일링 *
w["종업원수_평균", "ML3"] +
자본금_평균_스케일링 *
w["자본금_평균", "ML3"],
시장성 = ML3 * factor_w["ML3"],
혁신성 =
ML1 * factor_w["ML1"] +
ML2 * factor_w["ML2"]
)8 5. 기업 분류
시장성·혁신성 점수는 백분위로 바꿨다. 값이 작을수록 상위 기업이 되도록 1 - percent_rank()를 사용했다.
| 분류 | 기준 |
|---|---|
| 선도기업 | 시장성백분위 <= 0.1, 혁신성백분위 <= 0.1 |
| 예비선도기업 | 두 백분위가 모두 0.3 이하 |
| 잠재기업 | 두 백분위가 모두 0.5 이하 |
| 열외기업 | 시장성 또는 혁신성 백분위가 0.5 초과 |
선도기업은 2단계 조건을 추가로 적용했다. 최근 3년 평균매출액이 기준 이상이고, R&D 집약도가 기준 이상이거나 연구소를 보유해야 최종 선도기업으로 남겼다.
flowchart TB
T["정밀의료바이오헬스 기업 분류"]
T --> M{"시장성 백분위<br/>0.5 이하인가?"}
M -- 아니오 --> O["열외기업"]
M -- 예 --> I{"혁신성 백분위<br/>0.5 이하인가?"}
I -- 아니오 --> O
I -- 예 --> P{"시장성·혁신성<br/>모두 0.3 이하인가?"}
P -- 아니오 --> L["잠재기업"]
P -- 예 --> S{"시장성·혁신성<br/>모두 0.1 이하인가?"}
S -- 아니오 --> E["예비선도기업"]
S -- 예 --> C["선도기업"]
C --> C2{"2단계 조건 충족?<br/>매출 규모 + R&D 기준"}
C2 -- 예 --> C3["최종 선도기업"]
C2 -- 아니오 --> E2["예비선도기업으로 조정"]
실제 보고서용 그림은 아래처럼 그릴 수 있다. 한글이 깨지는 경우에는 ragg 장치와 한글 폰트 계열을 명시한다.
knitr::opts_chunk$set(
dev = "ragg_png",
dpi = 144
)
theme_set(
theme_classic(base_family = "Pretendard")
)
ggplot(
df_bio_final,
aes(
x = 시장성백분위,
y = 혁신성백분위
)
) +
geom_hline(
yintercept = c(0.1, 0.3, 0.5),
linetype = "dashed",
linewidth = 0.35,
color = "grey45"
) +
geom_vline(
xintercept = c(0.1, 0.3, 0.5),
linetype = "dashed",
linewidth = 0.35,
color = "grey45"
) +
geom_point(
aes(color = 기업군),
size = 2.4,
alpha = 0.85
) +
scale_x_reverse(limits = c(1, 0)) +
scale_y_reverse(limits = c(1, 0)) +
labs(
x = "시장성 백분위",
y = "혁신성 백분위",
color = NULL
) +
theme(
legend.position = "bottom",
text = element_text(family = "Pretendard")
)9 정리
이 분석은 요인분석 결과를 그대로 최종 결론으로 쓰기보다, 요인적재량과 아이젠밸류를 이용해 정책지표용 가중합 점수식을 만든 사례다. 핵심은 세 가지다.
첫째, 상관행렬과 스크리도표는 변수 선택과 요인 수 결정을 위한 탐색 단계다. 둘째, 시장성·혁신성은 원자료에 있는 단일 지표가 아니라 요인분석 기반의 재구성 지표다. 셋째, 기업군 분류는 산업 내부의 상대평가이므로 다른 산업과 백분위 값을 직접 비교하면 안 된다.