합계출산율 추이와 결혼 출산 인식 변화: R로 시각화하기
합계출산율 추이를 살펴보는 것은 한 사회의 미래를 예측하는 중요한 요소로, 이에 대한 사회적 의견과 결혼 출산 인식 변화는 정책 방향 설정과 문화적 흐름을 이해하는 데 핵심적인 역할을 합니다.
이번 포스트에서는 R의 ggplot2와 patchwork 패키지를 활용해 합계출산율 추이과 결혼 출산 인식 변화를 시각화하고, 두 요소 간의 상관관계를 분석하는 방법을 소개합니다. 아래에서 제시하는 예제는 현실 데이터를 기반으로 한 가상의 데이터를 사용해 트렌드와 상관관계를 시각적으로 보여줍니다.
합계출산율 추이과 결혼 출산 인식 변화 데이터 생성
이 분석은 2018년부터 2024년까지의 합계출산율 추이 데이터와 결혼·출산에 대한 사회적 의견 변화 데이터를 기반으로 합니다. 데이터를 간단히 생성하고 이를 시각화하여 트렌드를 분석합니다.(데이터는 통계청 발표에 근거합니다.)
R 시각화 코드
# 필요한 라이브러리 로드
library(ggplot2)
library(dplyr)
library(tidyr)
library(patchwork)
library(ggrepel)
# 데이터 생성: 합계출산율
tfr_data <- data.frame(
Year = 2018:2024,
TFR = c(0.977, 0.918, 0.837, 0.808, 0.778, 0.720, 0.701)
)
# 데이터 생성: 결혼 출산 인식 변화
opinion_data <- data.frame(
Year = c(2018, 2020, 2022, 2024),
Strongly_Agree = c(25.4, 25.5, 21.6, 23.4),
Somewhat_Agree = c(44.1, 42.6, 43.8, 44.9),
Somewhat_Disagree = c(21.9, 22.1, 23.9, 22.7),
Strongly_Disagree = c(8.6, 9.8, 10.8, 9.0)
)
# 긴 형식으로 변환
opinion_long <- opinion_data %>%
pivot_longer(
cols = starts_with("Strongly") | starts_with("Somewhat"),
names_to = "Opinion",
values_to = "Percentage"
)
# 결합 데이터 생성
merged_data <- left_join(opinion_long, tfr_data, by = "Year")
# 상관관계 분석을 위한 데이터 준비
correlation_data <- opinion_data %>%
select(-Year) %>%
mutate(TFR = tfr_data$TFR[match(opinion_data$Year, tfr_data$Year)])
# 상관계수 계산
cor_matrix <- cor(correlation_data, use = "complete.obs")
cor_data <- as.data.frame(cor_matrix["TFR", ])
cor_data$Variable <- rownames(cor_data)
colnames(cor_data)[1] <- "TFR"
cor_data <- cor_data %>%
filter(Variable != "TFR") %>%
arrange(desc(abs(TFR)))
# 상관관계 시각화
correlation_plot <- ggplot(cor_data, aes(x = reorder(Variable, abs(TFR)), y = TFR)) +
geom_bar(stat = "identity", aes(fill = TFR), width = 0.6) +
scale_fill_gradient2(
low = "#D73027",
mid = "white",
high = "#1A9850",
midpoint = 0
) +
geom_text(
aes(label = sprintf("%.3f", TFR)),
vjust = ifelse(cor_data$TFR >= 0, -0.5, 1.5),
size = 4
) +
labs(
title = "Correlation Analysis: TFR vs Opinion Categories",
x = "Opinion Category",
y = "Correlation Coefficient"
) +
coord_flip() +
theme_minimal() +
theme(
axis.text = element_text(size = 10),
axis.title = element_text(size = 12, face = "bold"),
plot.title = element_text(size = 14, face = "bold"),
legend.position = "none"
)
# 산점도 매트릭스 생성
scatter_matrix <- ggplot(merged_data, aes(x = TFR, y = Percentage)) +
geom_point(aes(color = Opinion), size = 3, alpha = 0.6) +
geom_smooth(aes(color = Opinion), method = "lm", se = FALSE, linetype = "dashed") +
scale_color_manual(
values = c(
"Strongly_Agree" = "#1F78B4",
"Somewhat_Agree" = "#33A02C",
"Somewhat_Disagree" = "#FB9A99",
"Strongly_Disagree" = "#E31A1C"
)
) +
labs(
title = "TFR vs Opinion Categories Relationship",
x = "Total Fertility Rate",
y = "Percentage (%)"
) +
theme_minimal() +
theme(
legend.position = "bottom",
plot.title = element_text(size = 14, face = "bold"),
axis.title = element_text(size = 12, face = "bold")
)
# 시각화 출력
print(correlation_plot)
print(scatter_matrix)분석 및 인사이트

