대충벌레 블로그
article thumbnail
Published 2021. 1. 25. 18:00
R언어 공부정리 [7] IT 기술/R
728x90
반응형

2021/01/22 - [IT/R] - R언어 공부 정리 [6]

2021/01/21 - [IT/R] - R언어 공부 정리 [5]

2021/01/20 - [IT/R] - R언어 공부 정리 [4]

2021/01/19 - [IT/R] - R 언어 공부 정리 [3]

2021/01/18 - [IT/R] - R 언어 공부정리 [2]

2021/01/15 - [IT/R] - 분석 , 통계시 유용한 R 언어 설치와 기본 공부 정리

 

이번엔 지금까지 공부했던 내용을 가지고 분석 프로젝트를 해보겠습니다.

github.com/youngwoos/Doit_R/tree/master/Data

 

youngwoos/Doit_R

저장소. Contribute to youngwoos/Doit_R development by creating an account on GitHub.

github.com

위의 링크에서 Koweps_hpc10_2015_beta1.sav 파일을 다운받아 준비를 합니다.

 

필요한 패키지 설치와 로드

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

foreign 패키지는 SPSS 파일로드, SAS , STATA 통계 소프트웨어 파일을 사용할수 있습니다.

분석을 위해 사용되는 나머지 패키지를 로드하겠습니다.

 

library(foreign) # spss 파일 로드
library(dplyr)  # 전처리
library(ggplot2) # 시각화
library(readxl) # 엑셀파일 불러올때

spss 파일을 데이터 프레임으로 불러와서 사용할수 있게 합니다.

raw_welfare <- read.spss(file='Koweps_hpc10_2015_beta1.sav',
                         to.data.frame = T)

원본은 두고 복사본을 만들어서 사용하겟습니다.

welfare <- raw_welfare

 

기본적으로 몇행 몇열인지 무슨 데이터가 들어가있는지 컬럼은 데이터형이 무엇인지 등등을 알아보도록 합니다.

dim(welfare)   # 16664 957  
head(welfare)
tail(welfare)
str(welfare)
summary(welfare)

데이터를 보면 957열 이므로 원하는 컬럼을 찾기가 어렵습니다 저희가 알아볼수 있게 변수명을 바꾸도록 하겠습니다.

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 

확인 결과 이상치는 존재하지않습니다.

근데 만약 이상치가 존재한다면 NA로 수정해주고 결측치 NA를 없애거나 다른수로 나타내야됩니다.

welfare$sex <- ifelse(welfare$sex==이상치,NA,welfare$sex)

결측치가 존재하는지 확인

table(is.na(welfare$sex)) 

# 결측치 존재 유무 
FALSE 
16664 

 

이번에는 알아보기 쉽게 성별 1을 male로 2를 female로 수정해줍니다.

welfare$sex <- ifelse(welfare$sex==1,"male",'female')
# 수정후 확인
table(welfare$sex)

# 실행 결과 
female   male 
  9086   7578 

qplot(welfare$sex)

성별 전처리가 끝났으니 월급 전처리를 합니다 : 이상치와 결측치가 있다면 제거합니다.

class(welfare$income) 
# [1] "numeric"
table(is.na(welfare$income))

# 결과
FALSE  TRUE 
 4634 12030 

TRUE가 12030개로 결측치가 엄청 많음 

boxplot(welfare$income)
boxplot(welfare$income)$stats

      [,1]
[1,]   0.0
[2,] 122.0
[3,] 192.5
[4,] 316.6
[5,] 608.0

boxplot으로 확인결과 이상치(극단치)가 많은것을 볼수있습니다.

0보다 작거나 608보다 크면 이상치 입니다.

이상치(극단치)를 모두 결측치 NA 로 바꿔줍니다.

welfare$income <- ifelse(welfare$income<0 | welfare$income >608, NA , welfare$income )

 

성별에 따른 월급차이가 있는지 분석해 봅시다.

wf <- welfare %>% filter(!is.na(sex) & !is.na(income))  %>%
  group_by(sex) %>% summarise(income_avg=mean(income))
  
