library(readxl)
library(psych)
library(lattice)
library(ggplot2)
## 
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
## 
##     %+%, alpha
library(showtext)
## Loading required package: sysfonts
## Loading required package: showtextdb
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(forcats)
library(scales)
## 
## Attaching package: 'scales'
## The following objects are masked from 'package:psych':
## 
##     alpha, rescale
library(tidyr)
library(stringr)

#install.packages("forcats")
#install.packages("showtext")
#install.packages("sysfonts")
#install.packages("curl")
#install.packages("scales")
#install.packages("tidyr")
#install.packages("stringr")

library(showtext)
library(sysfonts)

font_add_google("Noto Sans KR", "Noto Sans KR")
showtext_auto()
df <- read_excel("Austin_Animal_Center_Outcomes_(2020~2025).xlsx")
#View(df)

C375123 정유진_Big Data 502분반_분석보고서
2025.06.12.

  1. 프로젝트 주제 유기동물 입양 결정 요인에 대한 통합 분석: 건강, 연령, 보호 상태, 시계열 구조 중심으로

  2. 데이터 분석의 목적

  • 유기동물의 구조, 보호, 입양 전환 과정을 시계열로 분석하여 입양 성패를 가르는 결정 요인을 규명하고자 한다.
  • 건강, 연령, 품종, 색상, 중성화 여부, 보호 상태 등 다차원 요인 간 상관관계 시각화를 수행한다.
  • 입양률 향상, 정책 개입, 보호소 운영 전략 및 디자인 방향을 도출하고자 한다.
  1. 데이터 개요
  • 출처: https://data.austintexas.gov/Health-and-Community-Services/Austin-Animal-Center-Outcomes/9t4d-g238/about_data\ Austin Animal Center Outcomes
  • 파일명: Austin_Animal_Center_Outcomes_(2020~2025).xlsx
  • 관측치 수 (행 수): 59,089개
  • 변수 수 (열 수): 12개
  • 가공전 주요 변수 설명: id_1 / birth_2 / outcome_4 / month_5: / type_6 / subtype_7 / species_8:/ sex_9 / age_10 / breed_11 / color_12
  • 가공 후 주요 변수 설명: date: 구조일자, month: 사건 월, season: 계절, type_kr: 사건 유형, subtype_kr: 보호 상태, species_kr: 종, sex_kr: 성별+중성화, neuter_status_kr: 중성화 여부, age_10_kr: 나이 , age_group: 나이 범주, breed_kr: 품종, color_kr: 색상, adopted: 입양 여부
  1. 데이터 전처리 항목

*3의 가공 후 주요 변수에 대하여 전처리를 진행하며, 다음과 같다.

본 데이터는 동물 보호소 사건 데이터를 기반으로 하며, 총 10만여 건의 사건 기록을 포함한다. 각 행은 한 개체의 구조 및 이후 조치를 의미한다. 전처리 과정에서는 날짜 포맷 통일, 계절/연령 범주 생성, 품종/색상 정제, 입양 여부 이진화를 수행하였다.

  • 날짜 → Date 포맷 변환 및 월, 계절 파생 변수 생성
  • 나이 → 월/년 단위로 환산 후 연령 그룹화 (ex. 1~3살, 10살 이상)
  • 성별+중성화 상태 분리 및 정제
  • 입양 여부 이진화 (입양/비입양)
  • 색상/품종 간소화 및 카테고리 통일
  • 건강 상태 주요 분류군으로 통합

영문 → 한글 변환 작업

df <- df %>%
  mutate(
species_kr = recode(species_8,
                        "Dog" = "개", "Cat" = "고양이", "Bird"="새", "Livestock"="가축", "Other" = "기타"),
    
    sex_kr = recode(sex_9,
                    "Neutered Male" = "중성화 수컷","Spayed Female" = "중성화 암컷", "Intact Male" = "비중성화 수컷", "Intact Female" = "비중성화 암컷","Unknown" = "미상"),
    
    neuter_status = case_when(
      grepl("Spayed|Neutered", sex_9) ~ "중성화", grepl("Intact", sex_9) ~ "비중성화",
      TRUE ~ "미상"
    ),
    neuter_status_kr = factor(neuter_status,levels = c("중성화", "비중성화", "미상")),

    subtype_kr = recode(subtype_7,
                        "Snr" = "노령","Suffering" = "고통", "At Vet" = "병원 치료 중", "Rabies Risk" = "광견병 위험", "Foster" = "임시보호", "Partner" = "제휴기관","In Kennel" = "보호소 내","Field" = "현장 구조","Out State" = "타주 전송","Enroute" = "이송 중","In Surgery" = "수술 중", "In Foster" = "임보 중", "Medical" = "의료 필요" ,"Quarantine" = "격리 중", "Behavior" = "행동 문제", "Kennel" = "보호소 케널", "Pre-Adopt" = "입양 전 절차", "Offsite" = "외부 시설", "Cit Support" = "시민 지원", "Med Behavior" = "의료/행동 문제", "Barn" = "외양간 임시보호", "Underage" = "미성년 개체", "Neonatal" = "신생아", "Owner Surrender" = "주인 포기", "Awaiting Surgery" = "수술 대기 중", "Foster Hospice" = "호스피스 임보", "Nursing" = "수유 중",
      .default = "기타"),

    type_kr = recode(type_6,
                     "Adoption" = "입양","Transfer" = "이송","Return to Owner" = "주인 반환","Euthanasia" = "안락사","Died" = "사망",
                     .default = "기타"),

    adopted = ifelse(type_kr == "입양", "입양", "비입양"),

    color_kr = case_when(
      grepl("Black", color_12, ignore.case = TRUE) ~ "검정",
      grepl("White", color_12, ignore.case = TRUE) ~ "하양",
      grepl("Brown", color_12, ignore.case = TRUE) ~ "갈색",
      grepl("Tan", color_12, ignore.case = TRUE) ~ "탄색",
      grepl("Orange", color_12, ignore.case = TRUE) ~ "주황",
      grepl("Blue", color_12, ignore.case = TRUE) ~ "회색",
      grepl("Gray|Grey", color_12, ignore.case = TRUE) ~ "회색",
      grepl("Tabby", color_12, ignore.case = TRUE) ~ "줄무늬",
      grepl("Tricolor|Tri", color_12, ignore.case = TRUE) ~ "삼색",
      grepl("Brindle", color_12, ignore.case = TRUE) ~ "브린들",
      grepl("Calico", color_12, ignore.case = TRUE) ~ "캘리코",
      grepl("Cream", color_12, ignore.case = TRUE) ~ "크림",
      grepl("Gold", color_12, ignore.case = TRUE) ~ "금색",
      grepl("Chocolate", color_12, ignore.case = TRUE) ~ "초코",
      grepl("Red", color_12, ignore.case = TRUE) ~ "붉은색",
      grepl("Fawn", color_12, ignore.case = TRUE) ~ "베이지",
      TRUE ~ "기타"
    ),

    breed_kr = case_when(
      grepl("Domestic Shorthair", breed_11, ignore.case = TRUE) ~ "국내 단모종 고양이",
      grepl("Domestic Medium Hair", breed_11, ignore.case = TRUE) ~ "국내 중모종 고양이",
      grepl("Domestic Longhair", breed_11, ignore.case = TRUE) ~ "국내 장모종 고양이",
      grepl("Pit Bull", breed_11, ignore.case = TRUE) ~ "핏불",
      grepl("Chihuahua", breed_11, ignore.case = TRUE) ~ "치와와",
      grepl("Labrador", breed_11, ignore.case = TRUE) ~ "래브라도 리트리버",
      grepl("German Shepherd", breed_11, ignore.case = TRUE) ~ "저먼 셰퍼드",
      grepl("Dachshund", breed_11, ignore.case = TRUE) ~ "닥스훈트",
      grepl("Australian Cattle Dog", breed_11, ignore.case = TRUE) ~ "오스트레일리안 캐틀 독",
      grepl("Boxer", breed_11, ignore.case = TRUE) ~ "복서",
      grepl("Beagle", breed_11, ignore.case = TRUE) ~ "비글",
      grepl("Siberian Husky", breed_11, ignore.case = TRUE) ~ "시베리안 허스키",
      grepl("Tabby", breed_11, ignore.case = TRUE) ~ "줄무늬 고양이",
      grepl("Tuxedo", breed_11, ignore.case = TRUE) ~ "턱시도 고양이",
      grepl("Calico", breed_11, ignore.case = TRUE) ~ "캘리코 고양이",
      grepl("Mix|Mixed|/|&", breed_11, ignore.case = TRUE) ~ "혼합 품종",
      grepl("Bat", breed_11, ignore.case = TRUE) ~ "박쥐",
      TRUE ~ "기타"
    ),
age_10_kr = case_when(
  !is.na(age_10) & str_detect(age_10, "year") ~ str_replace(age_10, " year[s]*", "살"),
  !is.na(age_10) & str_detect(age_10, "month") ~ str_replace(age_10, " month[s]*", "개월"),
  !is.na(age_10) & str_detect(age_10, "week") ~ str_replace(age_10, " week[s]*", "주"),
  !is.na(age_10) & str_detect(age_10, "day") ~ str_replace(age_10, " day[s]*", "일"),
  !is.na(age_10) & str_detect(age_10, "-\\d+") ~ paste0(str_replace(str_extract(age_10, "-\\d+"), "-", ""), "살 미만"),
  TRUE ~ "미상"
    ),
subtype_kr = ifelse(is.na(subtype_kr), "미상", subtype_kr)
  )

월별 → 계절로 변환

get_season <- function(month) {
  if (month %in% 3:5) {
    return("봄")
  } else if (month %in% 6:8) {
    return("여름")
  } else if (month %in% 9:11) {
    return("가을")
  } else {
    return("겨울")
  }
}

df <- df %>%
  mutate(
    date = as.Date(substr(outcome_4, 1, 10)),
    month = as.integer(format(date, "%m")),
    season = sapply(month, get_season),
    adopted = ifelse(type_6 == "Adoption", "입양", "비입양")
  )

월별 → 나이 범주로 변환

