합계출산율 추이와 결혼 출산 인식 변화: R로 시각화하기

합계출산율 추이를 살펴보는 것은 한 사회의 미래를 예측하는 중요한 요소로, 이에 대한 사회적 의견과 결혼 출산 인식 변화는 정책 방향 설정과 문화적 흐름을 이해하는 데 핵심적인 역할을 합니다.

이번 포스트에서는 R의 ggplot2patchwork 패키지를 활용해 합계출산율 추이과 결혼 출산 인식 변화를 시각화하고, 두 요소 간의 상관관계를 분석하는 방법을 소개합니다. 아래에서 제시하는 예제는 현실 데이터를 기반으로 한 가상의 데이터를 사용해 트렌드와 상관관계를 시각적으로 보여줍니다.

합계출산율 추이과 결혼 출산 인식 변화 데이터 생성

이 분석은 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_longtfr_data)을 Year를 기준으로 결합.
  • 결과적으로, 각 연도별로 의견 비율(Percentage)과 합계출산율(TFR)이 포함된 데이터프레임을 생성.

상관관계 분석을 위한 데이터 준비

correlation_data <- opinion_data %>%
    select(-Year) %>%
    mutate(TFR = tfr_data$TFR[match(opinion_data$Year, tfr_data$Year)])
  1. select(-Year): Year 열을 제외한 데이터프레임을 생성.
  2. mutate(TFR = ...): TFR 열을 추가. match를 사용하여 opinion_datatfr_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)))
  1. cor(): 상관계수 행렬을 계산. use = "complete.obs"는 결측치를 제외하고 계산.
  2. cor_matrix["TFR", ]: TFR과 다른 열 사이의 상관계수만 추출.
  3. filter(Variable != "TFR"): TFR과 자기 자신(TFR)의 상관계수를 제외.
  4. 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()
  1. aes(x = reorder(Variable, abs(TFR)), y = TFR): 상관계수를 절대값 기준으로 정렬하여 그래프 축에 배치.
  2. geom_bar(): 막대 그래프 생성.
  3. scale_fill_gradient2(): 색상을 상관계수 값에 따라 변환(양수는 녹색, 음수는 빨간색).
  4. geom_text(): 상관계수를 그래프에 텍스트로 추가.
  5. 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()
  1. geom_point(): 의견별 점 그래프 생성.
  2. geom_smooth(): 각 의견 범주에 대해 선형 회귀선을 추가.
  3. geom_text_repel(): 각 점에 겹치지 않는 텍스트 레이블 추가. 텍스트에는 TFRPercentage 값이 표시됨.
  4. scale_color_manual(): 의견 범주별로 서로 다른 색상 지정.

결과물 출력

print(correlation_plot)
print(scatter_matrix)
  • 각각 상관관계 막대 그래프와 산점도를 출력하여 데이터를 시각적으로 분석합니다.

유사한 게시물