filter로 성별과 수입이 결측치 인것을 제외하고
성별기준 월급의 평균을 알아봅니다.

# A tibble: 2 x 2
  sex    income_avg
  <chr>       <dbl>
1 female       156.
2 male         272.

눈으로 확인하기 위해 시각화를 해줍니다 .

이제 나이와 월급간의 관계를 알아봅시다. 몇살때 가장 월급을 많이 받을까?

우선 출생년도를 기준으로 나이를 구해야 합니다.

우선 이상치가 있는지 확인해봅니다.

boxplot(welfare$birth)
# 이상치(극단치) 존재하지않음

table(is.na(welfare$birth)) 
# 결측치 확인 결과 존재하지않음

FALSE 
16664 

만약 이상치가 있을경우 결측 처리 합니다.

welfare$birth <- ifelse(welfare$birth==이상치,NA,welfare$birth)

나이 변수를 만들고 데이터 기준 2015년 이므로 2015년 - 출생년도 +1 을 해줍니다

그리고 데이터를 확인해봅니다

welfare$age <- 2015-welfare$birth +1 # 나이변수
summary(welfare$age)

  summary(welfare$age)
Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
2.00   28.00   50.00   48.43   70.00  109.00 
qplot(welfare$age)

나이에 따른 월급 평균표를 구해봅시다

age_income <- welfare %>%  # welfare 데이터에서
  filter(!is.na(income)) %>% # income 결측치 제외
  group_by(age) %>% # 나이 별
  summarise(mean_income=mean(income)) # 월급 평균

눈으로 보기위한 선형 그래프를 생성해줍니다.

연령대에 따른 월급의 차이를 알고싶습니다. 30대 미만은 young , 30~60 middle , 60 이상은 old 컬럼을 추가해봅시다

wf2 <- welfare %>% mutate(agegroup = ifelse(age<30,'young',ifelse(age<=59,'middle','old')))
# 새 컬럼 agegroup을 추가해서 30대 미만은 young
# 60세 미만은 middle 그 이상은 old 
table(wf2$agegroup) # 빈도를 측정해봅시다

middle    old  young 
  6049   6281   4334 
  
  # 빈도를 나타내 봅시다
qplot(wf2$agegroup)

이제 새로운 데이터프레임에 연령대별 월급평균을 구해봅시다.

agegroup_income <- wf2 %>%  # wf2 데이터에서
  filter(!is.na(income)) %>% # 월급이 결측치가 아닌것
  group_by(agegroup) %>% # 나이대별
  summarise(mean_income=mean(income)) # 월급 평균

막대 그래프로 나타내 봅시다.

ggplot(data=agegroup_income,aes(x=agegroup,y=mean_income)) + geom_col()

 

그래프 표시할때 알파벳순서로 컬럼이 표시되는데 이 컬럼순서를 변경하기 위해선 scale_x_discrete(limits=()) 를 사용합니다. young , middle , old 순서대로 표시해 보겠습니다.

ggplot(data=agegroup_income,aes(x=agegroup,y=mean_income)) + geom_col()+
  scale_x_discrete(limits=c("young","middle","old"))

연령대 및 성별 월급차이를 분석해봅시다

연령대에서 성별에 따른 월급차이가 있는지 알아보기 위해 연령대 및 성별에 따른 월급 평균표를 만들어봅시다.

sex_income <- wf2 %>% # welfare 데이터를
  filter(!is.na(income)) %>% #월급 결측치를 제외하고
  group_by(agegroup,sex) %>% #연령대 별 성 별 
  summarise(mean_income = mean(income)) # 월급평균
  
  # A tibble: 6 x 3
# Groups:   agegroup [3]
  agegroup sex    mean_income
  <chr>    <chr>        <dbl>
1 middle   female       186. 
2 middle   male         353. 
3 old      female        81.5
4 old      male         174. 
5 young    female       160. 
6 young    male         171. 

앞에서 만든 표를 이용해서 그래프를 생성해봅시다.