1. TFR과 사회적 인식 간 상관관계 분석
- 긍정적 의견(Agree)과의 상관관계:
- “Strongly Agree”는 TFR과 가장 높은 상관계수(0.644)를 보이며, 결혼과 출산에 대한 강한 긍정적 견해가 출산율 상승과 밀접한 관계가 있음을 보여줍니다.
- “Somewhat Agree”의 상관계수는 -0.314로, 긍정적이지만 다소 유보적인 의견은 TFR에 상대적으로 적은 영향을 미치는 것으로 나타났습니다.
- 부정적 의견(Disagree)과의 상관관계:
- “Somewhat Disagree”와 “Strongly Disagree”는 각각 -0.589와 -0.388의 상관계수를 보이며, 부정적 의견이 확산될수록 TFR 감소에 기여하고 있음을 보여줍니다.
- 특히 “Somewhat Disagree”의 상관계수가 가장 높아, 강한 부정보다는 부분적인 부정 의견이 출산율 감소에 더 큰 영향을 미칠 가능성을 시사합니다.

2. 상관분석을 통한 사회적 인식과 TFR 간 관계
- 상관분석 결과를 시각화한 Correlation Plot에서는 “Strongly Agree”와 TFR 간의 강한 양의 상관관계가 강조됩니다.
- Scatter Matrix Plot에서는 TFR과 다양한 의견 범주 간의 분포와 관계가 명확히 드러납니다. 특히 긍정적 의견이 높을수록 TFR이 상승하는 경향이 나타나며, 부정적 의견이 많을수록 출산율 감소 경향이 강화되는 패턴을 확인할 수 있습니다.
결론 및 정책적 제언

