본문 바로가기
프로그래밍 언어/R

R 8. 데이터 분석하기

by Jinger 2024. 2. 1.

서론

    앞서 배운 내용을 토대로 데이터를 분석해 보자.


준비하기

    '한국복지패널데이터'를 이용하여 실습을 해보자. 한국복지패널데이터는 한국보건사회연구원에서 가구의 경제활동을 연구해 정책 지원에 반영할 목적으로 발간하는 조사 자료이다. 2006년부터 매년 7000 가구를 대상으로 조사한 자료로, 경제활동, 생활실태, 복지욕구 등 천여 개 변수로 구성되어 있다. 복지패널데이터는 엄밀한 절차로 수집되었고, 다양한 변수를 담고 있기에 연습하기 좋은 재료이다. 이를 통해 한국인의 삶을 살펴보자. 아래 예시는 2016년에 발간된 2015년의 한국인의 삶 데이터이다.

데이터 준비

   깃헙에서 다운로드할 시 'Koweps_hpc10_2015_beta1.sav'파일을 다운하여 프로젝트 폴더에 삽입하면 된다. 직접 한국복지패널 사이트에 접속하여 데이터를 다운로드하여 프로젝트 폴더에 삽입해도 된다.

패키지 준비

    복지패널데이터는 통계분석 소프트웨어인 SPSS 전용 파일로 되어 있다. 'foreign' 패키지를 이용하면 SPSS, SAS, STATA 등 다양한 통계분석 소프트웨어의 파일을 불러올 수 있다.

install.packages("foreign")	# 패키지 설치

library(foreign)	# SPSS 파일 불러오기
library(dplyr)		# 전처리
library(ggplot2)	# 시각화
library(readxl)		# 엑셀 파일 불러오기

변수 검토 및 전처리

    foreign 패키지의 read.spss()를 이용해 복지패널데이터를 불러온다. 원본은 복구해야 할 상황을 대비해 복사본을 만들어 분석에 활용하자. 데이터를 불러와 데이터의 구조와 특징을 파악하자. 규모가 큰 조사 자료는 보통 데이터의 특성을 설명해 놓은 코드북(Codebook)과 함께 제공된다. 코드북에는 코드로 된 각각의 변수명이 무엇을 의미하는지 나타나 있다. 이를 살펴보며 데이터의 특성에 대해 감을 잡거나, 어떤 변수를 활용할지, 분석 방향에 대한 아이디어를 얻을 수 있다. 우리는 우선 사용하기 편하도록 변수명을 수정할 것이다.

# 데이터 불러오기
raw_welfare <- read.spss(file = "Koweps_hpc10_2015_beta1.sav", to.data.frame = T)

# 복사본 만들기
welfare <- raw_welfare

# 데이터 검토
head(welfare)
tail(welfare)
View(welfare)
dim(welfare)
str(welfare)
summary(welfare)

# 변수명 바꾸기
welfare <- rename(welfare,
		sex = h10_g3,			# 성별
            	birth = h10_g4,			# 태어난 연도
            	marriage = h10_g10,		# 혼인 상태
            	religion = h10_g11,		# 종교
            	income = p1002_8aq1,		# 월급
            	code_job = h10_eco9,		# 직업 코드
            	code_region = h10_reg7)		# 지역 코드

변수 간 관계 분석

   위와 같이 준비가 되었다면 이제 자신이 원하는 분석에 맞게 전처리 후 데이터를 요약한 표를 만든 후 분석 결과를 쉽게 이해할 수 있도록 그래프를 그리며 변수 간 관계를 분석하면 되나. 아래 여러 예시를 보면서 이해해 보자.


데이터 분석

성별에 따른 월급 차이

    주제를 보면 성별과 월급 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 성별 월급 평균표와 그래프를 만들어 보자.

# 성별 전처리
class(welfare$sex)
## [1] "numeric"

table(welfare$sex)
##    1    2
## 7578 9086

welfare$sex <- ifelse(welfare$sex == 9, NA, welfare$sex)	# 이상치(무응답/모름은 9를 부여) 결측 처리
table(is.na(welfare$sex))
## FALSE
## 16664

welfare$sex <- ifelse(welfare$sex == 1, "male", "female")	# 성별 항목 이름 부여
table(welfare$sex)
## female male
##   9086 7578

# 빈도 그래프
qplot(welfare$sex)

# 월급 전처리
class(welfare$income)
## [1] "numeric"