막대는 연령대별로 표현되도록 x축에는 agegroup을 지정 

또 막대가 성별에 따라 다른색이 표현되도록 fill에 sex를 지정하고 축 순서는 연령대 순서대로 설정해봅시다.

ggplot(data=sex_income,aes(x=agegroup,y=mean_income,fill=sex))+
  geom_col()+ # 막대 그래프 y축이 값
  scale_x_discrete(limits = c("young","middle","old")) # 정렬

 

위와 같이 출력하면 성별의 월급이 막대에 한번에 표현되어 차이를 비교하기 힘든데

geom_col()의 position='dodge'로 설정해서 막대를 분리해줍니다.

ggplot(data=sex_income,aes(x=agegroup,y=mean_income,fill=sex))+
  geom_col(position="dodge")+
  scale_x_discrete(limits = c("young","middle","old"))

이번엔 연령대말고 나이와 성별 월급평균을 그래프로 만들어보겠습니다.

선그래프에 성별에 따라 다르게 표현되도록 만들어봅시다.

우선 성별 연령별 월급 평균표를 생성해줍니다.

sex_age <- wf2 %>% # wf2 데이터에서
  filter(!is.na(income)) %>% # 월급 결측치 제외
  group_by(age,sex) %>% #나이별 성별
  summarise(mean_income=mean(income)) # 월급 평균
  
      age sex    mean_income
   <dbl> <chr>        <dbl>
 1    20 female        147.
 2    20 male           69 
 3    21 female        107.
 4    21 male          102.
 5    22 female        140.
 6    22 male          118.
 7    23 female        139.
 8    23 male          153.
 9    24 female        126.
10    24 male          158.
# ... with 124 more rows

그래프로 만들어줍시다.

선형은 aes 파라미터가 col 이 들어와야되고 막대는 fill 입니다 

ggplot(data=sex_age,aes(x=age,y=mean_income,col=sex))+geom_line()

직업별 월급 차이 분석

어떤 직업이 월급을 많이 받는지 분석해보겠습니다. 

먼저 welfare에 있는 code_job 은 직업변수입니다.

class(welfare$code_job)
# [1] "numeric"
table(welfare$code_job)
 111  120  131  132  133  134  135  139  141  149  151  152  153  159  211  212  213 
   2   16   10   11    9    3    7   10   35   20   26   18   15   16    8    4    3 
 221  222  223  224  231  232  233  234  235  236  237  239  241  242  243  244  245 
  17   31   12    4   41    5    3    6   48   14    2   29   12    4   63    4   33 
 246  247  248  251  252  253  254  259  261  271  272  273  274  281  283  284  285 
  59   77   38   14  111   24   67  109    4   15   11    4   36   17    8   10   26 
 286  289  311  312  313  314  320  330  391  392  399  411  412  421  422  423  429 
  16    5  140  260  220   84   75   15    4   13   87   47   12  124   71    5   14 
 431  432  441  442  510  521  522  530  611  612  613  620  630  710  721  722  730 
  20   33  154  197  192  353    5  106 1320   11   40    2   20   29   30   22   16 
 741  742  743  751  752  753  761  762  771  772  773  774  780  791  792  799  811 
  27    3   34   34    5   49   69   27   11   61   86    7   17    5   21   45   16 
 812  819  821  822  823  831  832  841  842  843  851  852  853  854  855  861  862 
   1    6    9    9   23    5   17   32   10    4   19   13    7   33    9    3   14 
 863  864  871  873  874  875  876  881  882  891  892  899  910  921  922  930  941 
  17   31    2  257   34   37    2    2    3    8   19   16  102   31   74  289  325 
 942  951  952  953  991  992  999 1011 1012 
  99  125  122   73   45   12  141    2   17 

직업 변수에는 직업 코드로 분류 되어있어서 무슨 직업인지 알수없으므로 직업 분류코드를 이용해 직업 명칭을 만들어줘야 합니다.

 

글 상단에 있는 깃허브 링크에서 Koweps_Codebook.xlsx 를 다운받아서 불러옵니다.