df <- df %>%
  mutate(
    age_years = case_when(
      str_detect(age_10, "year") ~ as.numeric(str_extract(age_10, "\\d+")),
      str_detect(age_10, "month") ~ as.numeric(str_extract(age_10, "\\d+")) / 12,
      str_detect(age_10, "week") ~ as.numeric(str_extract(age_10, "\\d+")) / 52,
      str_detect(age_10, "day") ~ as.numeric(str_extract(age_10, "\\d+")) / 365,
      TRUE ~ NA_real_
    ),
    age_group = cut(age_years,
                    breaks = c(-Inf, 1, 3, 6, 10, Inf),
                    labels = c("1살 미만", "1~3살", "4~6살", "7~10살", "11살 이상"),
                    right = FALSE)
  )

outcome_4에서 날짜만 추출 연-월 추출후 -01 단위 붙여 → 월단위 날짜로 변환

df <- df %>%
  mutate(
    date = as.Date(substr(outcome_4, 1, 10)),
    month = as.Date(paste0(format(date, "%Y-%m"), "-01"))
  )
  1. 데이터 구조 확인

*다음은 전처리가 완료된 항목이다.

df %>%
  select(
    date, month, season,species_kr, sex_kr, neuter_status_kr,subtype_kr, type_kr, adopted, color_kr, breed_kr,age_10_kr, age_group 
  ) %>%
  head(10)
## # A tibble: 10 × 13
##    date       month      season species_kr sex_kr    neuter_status_kr subtype_kr
##    <date>     <date>     <chr>  <chr>      <chr>     <fct>            <chr>     
##  1 2020-01-01 2020-01-01 겨울   고양이     비중성화 암컷…… 비중성화         미상      
##  2 2020-01-01 2020-01-01 겨울   기타       미상      미상             광견병 위험……
##  3 2020-01-01 2020-01-01 겨울   기타       미상      미상             광견병 위험……
##  4 2020-01-01 2020-01-01 겨울   개         중성화 암컷…… 중성화           미상      
##  5 2020-01-02 2020-01-01 겨울   고양이     중성화 암컷…… 중성화           임시보호  
##  6 2020-01-02 2020-01-01 겨울   고양이     중성화 수컷…… 중성화           임시보호  
##  7 2020-01-02 2020-01-01 겨울   고양이     중성화 암컷…… 중성화           임시보호  
##  8 2020-01-02 2020-01-01 겨울   고양이     중성화 수컷…… 중성화           임시보호  
##  9 2020-01-02 2020-01-01 겨울   고양이     중성화 암컷…… 중성화           임시보호  
## 10 2020-01-02 2020-01-01 겨울   고양이     비중성화 암컷…… 비중성화         노령      
## # ℹ 6 more variables: type_kr <chr>, adopted <chr>, color_kr <chr>,
## #   breed_kr <chr>, age_10_kr <chr>, age_group <fct>
  1. 분석 흐름 요약

분석은 아래 순서와 같이 전개된다.

    1. 기본 현황 분석 2. 보호 환경 실태 3. 연령과 건강의 상관관계 4. 입양 결정 요인 분석 5. 품종별 입양 경향 6. 보호 상태와 입양률 7. 시간 흐름 및 계절 요인 분석 8. 종합 결론 및 정책 제안
  1. 전체 분석 결과 요약
  • [기본 현황 분석] 유기동물은 개, 고양이가 대부분을 차지한다. 색상과 품종은 입양률에 명확한 영향을 미친다. 코로나로 인해 유기동물 수가 급감했으며 이후에는 꾸준히 상승 후 현재는 월별 변동이 존재하나 극단적인 증감 폭은 줄어들었다.

  • [보호 상태 분석] 노령, 병원 치료 등 건강 이상 상태에 놓인 개체는 입양률이 급격히 낮아지는 경향을 보였다.

  • [연령 vs 건강] 생물학적 나이와 보호소에서의 건강 판정은 일치하지 않는 경우가 많다. 2살임에도 노령으로 분류된다. 건강 저하는 입양 기피로 이어졌고, 보호소 체류 장기화 및 비용 증가로 연결되는 구조를 형성했다.

  • [입양 결정 요인 도출] 생후 2개월의 중성화 개체의 입양률은 85%에 달하여 매우 높은 수준을 기록했다. 중성화 여부는 입양에 긍정적인 영향을 미치는 변수로 작용하였다. 이 외에도 밝은 색상, 인기 품종, 어떤 방식으로 구조/보호되었는지 등의 변수 역시 입양률에 유의미한 영향을 미치는 것으로 분석됐다.

  • [품종별 경향 분석] 가장 많이 입양이 되는 생후 2개월에서 국내 단모종 고양이가 많았고 해당 나이대에 입양되는 동물의 대부분은 중성화가된 상태이다. (중성화 여부가 긍정적인 영향을 미친다는 앞선 결과와 일치한다.)

  • [보호 상태와 입양률 관계 분석] 건강 이상 상태에 있는 개체들의 입양률은 거의 0%에 수렴하는 것으로 나타났다. 임시보호 중이거나 제휴기관에 보호 중인 개체는 입양 전환률이 매우 높았다.

  • [시계열 및 계절 요인 분석] 건강 이상 상태를 가진 개체의 비중이 증가하는 시점에는 입양률이 함께 하락하는 현상이 나타났다. 또한, 여름철에는 구조 및 입양이 집중되는 반면, 겨울철에는 전반적으로 저조한 흐름을 보였다.

  1. 결론 요약
  • 중요 변수: 건강 > 연령 > 중성화 > 색상
  • 핵심 연령대: 2개월령 중성화 개체 → 입양률 최고 (85%)
  • 입양 저해 요인: 노령, 질환, 광견병 위험
  • 시간/계절 영향: 여름: 구조/입양 많음, 입양률 ↑, 겨울: 구조/입양 적음, 입양률 ↓

→ 입양은 젊고 건강하며 중성화된 개체, 특히 2개월령(85%)에서 가장 활발하게 이루어지며, 건강 이상 상태는 연령보다 훨씬 강력한 입양 저해 요인이다.

1. 유기동물 기본 분포 현황 분석

유기동물 보호소에 유입되는 개체는 종, 성별, 색상, 나이, 건강 상태 등 다양한 조건을 갖고 있으며, 입양 가능성과 직결되는 핵심 변수로 작용한다. 본 분석은 ’입양 결정 요인 분석’이라는 최종 목표에 앞서, 먼저 보호소에 유입되는 유기동물의 기초적인 특성과 분포 현황을 파악하는 것으로 시작한다.

특히, ‘어떤 동물이 보호소에 가장 많이 들어오는가’, ’어떤 특징이 빈번한가’에 대한 탐색을 통해 분석의 출발점을 설정하며, 이는 이후의 건강·연령·입양률 분석과의 연결고리를 형성한다.

1-1. 유기동물 종류

보호소에 유입되는 동물의 종 분포를 분석하여, 입양 결정의 기본 단위가 되는 개체 유형을 파악한다.

  1. 개의 개체 수가 가장 높게 나타났으며, 반려견 유기가 가장 빈번하게 발생하는 것으로 보인다.
  2. 개 다음으로는 고양이가 두 번째로 많은 유기동물이며, 대중적으로 많이 기르는 동물이라는 점에서 유기 사례도 많은 편이다.
  3. 개와 고양이의 유기동물 수는 전체의 90% 이상을 차지할 정도로 압도적이다.
  4. 기타 동물도 일부 존재하나, 상대적으로 매우 적은 편이며 비중이 거의 없는 수준이다.
  5. 가축은 유기동물 분류에서 보호소 통계에 거의 포함되지 않으며, 실질적으로 미비하게 확인된다.
ggplot(df %>% filter(!is.na(species_kr)), aes(x = species_kr)) +
  geom_bar(fill = "#b3eac7") +
  labs(title = "유기동물의 종류", x = "종", y = "개체수") +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold", margin = margin(b = 10)),
    axis.text = element_text(size = 10),
    axis.text.x = element_text(size = 10, margin = margin(b = 0, t = 6)),
    axis.text.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(t = 20)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-2. 유기동물 성별 및 중성화 상태 분포

  1. 중성화된 수컷과 암컷이 가장 많은 비중을 차지하며, 각각 2만 건 내외로 높은 개체 수를 기록하고 있다.
  2. 비중성화된 수컷과 암컷은 유사한 수준으로 나타나며, 상대적으로 낮은 개체 수를 보인다.