summary(welfare$income)
##  Min. 1st Qu. Median Mean   3rd Qu.   Max.   NA's
##  0.0  122.0   192.5  241.6  316.6     2400.0 12030	# 만 단위이다.

# 빈도 그래프
qplot(welfare$income) + xlim(0, 1000)	# 대다수와 최댓값 차이가 크기에 0~1000까지만 표현

welfare$income <-ifelse(welfare$income %in% c(0, 9999), NA, welfare$income)	# 이상치 결측 처리
table(is.na(welfare$income))	# 결측치 확인
## FALSE TRUE
## 4620  12044

# 성별 월급 평균표 만들기
sex_income <- welfare %>%
	filter(!is.na(income)) %>%
	group_by(sex) %>%
	summarise(mean_income = mean(income))
sex_income
# 결과 생략

# 성별 월급 평균 그래프 만들기
ggplot(data = sex_income, aes(x = sex, y = mean_income)) + geom_col()

성별 빈도 그래프/월급 빈도 그래프/성별 월급 평균 그래프

나이와 월급 관계

   주제를 보면 나이와 월급 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 나이에 따른 월급 평균표와 그래프를 만들어 보자. 월급 전처리는 앞서 진행했으니 여기서는 생략한다.

# 나이 변수
class(welfare$birth)
## [1] "numeric"

# 이상치 확인
summary(welfare$birth)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1907 1946    1966   1196 1988    2014

# 결측치 확인
table(is.na(welfare$birth))
## FALSE
## 16664

# 이상치 결측 처리
welfare$birth <- ifelse(welfare$birth == 9999, NA, welfare$birth)	# 무응답과 모름은 9999로 처리됨

# 빈도 그래프
qplot(welfare$birth)

# 파생 변수 만들기
welfare$age <- 2015 - welfare$birth + 1	# 2015년 기준, 한국식 나이 계산
summary(welfare$birth)
## Min. 1st Qu. Median Mean  3rd Qu. Max.
## 2.00 28.00   50.00  48.43 70.00   109.00

# 나이 별 월급 평균표
age_income <- welfare %>%
	filter(!is.na(income)) %>%
	group_by(age) %>% 
	summarise(mean_income = mean(income))

head(age_income)
# 결과 생략

# 나이 별 월급 평균 그래프
ggplot(data = age_income, aes(x = age, y = mean_income)) + geom_line()

연령대에 따른 월급 차이

    주제를 보면 나이를 연령대로 분류하고 월급을 검토 및 전처리한 뒤 변수 간의 관계를 분석하기 위해 연령대별 월급 평균표와 그래프를 만들어 보자. 월급 전처리는 앞서 진행했으니 여기서는 생략한다. "scale_x_discrete()"는 "limits" 파라미티를 이용하여 x 축 순서를 지정할 수 있다.

# 연령대 파생 변수 만들기
welfare <- welfare %>% mutate(ageg = ifelse(age < 30, "young", ifelse (age<=59, "middle", "old")))

table(welfare$ageg)
## middle old  young
## 6049   6281 4334

# 빈도 그래프
qplot(welfare$ageg)

# 연령대에 따른 월급 차이 평균표
ageg_income <- welfare %>% 
	filter(!is.na(income)) %>%
	group_by(ageg) %>%
	summarise(mean_income = mean(income))
ageg_income
# 결과 생략

# 연령대에 따른 월급 차이 평균 그래프
ggplot(data = ageg_income, aes(x = ageg, y = mean_income)) + 
	geom_col() +
	scale_x_discrete(limits = c("young", "middle", "old"))	# x축 순서 지정

연령대 및 성별 월급 차이

   주제를 보면 나이를 연령대로 분류하고 성별과 월급 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 연령대 및 성별 월급 평균표와 그래프를 만들어 보자. 연령대, 성별, 월급 모두 앞서 전처리를 진행했으니 생략한다. "ggplot()"의 "fill" 파라미터 기준으로 색상을 지정할 수 있다. "geom_col()"의 "position" 파라미터를 "dodge"로 설정해 막대를 분리할 수 있다.

# 연령대 및 성별 월급 평균표
sex_income <- welfare %>%
	filter(!is.na(income)) %>%
    	group_by(ageg, sex) %>%
    	summarise(mean_income = mean(income))
sex_income
# 결과 생략