엑셀 시트 두번째에 직종코드 시트가 직업분류 코드입니다.

엑셀 파일을 불러와야 하므로 readxl 패키지를 부르고 첫행에 컬럼명이 존재하므로 col_names를 추가해줍니다

 

library(readxl)

list_job <- read_excel("Koweps_Codebook.xlsx",col_names = T,sheet = 2)
head(list_job)

# A tibble: 6 x 2
  code_job job                                
     <dbl> <chr>                              
1      111 의회의원 고위공무원 및 공공단체임원
2      112 기업고위임원                       
3      120 행정 및 경영지원 관리자            
4      131 연구 교육 및 법률 관련 관리자      
5      132 보험 및 금융 관리자                
6      133 보건 및 사회복지 관련 관리자

left_join()으로 job 변수를 welfare 데이터와 결합하는데 공통으로 들어있는 code_job 변수를 기준으로 하면됩니다.

welfare <- left_join(welfare,list_job,id="code_job")

# 확인 작업
welfare %>% filter(!is.na(code_job)) %>% 
  select(code_job,job) %>% head(5)
  

#실행 결과
  code_job                                job
1      942                   경비원 및 검표원
2      762                             전기공
3      530 방문 노점 및 통신 판매 관련 종사자
4      999        기타 서비스관련 단순 종사원
5      312                    경영관련 사무원

이번에 직업별 월급 차이를 분석해 보겠습니다 .

우선 직업별 월급의 평균을 구합니다.

job_income <- welfare %>% filter(!is.na(job) & !is.na(income)) %>% # 직업이 없는경우 월급이 없는경우 제외
  group_by(job) %>% #직업별
  summarise(mean_income = mean(income)) # 월급 평균
  
  # A tibble: 142 x 2
   job                                mean_income
   <chr>                                    <dbl>
 1 가사 및 육아 도우미                       80.2
 2 간호사                                   241. 
 3 건설 및 광업 단순 종사원                 190. 
 4 건설 및 채굴 기계운전원                  358. 
 5 건설 전기 및 생산 관련 관리자            536. 
 6 건설관련 기능 종사자                     247. 
 7 건설구조관련 기능 종사자                 242. 
 8 건축 및 토목 공학 기술자 및 시험원       378. 
 9 건축마감관련 기능 종사자                 254. 
10 경비원 및 검표원                         134. 
# ... with 132 more rows

어떤 직업이 월급이 많은지 알아보기 위해 내림차순으로 상위 10개를 확인하겠습니다.

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

# A tibble: 10 x 2
   job                                  mean_income
   <chr>                                      <dbl>
 1 금속 재료 공학 기술자 및 시험원             845.
 2 의료진료 전문가                             844.
 3 의회의원 고위공무원 및 공공단체임원         750 
 4 보험 및 금융 관리자                         726.
 5 제관원 및 판금원                            572.
 6 행정 및 경영지원 관리자                     564.
 7 문화 예술 디자인 및 영상 관련 관리자        557.
 8 연구 교육 및 법률 관련 관리자               550.
 9 건설 전기 및 생산 관련 관리자               536.
10 석유 및 화학물 가공장치 조작원              532.

이제 위에서 만든 표를 가지고 그래프를 생성해줍니다. x축에 직업이름이 길어서 기본적으로 생성하게되면

이름이 겹치게 되서 보기 힘듭니다. coord_flip()을 추가해서 90도를 회전해줍니다.

ggplot(data=job_income_desc,aes(x=reorder(job,mean_income),y=mean_income))+
  geom_col()+coord_flip()

 

coord_flip() 속성을 주지 않았을시 x축 이름을 알아보기가 어려움

이번에는 하위도 확인해 보겠습니다.