1. 출산율 감소에 대한 다각적 접근 필요
- 출산율 감소는 단순히 경제적 지원으로 해결할 수 없는 다층적 문제입니다. 사회적 인식 변화와 정책적 지원이 병행되어야 합니다.
- 주요 정책 방향:
- 주거 안정화: 주택 비용 부담을 줄여 안정적인 가정을 꾸릴 수 있는 환경을 조성.
- 양육비 지원 확대: 공공 보육 시스템 강화와 양육비 보조금 지급.
- 일과 가정의 균형 지원: 육아휴직 제도 개선과 여성 경력 단절 방지.
2. 긍정적 인식 확대를 위한 노력
- 결혼과 출산에 대한 긍정적 메시지를 확산시키는 캠페인과 사회적 담론을 강화해야 합니다.
- 특히, 젊은 세대를 대상으로 출산과 결혼의 긍정적 측면을 알리고, 선택권을 존중하는 환경을 만들어야 합니다.
3. 부정적 의견 완화
- 결혼과 출산을 주저하게 만드는 사회적, 경제적, 문화적 요인을 분석하고, 이를 해결하기 위한 근본적인 접근이 필요합니다.
- 출산과 결혼이 개인적 희생이 아닌, 개인의 성장과 만족을 가져오는 과정으로 인식될 수 있도록 해야 합니다.
4. 데이터 기반 정책 수립
- 상관분석 결과는 사회적 인식 변화가 출산율에 실질적인 영향을 미치고 있음을 보여줍니다.
- 데이터를 지속적으로 모니터링하고, 이를 기반으로 한 정책 수립은 향후 출산율 안정화에 큰 기여를 할 것입니다.
위 분석과 시각화를 통해 결혼과 출산에 대한 인식 변화가 출산율에 어떤 영향을 미치는지 명확히 이해할 수 있습니다. 이를 기반으로 사회적 논의와 정책이 보다 심층적이고 효과적으로 전개되길 기대합니다.
# 코드 상세해설
필요한 라이브러리 로드
library(ggplot2) library(dplyr) library(tidyr) library(patchwork) library(ggrepel)
- ggplot2: 데이터 시각화를 위한 R의 대표적인 그래프 패키지.
- dplyr: 데이터 조작과 변환을 쉽게 해주는 패키지.
- tidyr: 데이터를 긴 형식으로 변환하거나 정리하는 데 사용.
- patchwork: 여러 그래프를 하나의 레이아웃으로 결합할 때 사용.
- ggrepel: 그래프에서 겹치지 않는 레이블을 추가하기 위해 사용.
데이터 생성: 합계출산율
tfr_data <- data.frame( Year = 2018:2024, TFR = c(0.977, 0.918, 0.837, 0.808, 0.778, 0.720, 0.701) )
Year: 2018년부터 2024년까지의 연도.TFR: 해당 연도의 합계출산율 데이터를 가상의 값으로 생성.데이터 생성: 결혼·출산 인식 변화
opinion_data <- data.frame( Year = c(2018, 2020, 2022, 2024), Strongly_Agree = c(25.4, 25.5, 21.6, 23.4), Somewhat_Agree = c(44.1, 42.6, 43.8, 44.9), Somewhat_Disagree = c(21.9, 22.1, 23.9, 22.7), Strongly_Disagree = c(8.6, 9.8, 10.8, 9.0) )
Year: 의견 변화가 측정된 연도.- 네 개의 의견 범주(
Strongly_Agree,Somewhat_Agree,Somewhat_Disagree,Strongly_Disagree)에 대한 비율(%) 데이터를 생성.긴 형식으로 변환
opinion_long <- opinion_data %>% pivot_longer( cols = starts_with("Strongly") | starts_with("Somewhat"), names_to = "Opinion", values_to = "Percentage" )
pivot_longer(): 데이터를 “긴 형식”으로 변환하여Opinion열에 의견 범주를,Percentage열에 각 의견의 비율을 저장.
cols = starts_with("Strongly") | starts_with("Somewhat"): 열 이름이Strongly또는Somewhat로 시작하는 열을 변환 대상으로 지정.names_to = "Opinion": 의견 범주를Opinion열에 저장.values_to = "Percentage": 각 범주의 비율 값을Percentage열에 저장.결합 데이터 생성
merged_data <- left_join(opinion_long, tfr_data, by = "Year")
left_join: 두 데이터프레임(opinion_long과tfr_data)을Year를 기준으로 결합.- 결과적으로, 각 연도별로 의견 비율(
Percentage)과 합계출산율(TFR)이 포함된 데이터프레임을 생성.상관관계 분석을 위한 데이터 준비
correlation_data <- opinion_data %>% select(-Year) %>% mutate(TFR = tfr_data$TFR[match(opinion_data$Year, tfr_data$Year)])
select(-Year):Year열을 제외한 데이터프레임을 생성.mutate(TFR = ...):TFR열을 추가.match를 사용하여opinion_data와tfr_data의 연도를 매칭시켜TFR값을 가져옴.상관계수 계산
cor_matrix <- cor(correlation_data, use = "complete.obs") cor_data <- as.data.frame(cor_matrix["TFR", ]) cor_data$Variable <- rownames(cor_data) colnames(cor_data)[1] <- "TFR" cor_data <- cor_data %>% filter(Variable != "TFR") %>% arrange(desc(abs(TFR)))
cor(): 상관계수 행렬을 계산.use = "complete.obs"는 결측치를 제외하고 계산.cor_matrix["TFR", ]:TFR과 다른 열 사이의 상관계수만 추출.filter(Variable != "TFR"):TFR과 자기 자신(TFR)의 상관계수를 제외.arrange(desc(abs(TFR))): 절대값 기준으로 상관계수를 내림차순 정렬.상관관계 시각화
correlation_plot <- ggplot(cor_data, aes(x = reorder(Variable, abs(TFR)), y = TFR)) + geom_bar(stat = "identity", aes(fill = TFR), width = 0.6) + scale_fill_gradient2( low = "#D73027", mid = "white", high = "#1A9850", midpoint = 0 ) + geom_text( aes(label = sprintf("%.3f", TFR)), vjust = ifelse(cor_data$TFR >= 0, -0.5, 1.5), size = 4 ) + labs( title = "Correlation Analysis: TFR vs Opinion Categories", x = "Opinion Category", y = "Correlation Coefficient" ) + coord_flip() + theme_minimal()
aes(x = reorder(Variable, abs(TFR)), y = TFR): 상관계수를 절대값 기준으로 정렬하여 그래프 축에 배치.geom_bar(): 막대 그래프 생성.scale_fill_gradient2(): 색상을 상관계수 값에 따라 변환(양수는 녹색, 음수는 빨간색).geom_text(): 상관계수를 그래프에 텍스트로 추가.coord_flip(): X축과 Y축을 뒤집어 가로형 막대 그래프 생성.산점도 매트릭스 생성
scatter_matrix <- ggplot(merged_data, aes(x = TFR, y = Percentage)) + geom_point(aes(color = Opinion), size = 3, alpha = 0.6) + geom_smooth(aes(color = Opinion), method = "lm", se = FALSE, linetype = "dashed") + geom_text_repel( aes( label = paste0("(", round(TFR, 3), ", ", round(Percentage, 1), ")"), color = Opinion ), size = 3, box.padding = 0.5, point.padding = 0.3, force = 2, max.overlaps = Inf, show.legend = FALSE ) + labs( title = "TFR vs Opinion Categories Relationship", x = "Total Fertility Rate", y = "Percentage (%)" ) + theme_minimal()
geom_point(): 의견별 점 그래프 생성.geom_smooth(): 각 의견 범주에 대해 선형 회귀선을 추가.geom_text_repel(): 각 점에 겹치지 않는 텍스트 레이블 추가. 텍스트에는TFR과Percentage값이 표시됨.scale_color_manual(): 의견 범주별로 서로 다른 색상 지정.결과물 출력
print(correlation_plot) print(scatter_matrix)
- 각각 상관관계 막대 그래프와 산점도를 출력하여 데이터를 시각적으로 분석합니다.