# 연령대 및 성별 월급 평균 그래프 1
ggplot(data = sex_income, aes(x = ageg, y = mean_income, fill = sex)) +	# fill의 기준에 따라 색상 다르게 설정
	geom_col() +
    	scale_x_discrete(limits = c("young", "middle", "old"))

# 연령대 및 성별 월급 평균 그래프 2
ggplot(data = sex_income, aes(x = ageg, y = mean_income, fill = sex)) +
	geom_col(position = "dodge") +
    	scale_x_discrete(limits = c("young", "middle", "old"))
        
# 나이 및 성별 월급 평균표
sex_age <- welfare %>%
	filter(!is.na(income)) %>%
    	group_by(age, sex) %>%
        summarise(mean_income = mean(income))
sex_age
# 결과 생략

# 나이 및 성별 월급 그래프
ggplot(data = sex_age, aes(x = age, y = mean_income, col = sex)) + geom_line()

직업별 월급 차이

    주제를 보면 직업과 월급 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 직업별 월급 평균표와 그래프를 만들어 보자. 월급은 앞서 전처리를 진행했으니 생략한다. "coord_flip()"은 막대그래프를 오른쪽으로 90도 회전시킨다.

# 직업 변수 검토
class(welfare$code_job)
## [1] "numeric"

table(welfare$code_job)
## 결과 생략

# 직업 코드와 직업 연결된 엑셀 파일 불러오기
library(readxl)
list_job <- read_excel("Koweps_Codebook.xlsx", col_names = T, sheet = 2)
head(list_job)
## 결과 생략

dim(list_job)
## [1] 149 2

# job변수를 welfare와 결합
welfare <- left_join(welfare, list_job, by = "code_job")

welfare %>%
	filter(!is.na(code_job)) %>%
    	select(code_job, job) %>%
        head(10)
## 결과 생략

# 직업별 월급 평균표
job_income <- welfare %>%
	filter(!is.na(job) & !is.na(income)) %>%
	group_by(job) %>%
	summarise(mean_income = mean(income))
head(job_income)
## 결과 생략

top10 <- job_income %>%
	arrange(desc(mean_income)) %>%
	head(10)

# 직업별 월급 그래프
ggplot(data = top10, aes(x = reorder(job, mean_income), y = mean_income)) +
	geom_col() +
	coord_flip()

bottom10 <- job_income %>%
	arrange(mean_income) %>%
	head(10)
bottom10
## 결과 생략

ggplot(data = bottom10, aes(x = reorder(job, -mean_income), y = mean_income)) +
	geom_col() +
	coord_flip() +
	ylim(0, 850)

성별 직업 빈도

   주제를 보면 성별과 직업 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 성별 월급 평균표와 그래프를 만들어 보자. 성별과 직업 모두 앞서 전처리를 진행했으니 생략한다.

# 남성 직업 빈도 상위 10개 추출
job_male <- welfare %>%
	filter(!is.na(job) & sex == "male") %>%
    group_by(job) %>%
    summarise(n = n()) %>%
    arrange(desc(n)) %>%
    head(10)
job_male
## 결과 생략

# 여성 직업 빈도 상위 10개 추출
job_female <- welfare %>%
	filter(!is.na(job) & sex == "female") %>%
    group_by(job) %>%
    summarise(n = n()) %>%
    arrange(desc(n)) %>%
    head(10)
job_female
## 결과 생략

# 남성 직업 빈도 상위 10개 그래프
ggplot(data = job_male, aes(x = reorder(job, n), y = n)) + geom_col() + coord_flip()

# 여성 직업 빈도 상위 10개 그래프
ggplot(data = job_female, aes(x = reorder(job, n), y = n)) + geom_col() + coord_flip()

종교 유무에 따른 이혼율

   주제를 보면 종교와 혼인 상태 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 성별 월급 평균표와 그래프를 만들어 보자.

# 종교 변수 검토
class(welfare$religion)
## [1] "character"

table(welfare$religion)
##   no  yes
## 8047 8617

# 빈도 그래프
qplot(welfare$religion)

# 혼인 상태 변수 검토
class(welfare$marriage)
## [1] "numeric"
table(welfare$marriage)
# 0 - 비해당(18세 미만), 1 - 유배우, 2 - 사별, 3 - 이혼, 4 - 별거, 5 - 미혼, 6 - 기타
##    0    1    2   3  4    5  6
## 2861 8431 2117 712 84 2433 26

# 이혼 여부 변수 만들기
welfare$group_marriage <- ifelse(welfare$marriage == 1, "marriage",
	ifelse(welfare$marriage == 3, "divorce", NA))