job_income_asc <- job_income %>%
  arrange(mean_income) %>%
  head(10)
  
  # A tibble: 10 x 2
   job                          mean_income
   <chr>                              <dbl>
 1 가사 및 육아 도우미                 80.2
 2 임업관련 종사자                     83.3
 3 기타 서비스관련 단순 종사원         88.2
 4 청소원 및 환경 미화원               88.8
 5 약사 및 한약사                      89  
 6 작물재배 종사자                     92  
 7 농립어업관련 단순 종사원           102. 
 8 의료 복지 관련 서비스 종사자       104. 
 9 음식관련 단순 종사원               108. 
10 판매관련 단순 종사원               117.

마찬가지로 그래프로 확인해줍니다 

ggplot(data=job_income_asc,aes(x=reorder(job,-mean_income),y=mean_income))+
  geom_col()+coord_flip()

그래프 생성시 한가지 헷갈릴수 있는데 데이터가 정렬되어있어도 그래프는 정렬이 되어있지 않습니다.

그러므로 그래프 생성시 정렬 옵션 reorder() 를 해주어야합니다.

 

성별 직업 빈도 구하기

성별,직업 변수 전처리 작업은 위에서 완료했으므로 변수간의 관계를 분석합니다.

성별 월급 평균표와 그래프 만들기 작업

 

남성의 직업 빈도를 구해 가장 높은것 10개 추출후에 그래프를 작성해보겠습니다.

job_male <- welfare %>% # welfare 데이터에서
  filter(!is.na(job)& sex == "male") %>% #직업에 결측치가 아닌것과 남성인것
  group_by(job) %>% # 직업별
  summarise(n=n()) %>% #개수
  arrange(desc(n)) %>% # 내림차순
  head(10)
  
  # A tibble: 10 x 2
   job                          n
   <chr>                    <int>
 1 작물재배 종사자            640
 2 자동차 운전원              251
 3 경영관련 사무원            213
 4 영업 종사자                141
 5 매장 판매 종사자           132
 6 제조관련 단순 종사원       104
 7 청소원 및 환경 미화원       97
 8 건설 및 광업 단순 종사원    95
 9 경비원 및 검표원            95
10 행정 사무원                 92

그래프 작업

ggplot(data=job_male,aes(x=reorder(job,n),y=n)) + geom_col()+
  coord_flip()

geom_col()과 geom_bar() 는 아직도 헷갈린다.  아래의 링크를 참고해보자..

 

 

R08_ggplot2를 이용한 여러가지 그래프

Goals geom_col( ), reorder, xlab, ylab, geom_bar ggplot2 : cheat sheet, geom_col vs geom_bar 빈도수 순서로 출력 선 그래프, boxplot , 하나의 차트에서 여러 개의 boxplot 만들기 ggthemes #ggplot2.tidyv..

morningcoding.tistory.com

이번엔 여성의 직업 빈도를 구해봅시다. 남성에서 약간만 수정해주면 됩니다.

job_female <- welfare %>% # welfare 데이터에서
  filter(!is.na(job)& sex == "female") %>% #직업에 결측치가 아닌것과 남성인것
  group_by(job) %>% # 직업별
  summarise(n=n()) %>% #개수
  arrange(desc(n)) %>% # 내림차순
  head(10)
  
     job                              n
   <chr>                        <int>
 1 작물재배 종사자                680
 2 청소원 및 환경 미화원          228
 3 매장 판매 종사자               221
 4 제조관련 단순 종사원           185
 5 회계 및 경리 사무원            176
 6 음식서비스 종사자              149
 7 주방장 및 조리사               126
 8 가사 및 육아 도우미            125
 9 의료 복지 관련 서비스 종사자   121
10 음식관련 단순 종사원           104

그래프 작업

ggplot(data=job_female,aes(x=reorder(job,n),y=n)) + geom_col()+
  coord_flip()

종교 유무에 따른 이혼율을 분석해 봅시다

가정으로 종교가 있는 사람들이 이혼을 덜 하는지 세워봅시다

먼저 종교 변수와 혼인상태의 검토와 전처리를 해줍니다.

 

class(welfare$religion)
# [1] "numeric"

table(welfare$religion)
# 1    2 
# 8047 8617 

종교 유무가 1 2 로 구분되어 있고 결측치는 없는거같습니다 .