ggplot(df %>% filter(sex_kr != "미상"), aes(x = factor(sex_kr))) + 
  geom_bar(fill = "#b3eac7") +
  labs(
    title = "유기동물의 성별", 
    x = "성별", y = "개체수"  # 오탈자 "개채수" → "개체수"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    axis.text = element_text(size = 10),
    axis.text.x = element_text(size = 10, margin = margin(b = 14, t = 6)),
    axis.text.y = element_text(margin = margin(r = 10)),
    axis.title.x = element_text(margin = margin(r = 20)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-3-1. 유기동물 색상 분포

  1. 검정색과 하양색 유기동물이 가장 많으며, 단색 계열이 유기동물의 대다수를 차지한다.
  2. 갈색, 회색, 주황, 탄색 등의 색상은 그 뒤를 잇는 주요 색상군이다.
  3. 캘리코, 삼색, 줄무늬 등은 유전적으로 한정되거나 희귀한 색상으로, 전체 유기동물 중 비중이 낮다.
df$color_kr <- as.factor(df$color_kr)

color_counts <- table(df$color_kr[df$color_kr != "기타"])
top_10_colors <- head(sort(color_counts, decreasing = TRUE), 10)

color_df <- as.data.frame(top_10_colors)
colnames(color_df) <- c("color_kr", "count")
color_df$color_kr <- factor(color_df$color_kr, levels = rev(color_df$color_kr))

ggplot(color_df, aes(x = count, y = color_kr)) +
  geom_col(fill = "#89deb0",width = 0.7) +
  labs(
    title = "유기동물 색상 분포", 
    subtitle = "상위 10개의 색상", 
    x = "개체 수", y = "색상"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 10),
    axis.text.y = element_text(size = 10),
    axis.title.x = element_text(margin = margin(t = 15)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-3-2. 유기동물에 대한 입양 및 비입양 분포 분석

  1. 상단에 위치한 하양, 검정, 갈색 등의 색상은 전체 유기동물 수가 많기 때문에, 입양된 개체와 비입양된 개체 수 모두 많은 편이다.
  2. 줄무늬, 삼색, 캘리코 등은 상대적으로 개체 수가 적은 색상이다.
  3. 검정색처럼 일부 색상은 비입양 수가 입양 수보다 훨씬 많아, 구조되는 개체 수는 많지만 입양까지 이어지는 비율은 높지 않다. 반면, 하양이나 크림색 등 밝은색 계열은 입양 수가 비입양 수와 비슷하거나 더 많은 경우도 나타난다.
  4. 캘리코는 개체 수는 적지만 입양률이 높은 특징을 보인다.
top_colors <- df %>%
  filter(color_kr != "기타") %>%
  count(color_kr) %>%
  top_n(10, n) %>%
  pull(color_kr)

df_color_adopt <- df %>%
  filter(color_kr %in% top_colors, !is.na(adopted)) %>%
  group_by(color_kr, adopted) %>%
  summarise(count = n(), .groups = "drop")

df_color_adopt$color_kr <- factor(
  df_color_adopt$color_kr,
  levels = df_color_adopt %>%
    group_by(color_kr) %>%
    summarise(total = sum(count)) %>%
    arrange(desc(total)) %>%
    pull(color_kr) %>%
    rev()
)

ggplot(df_color_adopt, aes(x = count, y = color_kr, fill = adopted)) +
  geom_col(width = 0.7) +
  scale_fill_manual(values = c("입양" = "#89deb0", "비입양" = "#528F70")) +
  labs(
    title = "색상별 입양/비입양 분포",
    subtitle = "상위 10개의 색상",
    x = "개체 수", y = "색상", fill = "입양 여부"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 11, margin = margin(b = 6, t = 6)),
    axis.text.y = element_text(size = 10),
    axis.title.x = element_text(margin = margin(t = 12)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-3-3. 종합 시사점

  1. 유기 개체 수가 많은 색상은 대체로 흔한 털 색인 경우가 많다.
  2. 색상은 입양률에 명확한 영향을 미치며, 선호도의 차이가 존재한다.
  3. 유기 개체 수가 많다고 해서 입양이 잘 되는 것은 아니며, 이는 유기와 입양이 서로 다른 요인에 의해 결정됨을 의미한다.
  4. 색상은 입양 선호도에 영향을 주지만, 유기의 직접적인 원인이라고 단정할 수 있는 증거는 부족하다.

1-4-1. 유기동물 품종 분포

  1. 유기동물 중 국내단모종이 가장 높은 빈도를 보이며, 압도적으로 많이 구조된 품종이다.
  2. 래브라도 리트리버, 저먼 셰퍼드, 핏불 등 중형에서 대형견에 해당하는 품종들이 다수 포함되어 있다.
  3. 고양이보다 개 품종이 상위권에 집중되어 있으며, 보호소의 구조 사례에서 개의 유기 비중이 높다는 점을 다시 한번 확인할 수 있다.
df$breed_kr <- as.factor(df$breed_kr)

breed_counts <- table(df$breed_kr[df$breed_kr != "기타"])
top_10_breeds <- head(sort(breed_counts, decreasing = TRUE), 10)

breed_df <- as.data.frame(top_10_breeds)
colnames(breed_df) <- c("breed_kr", "count")
breed_df$breed_kr <- factor(breed_df$breed_kr, levels = rev(breed_df$breed_kr))

ggplot(breed_df, aes(x = count, y = breed_kr)) +
  geom_col(fill = "#b3eac7", width = 0.7) +
  labs(
    title = "유기동물 품종 분포", 
    subtitle = "상위 10개 품종 기준", 
    x = "개체 수", y = "품종"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 11, margin = margin(b = 6, t = 6)),
    axis.text.y = element_text(size = 9),
    axis.title.x = element_text(margin = margin(t = 15)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-4-2. 품종별 입양/비입양 분포

  1. 국내단모종은 유기 개체 수가 많지만, 비입양 개체도 많아 입양 전환률이 낮은 편이다.
  2. 래브라도 리트리버는 유기 사례가 많음에도 불구하고 입양 전환 비율이 높은 편으로 나타나며, 이는 인기 품종이라는 점이 영향을 준 결과이다.
  3. 특정 품종은 유기 이후 입양까지 이어지기 어려운 반면, 일부 품종은 상대적으로 선호도가 높아 입양이 활발하게 이루어지는 경향을 보인다. 품종은 입양의 성패에 영향을 주는 요인 중 하나로 간주할 수 있다.
top_breeds <- df %>%
  filter(breed_kr != "기타") %>%
  count(breed_kr) %>%
  top_n(10, n) %>%
  pull(breed_kr)

df_breed_adopt <- df %>%
  filter(breed_kr %in% top_breeds, !is.na(adopted)) %>%
  group_by(breed_kr, adopted) %>%
  summarise(count = n(), .groups = "drop")

df_breed_adopt$breed_kr <- factor(
  df_breed_adopt$breed_kr,
  levels = df_breed_adopt %>%
    group_by(breed_kr) %>%
    summarise(total = sum(count)) %>%
    arrange(desc(total)) %>%
    pull(breed_kr) %>%
    rev()
)

ggplot(df_breed_adopt, aes(x = count, y = breed_kr, fill = adopted)) +
  geom_col(width = 0.7) +
  scale_fill_manual(values = c("입양" = "#89deb0", "비입양" = "#528F70")) +
  labs(
    title = "품종별 입양/비입양 분포",
    subtitle = "상위 10개 품종 기준",
    x = "개체 수", y = "품종", fill = "입양 여부"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 11, margin = margin(b = 6, t = 6)),
    axis.text.y = element_text(size = 10),
    axis.title.x = element_text(margin = margin(t = 12)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-4-3. 종합 시사점

  1. 개와 고양이가 전체 유기동물의 대부분을 차지하고 있으며, 그중 개가 가장 많은 비중을 차지하고 있다.
  2. 밝은색이나 희귀한 색상의 동물은 입양률이 높고, 검정색이나 흔한 색상은 입양 전환율이 낮은 편이다.
  3. 국내단모종처럼 흔한 품종은 유기 비율이 높으나, 입양까지 이어지는 비율은 낮다. 래브라도 같은 인기 품종은 입양률이 높은 편이다.
  4. 중성화된 동물이 대부분을 차지하며, 성별 자체는 입양에 큰 영향을 주지 않는 것으로 보인다.
  5. 2020년 코로나 확산 이후 일시적으로 유기 수가 급감했으며, 이후에는 점차 회복되다 안정화되었다
  6. 유기와 입양은 각각 다른 요인에 의해 결정되며, 색상이나 품종 하나만으로 입양 가능성을 판단하기는 어렵다.

1-5. 월별 신규 유기동물 발생 추이

  1. 코로나 첫해인 2020년 초반에는 유기동물 수가 급감하였으며, 보호소 접근의 어려움과 시민 이동의 제약으로 인해 구조 및 유기 자체가 감소한 것으로 해석된다.
  2. 2020년 하반기부터는 유기동물 수가 점차 회복세를 보였고, 2021년 상반기에는 최고점에 도달하였다.
  3. 2021년 6월~9월은 피크를 기록한 이후, 전체적으로 서서히 하향 안정화되는 흐름을 보였다.
  4. 2021년 중반부터 말까지 정점을 형성하였으며, 이후로는 고점의 수준이 점차 낮아지는 경향을 나타내고 있다.
  5. 2022년~2024은 전체적으로 평균선 부근에서 진동하며, 월별 변동은 존재하나 극단적인 증감 폭은 줄어든 상태이다.
df$date <- as.Date(substr(df$outcome_4, 1, 10))

df$month <- as.Date(paste0(format(df$date, "%Y-%m"), "-01"))  
monthly_counts <- aggregate(x = list(n = rep(1, nrow(df))), 
                            by = list(month = df$month), 
                            FUN = sum)

mean_count <- mean(monthly_counts$n, na.rm = TRUE)

ggplot(monthly_counts, aes(x = month, y = n)) +
  geom_hline(yintercept = mean_count, linetype = "dashed", color = "#ffb266", linewidth = 0.6) +
  geom_line(color = "#5ed399", linewidth = 1) +
  geom_point(color = "#5ed399", size = 1.6) +
  labs(
    title = "월별 유기동물 발생 건수", subtitle = "(2020-01 ~ 2025-04)",
    x = "월",
    y = "유기동물 수"
  ) +
  scale_x_date(
    date_breaks = "3 months", date_labels = "%Y-%m", limits = c(as.Date("2020-01-01"), as.Date("2025-05-01")) 
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

1-6. 통합 결론

  1. 코로나로 2020년 초 유기동물 수 급감을 초래했으며, 이후 2021년 중반부터 피크를 기록했다. 2021년 하반기 이후 유기동물 수는 서서히 안정화되었다.
  2. 개와 고양이는 유기동물 수에서 대부분을 차지했다. 특히, 검정색 유기동물은 유기 발생이 많지만 입양률이 낮은 경향이 있었다.
  3. 품종별 유기동물 수와 입양률은 매우 상이하며, 인기 품종은 유기 빈도와 입양 전환율이 높았다. 반면 국내단모종은 유기 수가 많지만 입양이 어려운 품종으로 나타났다.

2. 유기동물 보호환경의 실태 파악

2-1. 보호소 운영 방식과 건강 이상 상태

  1. 제휴기관 전송과 임시보호가 상위 두 항목을 차지하고 있으며, 구조 및 보호 방식이 외부 기관에 의존하고 있음을 나타낸다.
  2. 광견병 위험, 고통, 병원 치료 중 등의 항목이 높은 비중을 차지하고 있어, 의료적 처치가 필요한 상태의 유기동물이 상당한 수준임을 보여준다.
  3. 노령 유기동물은 나이가 많아 입양 가능성이 낮고, 의료비 부담이 큰 개체군으로 분류되며, 그 비율이 높은 편이다.
  4. 현장 구조와 타 지역 전송은 상대적으로 빈도가 낮으며, 보호소 운영에 있어 보조적인 수단에 해당하는 수준이다.
subtype_counts <- table(df$subtype_kr)
top_10_subtypes <- head(sort(subtype_counts[names(subtype_counts) != "미상"], decreasing = TRUE), 10)

top_10_df <- as.data.frame(top_10_subtypes)
colnames(top_10_df) <- c("subtype", "count")

top_10_df$subtype <- factor(top_10_df$subtype, levels = top_10_df$subtype)

ggplot(top_10_df, aes(x = subtype, y = count)) +
  geom_col(fill = "#89deb0") +
  labs(
    title = "유기동물 상태", 
    subtitle = "상위 10개 기준", 
    x = "상태", y = "유기동물 수"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 8, margin = margin(b = 10, t = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

임시 보호를 제외한 전반적인 유기동물의 상태는 광견병 위험, 노령, 고통 등과 같이 건강에 문제가 있는 개체들이 상당 부분을 차지하고 있는 것으로 나타난다. → 그렇다면 해당 유기동물들은 어떤 연령대에 속할까? 앞서 전체 유기동물의 연령 분포에 대해 분석한 결과를 바탕으로 고찰해볼 수 있다.

2-2. 구조되는 유기동물의 연령 분포

  1. 1살 미만의 개체가 전체에서 가장 큰 비중을 차지하고 있으며, 유기동물 상당수가 생후 수개월 이내에 구조되고 있다. 보호소에 유입되는 동물들이 출생 직후 혹은 입양 실패로 인해 빠르게 버려지고 있음을 의미한다.
  2. 1살~3살의 연령층도 상당한 비율을 차지하고 있어, 성숙기 동물의 유기 가능성이 매우 높은 것으로 나타난다.
  3. 3살 이후부터는 유기 건수가 급격히 감소하는 경향을 보인다.
df_age <- df %>%
  filter(!is.na(age_group)) %>%
  count(age_group)

ggplot(df_age, aes(x = "", y = n, fill = age_group)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y") +
  labs(
    title = "나이대별 유기동물 구성 비율",
    fill = "나이대"
  ) + scale_fill_manual(values = c(
  "1살 미만"   = "#265B3E",  # 가장 진함
  "1~3살"     = "#458160",
  "4~6살"     = "#6FA583",
  "7~10살"    = "#ABD3B6",
  "11살 이상" = "#dbf4e0"   # 가장 연함
)) +


  theme_void() +
  theme(
    plot.margin = margin(t = 10, r = 10, b = 0, l = 10),
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold", margin = margin(b = 6)),
    legend.title = element_text(size = 11),
    legend.text = element_text(size = 10)
  )

2-3. 통합 결론

  1. 보호소 운영은 외부 기관과 협력하는 구조이다.
  2. 유기동물 중 상당수가 의료적 처치가 필요한 상태이며, 노령 동물의 입양 촉진이 필요하다.
  3. 유기동물 비율은 1살 미만의 동물이 대부분을 차지하고 있으며, 3살 이후로는 급격히 감소한다.

3. 연령과 건강 문제의 상관관계

다음은 대부분의 비율을 차지하는 유기동물 연령대인 1개월부터 5살까지의 건강 문제와 상관관계를 도출한다. 이 연령대의 동물들은 사회성이 좋고 입양 가능성도 높지만, 유기되는 비율도 높은 중요한 대상이기에 건강에 대한 이상이 있는지의 여부를 파악하는 것이 중요하다.

3-1. 나이별 주요 건강 위험 분석

  1. 2살, 1살, 3살 등 비교적 젊은 나이대에서도 노령으로 판정된 사례가 존재한다. 노령 판정 기준이 상대적으로 낮거나, 건강 상태의 조기 저하를 겪는 개체가 많다는 구조적 특성을 반영하는 것이다.
  2. 광견병 판정은 2살에서 가장 높은 비중을 보이며, 1살과 6개월 등에서도 다수 확인된다. 전형적인 성체 구간에서 광견병 판정 빈도가 높다는 의미이며, 외부에서 구조된 유기동물 중 성체의 비중이 높고, 예방 접종을 받지 않았거나 야외 노출 이력이 많았음을 나타낸다.
  3. 고통 상태로 분류된 개체는 다양한 나이대에서 간헐적으로 발견된다.
age_levels <- c(
  "1개월", "2개월", "3개월", "4개월", "5개월",
  "1살", "2살", "3살", "4살", "5살"
)
target_subtypes_kr <- c("고통", "노령", "병원 치료 중", "광견병 위험")

df_focus <- df %>%
  filter(!is.na(age_10_kr), subtype_kr %in% target_subtypes_kr) %>%
  count(age_10_kr, subtype_kr)

df_focus$age_10_kr <- factor(df_focus$age_10_kr, levels = age_levels)

df_filtered <- df_focus %>%
  filter(age_10_kr %in% age_levels)

ggplot(df_filtered, aes(x = age_10_kr, y = subtype_kr, size = n)) +
  geom_point(alpha = 0.75, color = "#00bb6c") +
  scale_size_continuous(name = "빈도 수") +
  labs(
    title = "주요 건강 상태와 나이 분포", subtitle = "주요 유기동물 연령(1개월~5살)",
    x = "나이", y = "건강 상태"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 10, margin = margin(b = 10, t = 6)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

3-2. 구조량 상위 연령의 건강상태 평가

  1. 전체 유기동물 중 약 70~80%가 3세 미만으로, 사회적·생물학적으로 입양 적령기에 해당하며 입양 선호도가 높은 연령층이다. 표면적으로는 입양 가능성이 매우 높은 구간이라 할 수 있다.
  2. 그러나 이 주요 연령대에서 건강 이상이 집중되어 나타나며, 실제로는 입양이 어려운 상태인 경우가 많다. 3살 미만임에도 불구하고 일부는 노령으로 분류되고, 심각한 건강 이상을 동반한 개체들이 다수 포함되어 있다.
  3. 특히 2살은 젊은 나이임에도 불구하고 건강에 문제가 있는 개체가 가장 많이 분포된 구간으로, 입양 기피 현상이 심화되고 있다. 보호소 체류가 장기화되고, 결과적으로 의료 부담이 증가하는 악순환이 집중되는 나이대이다.

→ 입양이 가장 활발해야 할 연령대에서 오히려 건강 문제가 집중되고 있다면, 실제 입양 양상은 어떻게 나타나는가?

4. 입양 여부 결정 요인 분석

4-1. 연령에 따른 입양 선호도

  1. 입양은 생후 2개월에서 가장 활발하게 이루어지고 입양 성공률이 가장 높은 것으로 나타난다.
  2. 2살은 입양 여부를 가르는 분기점이 되는 연령대로, 구조 건수가 많음에도 불구하고 병력 등의 문제로 입양 전환에 어려움이 따른다. 앞선 분석에서도 2살에서 건강 문제가 집중되는 경향이 확인된 바 있다.
  3. 3살 이상에서는 구조 사례 자체가 적고, 입양률도 낮은 편이다. 특히 노령 개체의 경우 질환 동반 비율이 높아, 입양 전 치료와 지속적인 관리가 요구되는 구간이다.
  4. 1살~3살은 전체 구조의 핵심 연령층이나, 입양보다 비입양이 더 높은 비중을 차지하고 있다.
age_levels <- c("1개월", "2개월", "3개월", "4개월", "5개월",
                "1살", "2살", "3살", "4살", "5살")

df_age <- df %>%
  filter(!is.na(age_10_kr), !is.na(type_kr)) %>%
  mutate(adopted = ifelse(type_kr == "입양", "입양", "비입양"))

age_count <- df_age %>%
  count(age_10_kr, sort = TRUE)

top_ages <- head(age_count$age_10_kr, 10)

df_age_top10 <- df_age %>%
  filter(age_10_kr %in% top_ages) %>%
  group_by(adopted, age_10_kr) %>%
  summarise(count = n(), .groups = "drop") %>%
  mutate(age_10_kr = factor(age_10_kr, levels = age_levels))

ggplot(df_age_top10, aes(x = age_10_kr, y = adopted, fill = count)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "#dbf4e0", high = "#006644") +
  labs(
    title = "나이별 입양 여부", subtitle = "주요 유기동물 연령(1개월~5살)",
    x = "나이", y = "입양 여부",fill = "개체 수"
  ) +
  theme_minimal() +
  theme(
    axis.title.x = element_text(margin = margin(t = 12)),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 10, margin = margin(b = 10, t = 6)),
    text = element_text(family = "Noto Sans KR"),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

따라서 건강 상태와 연령, 특히 노령 여부는 입양 여부에 중요한 영향을 미치는 요인이다. 특히 2년령은 건강상의 문제로 유기되는 개체가 많고, 입양률은 상대적으로 낮은 특징을 보인다.

4-2. 중성화 상태와 입양의 상관성

  1. 생후 2개월 시점에서는 대부분의 개체가 중성화된 상태이다.
  2. 생리적으로 중성화가 어려운 연령인 1개월은 비중성화 개체의 비율이 가장 높다.
  3. 1살~5살은 중성화 비율이 비교적 안정적으로 유지되며, 나이가 많아질수록 중성화율이 점차 높아지는 경향을 보인다.
  4. 전반적으로 연령이 높을수록 중성화된 개체의 비율도 높아지는 추세이다
age_levels <- c("1개월", "2개월", "3개월", "4개월", "5개월",
                "1살", "2살", "3살", "4살", "5살")

df_neuter <- df %>%
  filter(
    !is.na(neuter_status_kr),
    neuter_status_kr != "미상",
    !is.na(age_10_kr),
    age_10_kr %in% age_levels
  )

df_top_ages <- df_neuter %>%
  mutate(
    age_10_kr = factor(age_10_kr, levels = age_levels),
    neuter_status_kr = factor(neuter_status_kr, levels = c("중성화", "비중성화"))
  )

ggplot(df_top_ages, aes(x = age_10_kr, fill = neuter_status_kr)) +
  geom_bar(position = "fill") +
  scale_y_continuous(labels = scales::percent) +
  scale_fill_manual(
    values = c("중성화" = "#C9E7D1", "비중성화" = "#528F70"),
    limits = c("중성화", "비중성화")
  ) +
  labs(
    title = "유기동물의 중성화 여부 비율", subtitle = "주요 유기동물 연령(1개월~5살)",
    x = "나이", y = "비율", fill = "중성화 여부"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 10, margin = margin(b = 6, t = 6)),
    axis.title.x = element_text(margin = margin(t = 12)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

중성화 여부는 입양 선호도에 영향을 미치는 요인으로 나타난다. 또한 건강 이상 상태 역시 입양을 어렵게 만드는 주요 요인이며, 보호소 체류 기간의 장기화와 의료비 등의 비용 증가로 이어지는 경향이 있다. 특히 중성화 여부가 건강 상태와도 관련이 있을 수 있기 때문에, 생후 2개월령 개체를 중심으로 중성화율과 입양률의 동시 분포를 확인하였다.

4-3. 종합 결론

  1. 생후 2개월 유기동물은 입양 선호도가 가장 높고, 2살 이상은 건강 문제로 입양에 어려움이 있다.
  2. 중성화 여부는 입양 여부에 큰 영향을 미친다. 중성화된 동물은 입양 가능성이 높아지며, 연령이 높을수록 중성화된 개체 비율도 증가한다.
  3. 건강 상태와 연령은 입양을 결정짓는 중요한 요소로, 건강 이상 상태와 나이가 많을수록 입양이 어려워지는 경향이 있다.

→ 입양이 가장 활발한 생후 2개월은 어떤 특징이 있는가?

5. 품종별 입양 경향

5-1. 2개월령 주요 품종 입양 분석

  1. 국내단모종이 가장 많이 입양되는 품종이다.
  2. 상위 5개 품종 모두에서 입양 수가 비입양 수보다 높은 경향을 보이며, 생후 2개월에서 전반적인 입양 선호도가 높다는 점을 다시 한 번 확인시켜준다.
  3. 다만 품종별로 입양 선호도에는 일정한 편차가 존재한다.
df_2mo <- df %>%
  filter(age_10_kr == "2개월") %>%
  filter(!is.na(breed_kr), !is.na(type_kr)) %>%
  mutate(
    adopted = ifelse(type_kr == "입양", "입양", "비입양")
  )

top_breeds <- df_2mo %>%
  filter(breed_kr != "기타") %>% 
  count(breed_kr, sort = TRUE) %>%
  top_n(5, n) %>%
  pull(breed_kr)

df_top_breeds <- df_2mo %>%
  filter(breed_kr %in% top_breeds) %>%
  mutate(
    breed_kr = fct_infreq(breed_kr),
    adopted = factor(adopted, levels = c("입양", "비입양"))
  )

ggplot(data = df_top_breeds) +
  geom_bar(aes(x = breed_kr, fill = adopted), position = "dodge") +
  labs(
    title = "2개월령 유기동물: 품종별 입양 여부 분포",
    x = "품종", y = "개체 수", fill = "입양 여부"
  ) +
  scale_fill_manual(values = c(
    "입양" = "#C9E7D1", 
    "비입양" = "#528F70"
  )) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold", margin = margin(b = 10)),   
    axis.text.x = element_text(size = 9, margin = margin(b = 10, t = 6)),
    axis.text.y = element_text(size = 10, margin = margin(r = 6)),       
    axis.title.x = element_text(margin = margin(t = 6)),              
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

5-2. 2개월령 주요 품종별 중성화 상태와 입양 여부

  1. 입양된 개체는 대부분 중성화된 상태로 나타났으며, 특히 국내단모종을 포함한 상위 품종 모두에서 동일한 경향이 확인된다.
  2. 반면 비입양 개체 중에서는 비중성화 상태의 비율이 높게 나타났으며, 중성화 여부가 입양 결정에 영향을 미칠 수 있는 요소임을 시사한다.
  3. 품종별로 다소의 편차는 존재하지만, 중성화 여부가 입양 선호에 긍정적인 영향을 주는 경향은 전반적으로 공통적이다.
  4. 생후 2개월에서는 중성화가 이미 이루어진 개체의 입양 가능성이 높다.
ggplot(df_top_breeds, aes(x = breed_kr, fill = neuter_status_kr)) +
  geom_bar(position = "dodge") +
  facet_wrap(~adopted, ncol = 1) +
  labs(
    title = "2개월령 유기동물: 상위 5개 품종별 입양 여부와 중성화 상태",
    x = "품종", y = "개체 수", fill = "중성화 여부"
  ) +
  scale_fill_manual(values = c(
    "중성화" = "#C9E7D1", 
    "비중성화" = "#528F70"
  )) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold", margin = margin(b = 10)),   
    axis.text.x = element_text(size = 9, margin = margin(b = 10, t = 6)),
    axis.text.y = element_text(size = 10, margin = margin(r = 6)),       
    axis.title.x = element_text(margin = margin(t = 6)),              
    axis.title.y = element_text(margin = margin(r = 12)),
    strip.text = element_text(size = 11, face = "bold"),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

5-3. 통합 분석

  1. 생후 2개월 유기동물 중 국내 단모종 고양이는 가장 많은 입양 건수를 기록하며, 전체 품종 중 입양 선호도가 가장 높은 품종으로 나타난다.
  2. 상위 5개 주요 품종 모두 입양 수가 비입양 수를 상회하는 경향을 보이며, 품종에 관계없이 전반적으로 비입양 보다 입양이 더 선호된다.
  3. 입양된 개체는 대부분 중성화된 상태로 구성되어 있는 반면, 비입양 개체는 비중성화 비율이 상대적으로 높아 중성화 여부가 입양 성사에 유의미한 영향을 주는 변수이다.
  4. 일부 품종에서는 중성화 상태임에도 불구하고 입양되지 않은 사례도 존재하여, 중성화 외에도 품종 선호나 외형적 요인이 입양 여부에 복합적으로 작용하고 있음을 시사한다.

6. 보호 상태별 입양 경향

6-1. 보호 상태별 입양 경향 분석

  1. 입양률이 높은 상태는 임시보호, 제휴기관 보호, 보호소 내 보호 등으로 분류된 개체들이 대부분이다.
  2. 입양률이 낮은 상태는 노령, 고통, 광견병 위험, 병원 치료 중인 개체들이며, 모두 건강에 이상이 있는 경우이다. 입양자 입장에서 건강 부담, 치료비 부담, 생존 가능성에 대한 우려로 인해 기피 대상이 되는 경향이 강하다.
df_subtype_adopt <- df %>%
  filter(type_kr == "입양", !is.na(subtype_kr))

top_subtypes <- df_subtype_adopt %>%
  count(subtype_kr) %>%
  top_n(4, n) %>%
  pull(subtype_kr)

target_subtypes <- c("노령", "고통", "광견병 위험", "병원 치료 중")
include_subtypes <- union(top_subtypes, target_subtypes)

df_top <- df %>%
  filter(subtype_kr %in% include_subtypes, subtype_kr != "미상", !is.na(adopted)) %>%
  group_by(subtype_kr) %>%
  summarise(
    total = n(),
    adopted = sum(adopted == "입양"),
    adoption_rate = adopted / total,
    .groups = "drop"
  ) %>%
  arrange(desc(adoption_rate)) %>%
  mutate(subtype_kr = fct_inorder(subtype_kr))

ggplot(df_top, aes(x = adoption_rate, y = subtype_kr)) +
  geom_segment(aes(x = 0, xend = adoption_rate, y = subtype_kr, yend = subtype_kr),
               color = "#89deb0", linewidth = 2) +
  geom_point(color = "#006644", size = 4) +
  scale_x_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(
    title = "유기동물 상태",
    subtitle = "입양된 개체 기반, 건강 이상 상태 포함",
    x = "입양률", y = "보호 상태"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 10, margin = margin(b = 10, t = 6)),
    axis.text.y = element_text(size = 10, margin = margin(r = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    axis.title.x = element_text(margin = margin(t = 6)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

보호 상태에 따라 입양 전환 가능성은 극명하게 갈리며, 실제로 임시보호나 외부 제휴시설을 제외하면 대부분의 보호 유형에서 입양률은 사실상 0%에 수렴하는 수준이다. 이에 따라, 입양이 어려운 보호 상태에 놓인 개체들이 어떤 특성을 가지는지 그 원인을 파악할 필요가 있다. 즉, 입양 전환이 거의 이루어지지 않는 개체들은 어떤 조건에 처해 있는가를 중심으로 분석을 진행하고자 한다.

6-2. 입양률이 낮은 보호 상태의 연령대 구성

  1. 전체적으로 1살~3살의 연령대가 주요 비중을 차지하고 있다.
  2. 노령으로 분류된 개체들 중에서도 1살~3살 비중이 높으며, 노령 판정 기준이 낮거나 실제로 건강이 빠르게 저하된 젊은 개체가 많다는 점을 시사한다. 입양률이 낮은 상태라고 하더라도, 실제로는 젊은 개체에 집중되어 있는 경우가 많다. → 즉, 입양이 어려운 이유는 나이가 많아서가 아니라 건강 문제에 기인한 구조임을 의미한다.
  3. 1살 미만의 연령대는 상대적으로 낮은 분포를 보이며, 심각한 질환의 진단 빈도가 낮고 보호소 유입 당시 비교적 건강한 상태였음을 나타낸다.
  4. 6살~10살, 그리고 10살 이상 나이대는 일부 보호 상태에서만 나타나며, 특히 노령 분류 상태에서만 고령 개체의 비율이 눈에 띄게 높다. 그 외의 대부분 보호 상태에서는 실제 노령보다는 성체기에 해당하는 개체에 집중되는 양상을 보인다.
target_subtypes_kr <- c("고통", "노령", "병원 치료 중", "광견병 위험")

df_grouped <- df %>%
  filter(!is.na(age_group), subtype_kr %in% target_subtypes_kr) %>%
  group_by(subtype_kr, age_group) %>%
  summarise(count = n(), .groups = "drop") %>%
  mutate(
    age_group = factor(age_group, levels = c("1살 미만", "1~3살", "4~6살", "7~10살", "11살 이상")),
    age_code = as.numeric(age_group)
  )

ggplot(df_grouped, aes(x = age_group, y = count, fill = age_code)) +
  geom_col() +
  facet_wrap(~ subtype_kr, scales = "free_y") +
  labs(
    title = "보호 상태별 연령대 구성",
    subtitle = "입양이 어려운 상태에 속한 개체들의 연령대 분포",
    x = "연령대", y = "유기동물 수"
  ) +
  scale_fill_gradientn(colors = c("#C9E7D1", "#006644")) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 9, margin = margin(b = 6, t = 6)),
    axis.text.y = element_text(size = 9, margin = margin(l = 10, r = 6)),
    axis.title.x = element_text(margin = margin(t = 8)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4),
    legend.position = "none"
  )

그렇다면 1세에서 3세 사이의 연령대에 해당하는 개체들이 실제로 입양되었는가에 대한 검토가 필요하다. 만약 이 연령대에서조차 입양 전환률이 낮다면, 이는 나이 때문이 아니라 다른 결정적 요인, 즉 건강 상태 때문일 가능성이 높다. 실제로도 해당 연령대 개체들 중 상당수가 노령으로 분류되거나 질병·부상 등의 이유로 입양이 이루어지지 않고 있으며, 이는 건강 문제가 입양 성패를 좌우하는 주요 변수임을 뒷받침한다.

그렇다면 이 연령대 개체들이 실제로 입양되었는가? -> 나이 때문이 아니면, 정말 건강 때문인가?

6-3. 입양 실패 개체의 연령대-건강 상태 교차 분석

  1. 노령 상태로 분류된 1살~3살의 비입양 개체 수가 압도적으로 많으며, 노령이라는 판정이 실제 생물학적 노화보다는 건강 이상 상태를 기준으로 판단되었음을 나타낸다.
  2. 고통 상태로 분류된 개체들 역시 1살 미만 및 1살~3살에 집중되어 있으며, 대부분 입양으로 이어지지 않는다.
  3. 병원 치료 중인 상태와 광견병 위험 상태 역시 유사한 연령 분포를 보이고 개체들은 연령에 관계없이 입양률이 극히 낮다.
  4. 10살 이상의 고령 개체들 가운데 비입양 수는 상대적으로 적은 편이다. 10살 이상은 유기동물 수 자체가 많지 않는 것도 이에 영향을 미친다.
df_3way <- df %>%
  filter(
    subtype_kr %in% c("고통", "노령", "병원 치료 중", "광견병 위험"),
    !is.na(age_group),
    !is.na(adopted)
  ) %>%
  group_by(age_group, subtype_kr, adopted) %>%
  summarise(count = n(), .groups = "drop")

df_3way %>%
  filter(adopted == "비입양") %>%
  ggplot(aes(x = age_group, y = subtype_kr, fill = count)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "#dbf4e0", high = "#006644") +
  labs(
    title = "입양되지 못한 개체의 연령대 분포",
    subtitle = "보호 상태에 따른 연령별 입양 실패 집중도",
    x = "연령대", y = "보호 상태", fill = "개체 수"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 11, margin = margin(b = 6, t = 6)),
    axis.text.y = element_text(size = 10),
    axis.title.x = element_text(margin = margin(t = 12)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

6-4. 종합 분석

  1. 입양 성사 여부는 건강 상태에 의해 결정되는 경향이 뚜렷하다.
  2. 입양률이 낮은 개체들은 주로 젊은 연령대에 집중되어 있으며, 특히 1살~3살 사이의 개체가 비입양의 중심을 이루고 있다. 다수는 생물학적 고령이 아님에도 불구하고 건강 저하로 인해 노령으로 판정되어 입양이 어려운 상태에 처해 있다. → 즉, 입양이 어려운 원인은 나이가 많아서가 아니라 건강 문제라는 구조가 명확하게 드러난다.
  3. 10살 이상의 고령 개체는 구조 사례 자체가 적고, 입양도 거의 이루어지지 않고 있다.
  4. 입양률이 0%에 가까운 집단은 나이가 적지만 심각한 건강 이상을 지닌 개체들로 구성되어 있다.

7. 시간 흐름에 따른 입양 변화와 건강 요인 동태 분석

7-1-1.입양과 비입양 수의 월별 흐름 분석

  1. 그래프 초반인 2020년에는 입양 수와 비입양 수의 차이가 크지 않았으나, 2021년 중반 이후부터는 입양 수가 뚜렷하게 우세해지는 구간이 나타난다. 입양의 절대량이 비입양 수를 지속적으로 상회하는 구조가 장기적으로 자리 잡았음을 의미한다.
  2. 비입양 수는 상대적으로 넓은 폭의 진동을 보이며, 2021년~2023년은 일부 시점에서 비입양 급증 현상이 관찰된다.
  3. 입양 수는 다소 등락이 있더라도 전반적으로 상승세를 유지하며, 2023년~2024년은 입양 수가 최고치를 기록한 달이 여러 차례 나타난다.
  4. 입양이나 비입양이 특정 계절에만 집중되는 일관된 패턴은 뚜렷하지 않으나, 여름철인 6월에서 8월 전후로 구조량과 비입양 수가 증가하는 현상이 일부 확인된다.
df_adopt <- df %>%
  filter(!is.na(month), !is.na(type_kr)) %>%
  group_by(month, adopted) %>%
  summarise(count = n(), .groups = "drop")

ggplot(df_adopt, aes(x = month, y = count, color = adopted)) +
  geom_line(linewidth = 1.2) +
  labs(
    title = "월별 유기동물 입양 및 비입양 추이", subtitle = "(2020-01 ~ 2025-04)",
    x = "월", y = "유기동물 수", color = "입양 여부"
  ) +
  scale_color_manual(values = c(
    "입양" = "#5ed399", 
    "비입양" = "#006644"
  )) +
  scale_x_date(
    date_breaks = "3 months", date_labels = "%Y-%m",
    limits = c(as.Date("2020-01-01"), as.Date("2025-05-01"))
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-1-2. 입양률의 시계열 추이 분석

  1. 입양률은 2020년~2021년 초반까지는 60~70% 수준으로 비교적 높은 수준을 유지하였으나, 2021년 중반부터는 40% 선까지 하락하는 경향을 보인다.
  2. 2022년 구간에서는 입양률 수치가 불안정하게 나타나며, 특정 달에 입양률이 급등하거나 급락하는 현상이 명확하게 관찰된다.
  3. 2024년 말에는 입양률이 70%를 초과하여 기록되었으며, 이후로도 상승세가 이어지며 입양률 최고점을 지속적으로 갱신하고 있다.
df_age <- df %>%
  filter(!is.na(month), !is.na(type_6)) %>%
  mutate(adopted = ifelse(type_6 == "Adoption", "입양", "비입양")) %>%
  group_by(month, adopted) %>%
  summarise(count = n(), .groups = "drop") %>%
  tidyr::pivot_wider(names_from = adopted, values_from = count, values_fill = 0) %>%
  mutate(total = 입양 + 비입양, 입양률 = 입양 / total)

ggplot(df_age, aes(x = month, y = 입양률)) +
  geom_line(color = "#5ed399", linewidth = 1.2) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m", limits = c(as.Date("2020-01-01"), as.Date("2025-05-01"))) +
  labs(
    title = "월별 입양률 변화 추이", subtitle = "(2020-01 ~ 2025-04)",
    x = "월", y = "입양률"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-2. 건강 이상 상태 구조 비중의 변화

  1. 노령 상태는 대부분의 시기에 걸쳐 높은 비율을 차지한다. 겨울철과 코로나 이후 시점에서 소폭의 상승 경향이 나타나며 보호소에 유입되는 노령 동물의 구조 비중이 전반적으로 안정적으로 높다는 구조 현실을 반영하는 결과이다.
  2. 고통 상태는 전체 구조 동물 중 비율은 낮지만, 특정 시점에서는 급격한 증가 현상이 나타난다. 2023년 중반과 2024년 초반에 소폭의 상승세가 확인된다.
  3. 병원 치료 중인 상태는 전반적으로 비율이 낮고 일시적으로 상승한 뒤 다시 감소하는 흐름을 보인다.
  4. 광견병 위험 상태는 특정 시점에서 급격히 증가하고 전체적으로는 불규칙하고 예외적인 분포 양상을 나타낸다.
df_total <- df %>%
  filter(!is.na(month)) %>%
  group_by(month) %>%
  summarise(total_count = n(), .groups = "drop")

target_subtypes_kr <- c("고통", "노령", "병원 치료 중", "광견병 위험") 

df_sub <- df %>%
  filter(!is.na(month), subtype_kr %in% target_subtypes_kr) %>%
  group_by(month, subtype_kr) %>%
  summarise(sub_count = n(), .groups = "drop")

df_ratio <- merge(df_sub, df_total, by = "month") %>%
  mutate(ratio = sub_count / total_count)

ggplot(df_ratio, aes(x = month, y = ratio, color = subtype_kr)) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 1.2) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m", limits = c(as.Date("2020-01-01"), as.Date("2025-05-01"))) +
  scale_color_manual(values = c(
    "광견병 위험" = "#F39C12",
    "고통" = "#D63031",
    "노령" = "#6C757D",
    "병원 치료 중" = "#00ACC1"
  )) +
  labs(
    title = "건강 이상 상태의 전체 구조 대비 비중 추이",
    subtitle = "(월별 %)",
    x = "월", y = "비중", color = "건강 이상 상태"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.title.y = element_text(margin = margin(r = 12)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4),
    legend.position = "bottom"
  )

7-3. 건강 이상 상태별 구조 비중과 입양률의 상관성

7-3-1. 고통, 광견병 위험: 상대적으로 급성 상황이거나 사회적 감정에 민감하게 작용하는 유형

  1. 고통 상태 개체
  • 구조 비중 전체 구조 중 고통 상태 개체는 대부분 1% 미만의 낮은 비중을 보이는 상태이다.
  • 2023년 중반에는 일시적으로 비중이 급등한 시점이 존재한다. 입양률과의 관계 고통 상태 비중이 높아진 시점 전후로 입양률이 소폭 하락하는 구간이 확인된다.

→ 다만 전반적으로는 입양률과 고통 상태 간 뚜렷한 반비례 관계는 보이지 않는다. 고통 상태 자체가 입양에 있어 결정적 장애 요소라고 보기는 어렵다.

  1. 광견병 위험 개체
  • 구조 비중 대부분의 시점에서 광견병 위험 개체는 0%에 가까운 비중을 차지한다.
  • 그러나 2022년 하반기부터 2023년 초까지 특정 시점에 구조 비중이 급증한 현상이 존재한다. (당시의 유행병 확산 혹은 구조 기록 기준 변경 등의 가능성을 반영하는 것으로 보인다.)

→ 입양률과의 관계 광견병 위험 비중이 급증한 시기에는 입양률이 눈에 띄게 하락하는 경향을 보인다.

df_total <- df %>%
  filter(!is.na(month)) %>%
  group_by(month) %>%
  summarise(total = n(), .groups = "drop")

target_states <- c("고통", "광견병 위험")

df_subtypes <- df %>%
  filter(!is.na(month), subtype_kr %in% target_states) %>%
  group_by(month, subtype_kr) %>%
  summarise(count = n(), .groups = "drop") %>%
  left_join(df_total, by = "month") %>%
  mutate(ratio = count / total, variable = "구조 비중") %>%
  select(month, subtype_kr, variable, value = ratio)

df_adopt <- df %>%
  filter(!is.na(month), !is.na(type_kr)) %>%
  mutate(adopted = ifelse(type_kr == "입양", "입양", "비입양")) %>%
  group_by(month, adopted) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = adopted, values_from = count, values_fill = 0) %>%
  mutate(value = `입양` / (`입양` + `비입양`)) %>%
  select(month, value)

df_adopt_expanded <- expand.grid(month = unique(df_adopt$month), subtype_kr = target_states) %>%
  left_join(df_adopt, by = "month") %>%
  mutate(variable = "입양률")


df_plot <- bind_rows(df_subtypes, df_adopt_expanded) %>%
  mutate(key = ifelse(variable == "입양률", "입양률", paste(subtype_kr, variable, sep = ".")))

ggplot(df_plot, aes(x = month, y = value, color = key)) +
  geom_line(linewidth = 1.2) +
  facet_wrap(~subtype_kr, ncol = 1) +
  scale_color_manual(values = c(
    "고통.구조 비중" = "#D63031",
    "광견병 위험.구조 비중" = "#6C757D",
    "입양률" = "#5ED399"
  )) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m") +
  labs(
    title = "건강 이상 구조 개체 비중과 해당 시점 입양률 추이 비교",
    subtitle = "2020-01 ~ 2025-04 | 고통, 광견병 위험 대상",
    x = "월", y = "비율", color = "지표"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    strip.text = element_text(face = "bold", size = 11),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.text.y = element_text(size = 9),
    legend.position = "bottom",
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-3-2. 노령, 병원 치료 중: 만성적 요인이거나 의료적 불확실성이 존재하는 유형

  1. 노령 개체
  • 구조 비중 전체 구조 중에서 노령 개체의 비중은 일정한 수준 이상으로 지속적으로 나타나는 편이다.
  • 특히 2022년~2023년 초반 구간에 비중이 점진적으로 상승하는 흐름을 보인다.
  • 입양률과의 관계 전반적으로 입양률은 노령 개체 구조 비중과 역방향 경향을 보이는 구간이 존재한다.
    노령 비중이 높아질수록 입양률이 소폭 하락하는 경향이 눈에 띈다. → 눈에 띄는 연관성은 확인하기 어렵다.
  1. 병원 치료 중 개체
  • 구조 비중 병원 치료 중으로 분류된 개체는 전체 구조 중에서 1%로 극히 적은 비중을 차지한다. → 비중이 적어 연관성을 확인하기 어렵다.
target_states2 <- c("노령", "병원 치료 중")

df_subtypes2 <- df %>%
  filter(!is.na(month), subtype_kr %in% target_states2) %>%
  group_by(month, subtype_kr) %>%
  summarise(count = n(), .groups = "drop") %>%
  left_join(df_total, by = "month") %>%
  mutate(ratio = count / total, variable = "구조 비중") %>%
  select(month, subtype_kr, variable, value = ratio)

df_adopt_expanded2 <- expand.grid(month = unique(df_adopt$month), subtype_kr = target_states2) %>%
  left_join(df_adopt, by = "month") %>%
  mutate(variable = "입양률")

df_plot2 <- bind_rows(df_subtypes2, df_adopt_expanded2) %>%
  mutate(key = ifelse(variable == "입양률", "입양률", paste(subtype_kr, variable, sep = ".")))

ggplot(df_plot2, aes(x = month, y = value, color = key)) +
  geom_line(linewidth = 1.2) +
  facet_wrap(~subtype_kr, ncol = 1) +
  scale_color_manual(values = c(
    "노령.구조 비중" = "#00ACC1",     
    "병원 치료 중.구조 비중" = "#F39C12",  
    "입양률" = "#5ed399"       
  )) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m") +
  labs(
    title = "건강 이상 구조 개체 비중과 해당 시점 입양률 추이 비교",
    subtitle = "2020-01 ~ 2025-04 | 노령, 병원 치료 중 대상",
    x = "월", y = "비율", color = "지표"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    strip.text = element_text(face = "bold", size = 11),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 7, margin = margin(b = 10, t = 6)),
    axis.text.y = element_text(size = 9),
    legend.position = "bottom",
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-3-3. 건강 이상 상태와 입양률 교차 분석

  1. 고통 상태 개체는 전체 구조 중 1% 미만의 낮은 비중을 차지하며, 입양률과 뚜렷한 상관관계는 보이지 않는다.
  2. 광견병 위험 개체는 구조 비중이 매우 낮지만, 일시적으로 급증한 시기에는 입양률이 동시에 급락하는 양상을 보인다.
  3. 노령 개체는 구조 비중이 지속적으로 높은 유형으로, 비중이 상승할수록 입양률이 낮아지는 역방향 경향이 뚜렷하다.
  4. 병원 치료 중 개체는 구조 비중이 낮은 편이지만, 비중이 일시적으로 높아진 시기에는 입양률이 함께 하락하는 패턴이 확인된다.

→ 종합적으로, 노령·병원치료와 같은 만성적/불확실한 상태는 입양률에 부정적인 영향을 미치며, 광견병 위험은 사회적 불안 요소로 입양률 급락과 연결되는 경우가 있다.

7-4. 계절과 입양 행동의 관계 분석

7-4-1. 계절별 유기동물 구조 및 입양 규모 비교

  1. 전체적으로 여름철에 유기동물의 구조 수와 입양 수가 가장 많다. 외부 활동이 증가함에 따라 유실 가능성이 높아지고, 구조량이 함께 증가하는 경향 때문이다. 여름방학, 입양 캠페인 등 사회적 요인이 맞물리면서 입양도 상대적으로 활발하게 이루어진다.
  2. 겨울철에는 구조와 입양 모두 감소하는 경향을 보인다. 야외활동이 제한되고 보호소 방문율이 낮아지는 계절적 영향이 반영된 결과이다.
  3. 봄과 가을은 구조량과 입양량 모두가 안정적이며 균형적인 수준을 유지한다.

→ 구조량 대비 입양량의 비율은 계절 간 큰 차이가 없으나, 여름철에 구조와 입양이 집중되는 경향이 특히 두드러진다. 반면 봄과 가을은 일정한 흐름을 유지하며, 겨울철은 구조 및 입양 모두 저조한 수준에 머무르는 경향이 지속된다.

df_season <- df %>%
  filter(!is.na(season), !is.na(adopted)) %>%
  group_by(season, adopted) %>%
  summarise(count = n(), .groups = "drop")

df_season$season <- factor(df_season$season, levels = c("봄", "여름", "가을", "겨울"))

ggplot(df_season, aes(x = season, y = count, fill = adopted)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "계절별 유기동물 구조 및 입양 수",
    subtitle = "(전체 누적 기준)",
    x = "계절", y = "유기동물 수", fill = "입양 여부"
  ) +
  scale_fill_manual(values = c(
    "입양" = "#C9E7D1", 
    "비입양" = "#528F70"
  )) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.title.y = element_text(margin = margin(r = 12)),
    axis.title.x = element_text(margin = margin(t = 8)),
    axis.text.x = element_text(size = 11),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-4-2. 계절별 입양률 비교

  1. 입양률은 계절 간 큰 격차는 없지만, 여름철 입양률이 상대적으로 가장 높다.
  2. 겨울철 입양률은 가장 낮다. 입양 환경의 물리적 제약(추위, 방문 감소 등)이 반영된 결과로 볼 수 있다.
  3. 봄과 가을은 전체적으로 안정적인 입양률을 유지한다.
df_season_ratio <- df %>%
  filter(!is.na(season), !is.na(adopted)) %>%
  group_by(season, adopted) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = adopted, values_from = count, values_fill = 0) %>%
  mutate(
    total = 입양 + 비입양,
    입양률 = 입양 / total
  ) %>%
  mutate(season = factor(season, levels = c("봄", "여름", "가을", "겨울")))

ggplot(df_season_ratio, aes(x = season, y = 입양률)) +
  geom_col(fill = "#b3eac7",width = 0.6) +
  geom_text(aes(label = percent(입양률, accuracy = 0.1)), vjust = -0.5, size = 4) +
  scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1)) +
  labs(
    title = "계절별 입양률 비교",
    subtitle = "(전체 누적 기준, 구조 대비 입양 비율)",
    x = "계절", y = "입양률"
  ) +
  theme_minimal() +
  theme(
    text = element_text(family = "Noto Sans KR"),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11, margin = margin(b = 10)),
    axis.text.x = element_text(size = 11, margin = margin(b = 6, t = 6)),
    panel.border = element_rect(color = "#505050", fill = NA, linewidth = 0.4)
  )

7-4-3. 계절과 입양 행동의 관계

  1. 유기량과 입양량은 여름에 집중된다. → 유기 및 입양 모두 계절적 요인의 영향을 받는다는 점을 나타낸다.
  2. 입양률 또한 여름에 가장 높다. → 구조 대비 입양 비율은 여름이 가장 높고, 겨울이 가장 낮다. 단순 구조량 증가에 따른 기계적 증가가 아니라, 입양 행동 자체가 여름에 더 활발함을 의미한다.
  3. 겨울은 구조량과 입양량 모두 저조하며, 입양률도 가장 낮다.
  4. 봄·가을은 구조량과 입양률 모두 안정적인 수준을 유지한다.

→ 따라서 입양률 비교는 구조 수만으로는 파악되지 않는 계절별 입양 선호도의 실체를 드러낸다.

7-5. 통합 분석

  1. 입양률에 가장 큰 영향을 미치는 요인은 건강 상태이다.
  2. 노령 상태의 비중이 높을수록 입양률이 낮아지는 경향이 뚜렷하게 나타나며, 노령 개체 비중과 입양률 간에 명확한 반비례 관계가 있다.
  3. 연령이 1살~3살로 젊다고 하더라도, 노령 판정이나 기타 건강 이상 상태에 해당하는 경우에는 입양이 기피되는 경향이 강하다.
  4. 여름철에는 구조 수와 입양 수가 모두 증가하며, 겨울철에는 구조와 입양 모두 저조해지는 계절적 변화가 존재한다.
  5. 유기동물이 어떤 방식으로 구조/보호되었는지도 입양 가능성에 영향을 줄 수 있으나, 건강 상태(노령, 질병 등) 가 훨씬 더 강력한 입양 결정 요인이다.

8. 종합 결론 및 정책·디자인 제안

8-1. 종합 결론

  1. 유기동물은 대부분 개와 고양이이며, 검정색 개체와 국내단모종의 비중이 가장 높다.
  2. 입양률에 가장 큰 영향을 미치는 요인은 건강 상태이다. 노령, 고통, 병원 치료 중 상태의 개체는 입양이 거의 이루어지지 않는다.
  3. 건강 이상 판정은 실제 연령과 무관하게 젊은 개체에게도 부여되고 있으며, 특히 1~2살의 젊은 개체들이 건강 저하로 인해 노령으로 판정되어 입양이 어려운 상태이다.
  4. 입양 선호 연령은 생후 2개월이며, 3살 이후부터는 입양률이 급감하는 경향을 보인다.
  5. 중성화 여부는 입양 성사에 긍정적인 영향을 미치는 핵심 변수이다.
  6. 색상과 품종은 유기의 직접적인 원인이라고 단정할 수 는 없지만 입양 선호도에 영향을 준다.
  7. 보호 상태 중 임시보호, 제휴기관 보호일수록 입양 가능성이 높다.
  8. 입양률은 여름에 가장 높고, 겨울에 가장 낮다.

→ 구조량과 입양량은 계절, 건강 상태, 중성화 여부 등 다양한 요인의 영향을 받는다. → 종합적으로 입양 성패의 결정 요인은 건강 상태이며, 나이, 중성화, 품종, 계절 등의 변수는 그에 따라 보조적으로 작용한다.

8-2. 정책 제안

  1. 중성화 조기 지원 정책 확대 단순한 비용 지원을 넘어, 지자체별 중성화 조기지원 전담 부서 신설 및 중성화 인증 시스템 구축이 필요하다. 또한 중성화 완료 동물에 대해 보호소-입양플랫폼 간 자동 태깅 연계를 구현함으로써, 우선 추천 대상군으로 자동 분류되도록 해야 한다. 중장기적으로는 지자체 중성화 예산 비율을 확대하고, 민간 수의사 협약 시스템을 통해 수의료 접근성을 높이는 방식으로 확장할 수 있다.

  2. 건강 중심 보호 체계 개선의 실행 체계화 모든 구조 동물에 대해 입소 48시간 이내 건강 상태 진단을 의무화하고, 건강한 개체-치료 필요 개체-예후불량 개체로 분류하는 체계를 구축해야 한다. 치료 필요 개체에 대해서는 보호소-지역 동물병원 간 협력 진료 네트워크를 확대하고, 입양 연계를 고려한 치료 후 입양 전환 트래킹 시스템을 도입하는 것이 필요하다.

  3. 임시보호 제도의 확장 및 제도화 현재 일부 보호소에서만 시범적으로 운영되는 임시보호 제도를 전국 단위로 확대 적용해야 한다. 이를 위해서는 시민 보호자 등록제, 보호자 교육 프로그램 이수 인증제, 임시보호 점수제 기반 보상 시스템 등의 제도화를 추진할 수 있다. 특히 입양으로 전환된 사례는 입양 전환 시 리워드 지급인 입양 인센티브 환급 방식으로 설계함으로써 제도 참여를 유도할 수 있다.

  4. 건강취약 개체 후원 입양 제도의 구체화 후원 입양은 보호자는 등록하되 경제적 책임은 후원자/지자체가 분담하는 구조로 정의한다. 이를 위해 후원 입양 전용 온라인 플랫폼을 구축하고, 기업 후원 연계가 가능한 시스템을 설계한다. 특히 장기 치료가 필요한 개체는 1인 1마리 후원 형태로 매칭하는 고정형 후원 모델로 발전시킬 수 있다.

  5. 계절·시계열 기반 캠페인 및 데이터 플랫폼 운영 입양률이 높은 여름철(6~8월)을 중심으로 계절 집중 캠페인을 운영한다. 또한 보호소와 입양 플랫폼이 구조-입양 트렌드 정보를 공동 공개할 수 있도록 통합 데이터 플랫폼을 마련해야 한다. 시민은 이 플랫폼을 통해 이번 달 입양률, 보호 동물 현황, 가장 입양이 시급한 개체 등의 정보를 실시간으로 확인할 수 있어야 한다. 장기적으로는 지역별 보호소 입양성과를 비교할 수 있는 입양지표 정량화 체계 도입도 고려할 수 있다.

8-3. 디자인 적용 전략 및 시각 커뮤니케이션 연계 방안

유기동물 입양에 영향을 미치는 요인이 명확히 드러난 만큼, 관련 정보를 제공하는 시각 시스템 및 캠페인 디자인도 보다 체계적이고 직관적으로 개선할 필요가 있다. 이를 통해 시민의 행동 전환을 유도하고, 입양률을 실질적으로 높일 수 있다.

앞서 기존 유기동물 입양 어플의 장단점을 분석한다.

장점

  • 접근성: 누구나 쉽게 다운로드하여 전국 보호소 정보를 확인할 수 있다. 포인핸드 기준, 사용자 규모가 크고 확산성이 높다.
  • 실시간 데이터: 보호소 정보와 연동되어 구조·입양 현황을 빠르게 반영한다. 실종·목격 정보까지 통합된 구조이다.
  • 커뮤니티 연계: 일부 앱은 입양 후기 공유, SNS 공유 기능을 통해 입양자 간 유대감을 형성한다.
  • 채팅 기능 제공: 퍼피링크 등은 입양자와 보호소 간 채팅 기능을 지원하여 소통의 장벽을 낮춘다.

단점

  • 입양 성공 요인 미반영: 중성화 여부, 건강 상태, 보호 상태 등의 핵심 입양 요인을 UI/UX에 반영하지 않고 있다.
  • 시각 정보 구조 부족: 텍스트 중심 정보 제공이 대부분이며, 컬러코드나 상태별 시각적 구분이 없다.
  • 입양 추천 기능 부재: 사용자가 입양하기 좋은 개체를 추천받거나 비교할 수 있는 지표나 가이드가 없다.
  • 임시보호/후원 기능 미흡: 임시보호나 건강취약 개체의 후원·특별 입양 기능이 구조적으로 부족하다.
  • 감성 캠페인 연계 약함: 시즌별, 조건별 맞춤형 입양 캠페인을 시각적으로 연결하지 못하고 있다.

기존의 유기동물 입양 어플은 기본적인 정보 제공에는 충실하나, 입양 성공률을 높이기 위한 시각적 구조와 행동 유도 디자인 요소가 부족하다. 중성화 여부, 건강 상태, 보호 상태, 연령, 색상 등 귀하께서 도출한 입양 결정 요인들이 사용자의 선택 흐름에 반영되지 않기 때문에, 정보는 제공되나 판단 기준은 제공되지 못하고 있다. 이를 보완하기 위해 다음과 같은 디자인 전략이 필요하다.

  1. 상태 시각화를 통한 정보의 직관화

기존 어플은 대부분 개체의 상태 정보를 텍스트 중심으로만 나열하고 있으며, 사용자는 각 조건을 해석해 스스로 판단해야 한다. → 상태 배지, 아이콘 체계를 도입한다.

  • 상태 배지 시스템: 중성화 완료, 건강 양호, 임시보호 중 상태를 컬러 배지로 명확하게 구분
  • 상태 아이콘 도입: 건강 상태를 아이콘으로 표현 (🟢 건강, 🔶 치료 중, ⚫ 노령) - 입양 가능성 게이지 바: 귀하의 분석 결과(중성화+건강+연령+색상)를 점수화해 게이지로 시각 → “입양 가능성 ★★★★☆”와 같은 직관적 표현
  1. 추천 기반 사용자 인터페이스 구현

기존 어플은 단순 리스트 구조로 개체 정보를 일괄적으로 나열하고 있어, 입양 가능성이 높은 개체가 묻히는 문제가 발생한다.

  • 상단 추천 섹션: 귀하의 데이터 기준(중성화+2개월령 등)에 해당하는 개체를 추천 동물 영역으로 상단 고정
  • 추천 필터 기능: 중성화 완료만 보기, 임시보호 동물 보기 등의 버튼형 필터 추가
  • 스와이프 카드 UI: Tinder처럼 좌우로 넘기며 입양 대상 동물을 탐색 → 시각적으로 집중도와 몰입감 향상
  1. 행동 유도형 디자인 설계

현재의 어플 구조는 개체를 보여주기만 할 뿐, 입양으로 이어지는 행동을 유도하는 장치가 부족하다. → 사용자의 행동을 단계별로 설계한 인터페이스가 필요하다.

  • 입양 매칭 결과 제공: “귀하에게 어울리는 보호동물은 이 아이입니다!” 알고리즘 추천 시스템
  • 성향 비교 툴: 사용자가 활발한 동물, 조용한 동물을 선택하면 조건 기반 매칭
  • 즉시 문의 버튼: 개체 상세 정보 하단에 채팅·신청 버튼을 항상 고정 배치 → 행동 유도 강화
  1. 후원 및 임시보호 기능 강화

건강취약 개체나 노령 동물은 입양률이 낮아 후원 또는 임시보호로 연계하는 전략이 필요하다.

  • 후원형 프로필: 건강취약 개체는 “후원이 필요한 친구입니다” 표시 + 후원 금액 선택 UI 삽입
  • 임시보호 신청 구조 연동: 임보 가능 동물은 우측 상단에 임보 신청 버튼 고정
  • 스토리형 UX: 임시보호/치료 후 입양 성공기를 카드 뉴스 형태로 구성 → 사회적 감동 유도
  1. 계절 기반 캠페인 디자인 도입

기존 앱들은 이러한 시간성과 계절성을 디자인에 반영하지 못하고 있으며, 사용자는 ’지금이 왜 입양하기 좋은 시점인지’에 대한 정보 없이 앱을 사용하게 된다. → 계절별 테마 컬러와 메시지를 적용한 디자인 전략이 필요하다.

  • 계절별 메인 테마 UI: 여름: 밝은 파랑, 노랑 계열 배경 + “지금, 함께할 친구를 만드세요!” 겨울: 따뜻한 톤과 눈 이미지 활용 + “이 추운 계절, 따뜻한 가족을 기다립니다”
  • 캘린더형 입양 타이밍 안내: 가장 입양이 활발한 시기, 임시보호 수요가 급증하는 시기 등을 달력으로 시각화 - 특별 주간 캠페인 레이아웃: “2개월령 입양 주간” → 홈화면 전면 배너 + 입양 가이드 카드 UI 등장