table(welfare$group_marriage)
## divorce marriage
##     712     8431

table(is.na(welfare$group_marriage))
## FALSE TRUE
##  9143 7521

# 빈도 그래프
qplot(welfare$group_marriage)

# 종교 유무에 따른 이혼율 표
religion_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
	group_by(religion, group_marriage) %>%
	summarise(n = n()) %>%
	mutate(tot_group = sum(n)) %>%
	mutate(pct = round(n/tot_group*100, 1))
religion_marriage
## 결과 생략

# 이혼 추출
divorce <- religion_marriage %>%
	filter(group_marriage == "divorce") %>%
	select(religion, pct)
divorce
## 결과 생략

# 종교 유무에 따른 이혼율 그래프
ggplot(data = divorce, aes(x = religion, y = pct)) + geom_col()

# 연령대별 이혼율 표
ageg_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
	group_by(ageg, group_marriage) %>%
	summarise(n = n()) %>% 
	mutate(tot_group = sum(n)) %>% 
	mutate(pct = round(n/tot_group*100, 1))
ageg_marriage
## 결과 생략

# 연령대별 이혼율 추출
ageg_divorce <- ageg_marriage %>%
	filter(ageg != "young" & group_marriage == "divorce") %>%	# 초년 제외
	select(ageg, pct)
ageg_divorce
## 결과 생략

# 연령대별 이혼율 그래프
ggplot(data = ageg_divorce, aes(x = ageg, y = pct)) + geom_col()

# 연령대, 종교 유무, 결혼 상태별 비율표
ageg_religion_marriage <- welfare %>%
	filter(!is.na(group_marriage) & ageg != "young") %>%
    group_by(ageg, religion, group_marriage) %>%
    summarise(n = n()) %>%
    mutate(tot_group = sum(n)) %>%
    mutate(pct = round(n/tot_group*100, 1))
ageg_religion_marriage
## 결과 생략

# 연령대 및 종교 유무 별 이혼율 표
df_divorce <- ageg_religion_marriage %>%
	filter(group_marriage == "divorce") %>%
		select(ageg, religion, pct)
df_divorce
## 결과 생략

# 연령대 및 종교 유무 별 이혼율 그래프
ggplot(data = df_divorce, aes(x = ageg, y = pct, fill = religion)) + geom_col(position = "dodge")

지역별 연령대 비율

   주제를 보면 성별과 월급 두 변수를 검토하고 전처리한 뒤 변수 간의 관계를 분석하기 위해 성별 월급 평균표와 그래프를 만들어 보자. 연령대 변수 전처리는 앞서 진행했으니 생략한다.

# 지역 변수 검토
class(welfare$code_region)
## [1] "numeric"

table(welfare$code_region)
##    1    2    3    4    5    6    7
## 2486 3711 2785 2036 1467 1257 2922

# 전처리
list_region <- data.frame(code_region = c(1:7),
	region = c("서울",
    	"수도권(인처/경기",
    	"부산/경남/울산",
    	"대구/경북",
    	"대전/충남",
    	"강원/충북",
    	"광주/전남/전북/제주도"))

# 지역명 변수 추가
welfare <- left_join(welfare, list_region, by = "code_region")

welfare %>% select(code_region, region) %>% head

# 지역별 연령대 비율표
region_ageg <- welfare %>%
	group_by(region, ageg) %>%
    summarise(n = n()) %>%
    mutate(tot_group = sum(n)) %>%
    mutate(pct = round(n/tot_group*100, 2))
head(region_ageg)

# 지역별 연령대 비율 그래프
ggplot(data = region_ageg, aes(x = region, y = pct, fill = ageg)) + geom_col() + coord_flip()

# 노년층 비율 내림차순(높은 순) 정렬
list_order_old <- region_ageg %>% filter(ageg == "old") %>% arrange(pct)
list_order_old
## 결과 생략

# 지역명 순서 변수 만들기
order <- list_order_old$region
order
## 결과 생략

# 지역별 노년층 비율 내림차순 정렬 그래프
ggplot(data = region_ageg, aes(x = region, y = pct, fill = ageg)) +
	geom_col() +
	coord_flip() +
	scale_x_discrete(limits = order)

# 연령대 순으로 막대 색깔 나열하기
class(region_ageg$ageg)
## [1] "character"

levels(region_ageg$ageg)
## NULL

region_ageg$ageg <- factor(region_ageg$ageg, level = c("old", "middle", "young"))