종교 유무에 따라 문자를 부여해줍니다 종교가있는 8047명은 yes 종교가 없는 8617명은 no

# 종교 유무에 이름 부여함
welfare$religion <- ifelse(welfare$religion==1,'yes','no')

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

qplot(welfare$religion)

혼인 상태 변수의 검토와 전처리를 해줍니다.

class(welfare$marriage)
# [1] "numeric"

table(welfare$marriage)
# 0    1    2    3    4    5    6 
# 2861 8431 2117  712   84 2433   26 

혼인상태 변수에 대한 정보는 배우자 있으면 1 , 이혼시 3 그 외에는 NA 처리하겠습니다.

# 이혼 여부 변수
welfare$group_marriage <- ifelse(welfare$marriage==1,'marriage',
                                 ifelse(welfare$marriage==3,'disvorce',NA))
                                 
table(welfare$group_marriage)
# disvorce marriage 
# 712     8431 
# 
table(is.na(welfare$marriage))
# FALSE  TRUE  NA 데이터 7521개
# 9143  7521 
# 둘중 어디에도 속하지 않는 결측치 7521개

종교 유무에 따른 이혼률 표를 만들어봅시다 

경우의 수는 총 4가지가 나옵니다. [종교 O/X , 결혼 O/X ] 2가지 * 2가지 총 4가지 입니다

먼저 종교유무와 결혼상태별로 나눠서 빈도를 구하고 각 종교 유무집단의 빈도로 나눠서 비율을 구합니다.

welfare %>% filter(!is.na(group_marriage)) %>%  # 결측치 제외
  group_by(religion,group_marriage) %>% # 종교유무,결혼유무
  summarise(n=n()) %>% # 종교유무/이혼유무 / 즉 4종류를 카운트합니다
  mutate(tot_group=sum(n)) %>% # 합은 첫번째 조건 종교 유무 2종류 sum합산을 한다
  mutate(pct =round(n/tot_group*100,1)) # 소수점 첫째 자리까지 
  
  
  # Groups:   religion [2]
  religion group_marriage     n tot_group   pct
  <chr>    <chr>          <int>     <int> <dbl>
1 no       disvorce         384      4602   8.3
2 no       marriage        4218      4602  91.7
3 yes      disvorce         328      4541   7.2
4 yes      marriage        4213      4541  92.8

dplyr()의 count() 는 집단별 빈도를 구하는 함수입니다. count() 를 이용하고 비율을 구하는 mutate()를 하나로 합치면 아래와 같이 쓸수있습니다.

religion_marriage <- welfare %>% 
  filter(!is.na(group_marriage)) %>% 
  count(religion, group_marriage) %>% 
  group_by(religion) %>% 
  mutate(pct = round(n/sum(n)*100, 1))
  
   Groups:   religion [2]
  religion group_marriage     n   pct
  <chr>    <chr>          <int> <dbl>
1 no       disvorce         384   8.3
2 no       marriage        4218  91.7
3 yes      disvorce         328   7.2
4 yes      marriage        4213  92.8

 

앞에서 생성한 표에서 이혼에 해당하는 값을 가져와서 이혼율 표를 만듭니다.

r_divorce <- r_marriage %>% 
  filter(group_marriage=="divorce") %>% 
  select(religion,pct)
  
r_divorce  

  religion   pct
  <chr>    <dbl>
1 no         8.3
2 yes        7.2

그래프를 생성해 줍니다.

ggplot(data = r_divorce,aes(x=religion,y=pct)) + geom_col() # geom_col() 값

반응형

'IT 기술 > R' 카테고리의 다른 글

R언어 공부정리 [8]  (0) 2021.01.27
데이터 마이닝 R 4버전 이상 - KoNLP 설치  (0) 2021.01.26
R언어 공부 정리 [6]  (0) 2021.01.22
R언어 공부 정리 [5]  (0) 2021.01.21
R언어 공부 정리 [4]  (2) 2021.01.20
profile

대충벌레 블로그

@대충벌레

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!