class(region_ageg$ageg)
## [1] "factor"

levels(region_ageg$ageg)
## [1] "old" "middle" "young"

# 연령대 순으로 막대 색깔 나열한 그래프 그리기
ggplot(data = region_ageg, aes(x = region, y = pct, fill = ageg)) +
	geom_col() +
    coord_flip() +
    scale_x_discrete(limits = order)


주섬주섬

  • 위에 나온 데이터는 교재의 Github에 저장된 데이터를 사용했다. 최근 데이터를 보고 싶다면 '한국복지패널' 홈페이지에서 찾으면 된다.
  • 만약 다른 데이터를 찾고 싶다면, 통계청 혹은 유명 데이터 분석 사이트로 'kaggle'이 있다.
  • 위 방식 외에 상세한 데이터 분석 기술을 원한다면 데이터 분석 공부를 따로 해야 한다. 이 블로그는 R을 이용하여 간단하게 데이터를 분석하는 방법을 알려주어 감을 잡아주기 위한 블로그이다.
  • 위 예시의 그래프를 통해 알 수 있는 것은 직관적이다. 그 안에 이유를 찾는 것은 다른 데이터 분석 기법을 이용해야한다.
  • 'dplyr'의 "count()"를 이용하면 다음과 같이 코드를 줄일 수 있다.
더보기

1. 

# 종교 유무에 따른 이혼율 표
religion_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
	group_by(religion, group_marriage) %>%
	summarise(n = n()) %>%
	mutate(tot_group = sum(n)) %>%
	mutate(pct = round(n/tot_group*100, 1))
# 종교 유무에 따른 이혼율 표
religion_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
    	count(religion, group_marriage) %>%
	group_by(religion) %>%
	mutate(pct = round(n/sum(n)*100, 1))

 2.

# 연령대별 이혼율 표
ageg_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
	group_by(ageg, group_marriage) %>%
	summarise(n = n()) %>% 
	mutate(tot_group = sum(n)) %>% 
	mutate(pct = round(n/tot_group*100, 1))
# 연령대별 이혼율 표
ageg_marriage <- welfare %>%
	filter(!is.na(group_marriage)) %>%
    	count(ageg, group_marriage) %>%
	group_by(ageg) %>%
	mutate(pct = round(n/sum(n)*100, 1))

 3.

# 연령대, 종교 유무, 결혼 상태별 비율표
ageg_religion_marriage <- welfare %>%
    filter(!is.na(group_marriage) & ageg != "young") %>%
    group_by(ageg, religion, group_marriage) %>%
    summarise(n = n()) %>%
    mutate(tot_group = sum(n)) %>%
    mutate(pct = round(n/tot_group*100, 1))
# 연령대, 종교 유무, 결혼 상태별 비율표
ageg_religion_marriage <- welfare %>%
    filter(!is.na(group_marriage) & ageg != "young") %>%
    count(ageg, religion, group_marriage)
    group_by(ageg, religion) %>%
    mutate(pct = round(n/sum(n)*100, 1))

4.

# 지역별 연령대 비율표
region_ageg <- welfare %>%
    group_by(region, ageg) %>%
    summarise(n = n()) %>%
    mutate(tot_group = sum(n)) %>%
    mutate(pct = round(n/tot_group*100, 2))
# 지역별 연령대 비율표
region_ageg <- welfare %>%
    count(region, ageg) %>%
    group_by(region) %>%
    mutate(pct = round(n/sum()n*100, 2))

참고

 

GitHub - youngwoos/Doit_R: <Do it! 쉽게 배우는 R 데이터 분석> 저장소

<Do it! 쉽게 배우는 R 데이터 분석> 저장소. Contribute to youngwoos/Doit_R development by creating an account on GitHub.

github.com

 

한국복지패널 홈페이지입니다

 

www.koweps.re.kr:442

 

Kaggle: Your Machine Learning and Data Science Community

Kaggle is the world’s largest data science community with powerful tools and resources to help you achieve your data science goals.

www.kaggle.com

 

반응형

'프로그래밍 언어 > R' 카테고리의 다른 글

R 10. 지도 시각화  (0) 2024.02.02
R 9. 텍스트 마이닝  (0) 2024.02.02
R 7. 그래프 만들기  (1) 2024.01.31
R 6. 데이터 정제하기  (0) 2024.01.30
R 5. 데이터 가공하기  (0) 2024.01.29

댓글