Must Learning With Statistics

3. R 기본문법 2단계 본문

MustLearning with R 1편

3. R 기본문법 2단계

Doublek Park 2020. 1. 29. 20:00

Chapter3. R 기본문법 2단계

이번 장부터는 R에 데이터를 불러와, 직접 다뤄보도록 하겠습니다.
데이터 출처는 Kaggle이며, 해당 드롭박스 링크에서 받으실 수 있습니다.

링크 : https://www.dropbox.com/sh/xx1w2syi768kfu0/AACZgxgo1fcxyDMgv9U-iTz8a?dl=0

1. 연습데이터 설명

이번에 다룰 데이터는 어떤 회사의 ‘HR(Human Resource, 인사관리)’ 데이터입니다.

변수 설명

  • satisfaction_level : 직무 만족도
  • last_evaluation : 마지막 평가점수
  • number_project : 진행 프로젝트 수
  • average_monthly_hours : 월평균 근무시간
  • time_spend_company : 근속년수
  • work_accident : 사건사고 여부(0: 없음, 1: 있음, 명목형)
  • left : 이직 여부(0: 잔류, 1: 이직, 명목형)
  • promotion_last_5years: 최근 5년간 승진여부(0: 승진 x, 1: 승진, 명목형)
  • sales : 부서
  • salary : 임금 수준

2. 데이터 불러오기 및 Strings 확인

데이터 불러오기
데이터를 불러올 때는 파일이 저장되어 있는 경로를 복사한 다음, 파일경로/파일명.csv를 입력해 주시면 됩니다.

HR = read.csv('D:/Dropbox/DATA SET/HR_comma_sep.csv') # /로 경로 구분
HR = read.csv('D:\\Dropbox\\DATA SET\\HR_comma_sep.csv') # \\로 경로 구분

**
데이터 파악하기**

데이터를 불러온 다음에는 당연히 데이터가 제대로 불러와졌는지 확인을 해야합니다. 데이터를 확인하는 대표적인 명령어는 head(), str(), summary()가 있습니다. 여담으로 이중에서 제가 개인적으로 가장 많이 사용하는 명령어는 str()입니다.

  • head(), 데이터 윗부분을 출력하는 명령어
# 데이터 윗부분 띄우기
head(HR,n = 3)
  satisfaction_level last_evaluation number_project average_montly_hours
1               0.38            0.53              2                  157
2               0.80            0.86              5                  262
3               0.11            0.88              7                  272
  time_spend_company Work_accident left promotion_last_5years sales salary
1                  3             0    1                     0 sales    low
2                  6             0    1                     0 sales medium
3                  4             0    1                     0 sales medium
  • str(), 데이터의 shape, strings 파악
# 데이터 strings 파악
str(HR)
'data.frame':   14999 obs. of  10 variables:
 $ satisfaction_level   : num  0.38 0.8 0.11 0.72 0.37 0.41 0.1 0.92 0.89 0.42 ...
 $ last_evaluation      : num  0.53 0.86 0.88 0.87 0.52 0.5 0.77 0.85 1 0.53 ...
 $ number_project       : int  2 5 7 5 2 2 6 5 5 2 ...
 $ average_montly_hours : int  157 262 272 223 159 153 247 259 224 142 ...
 $ time_spend_company   : int  3 6 4 5 3 3 4 5 5 3 ...
 $ Work_accident        : int  0 0 0 0 0 0 0 0 0 0 ...
 $ left                 : int  1 1 1 1 1 1 1 1 1 1 ...
 $ promotion_last_5years: int  0 0 0 0 0 0 0 0 0 0 ...
 $ sales                : Factor w/ 10 levels "accounting","hr",..: 8 8 8 8 8 8 8 8 8 8 ...
 $ salary               : Factor w/ 3 levels "high","low","medium": 2 3 3 2 2 2 2 2 2 2 ...

여기서 중요한 것은 각 변수들이 어떤 strings를 가지는지 확인을 하는 것입니다. num, int, Factor 등 어떤 변수들이 어떤 strings로 저장이 되었는지는 R이 해당 변수를 어떻게 인식하고 있는가와 같은 의미입니다.

  • 데이터 요약해서 보기
# 요약된 데이터 살펴보기
summary(HR) # 요약된 데이터 살펴보기
 satisfaction_level last_evaluation  number_project  average_montly_hours
 Min.   :0.0900     Min.   :0.3600   Min.   :2.000   Min.   : 96.0       
 1st Qu.:0.4400     1st Qu.:0.5600   1st Qu.:3.000   1st Qu.:156.0       
 Median :0.6400     Median :0.7200   Median :4.000   Median :200.0       
 Mean   :0.6128     Mean   :0.7161   Mean   :3.803   Mean   :201.1       
 3rd Qu.:0.8200     3rd Qu.:0.8700   3rd Qu.:5.000   3rd Qu.:245.0       
 Max.   :1.0000     Max.   :1.0000   Max.   :7.000   Max.   :310.0       

 time_spend_company Work_accident         left       
 Min.   : 2.000     Min.   :0.0000   Min.   :0.0000  
 1st Qu.: 3.000     1st Qu.:0.0000   1st Qu.:0.0000  
 Median : 3.000     Median :0.0000   Median :0.0000  
 Mean   : 3.498     Mean   :0.1446   Mean   :0.2381  
 3rd Qu.: 4.000     3rd Qu.:0.0000   3rd Qu.:0.0000  
 Max.   :10.000     Max.   :1.0000   Max.   :1.0000  

 promotion_last_5years         sales         salary    
 Min.   :0.00000       sales      :4140   high  :1237  
 1st Qu.:0.00000       technical  :2720   low   :7316  
 Median :0.00000       support    :2229   medium:6446  
 Mean   :0.02127       IT         :1227                
 3rd Qu.:0.00000       product_mng: 902                
 Max.   :1.00000       marketing  : 858                
                       (Other)    :2923                

summary(DataSet)은 데이터에 포함된 모든 변수들에 대한 요약값을 보여줍니다. num 및 int는 변수의 최솟값, 최댓값, 평균, 중위수 등을 나타내고, Factor 형태는 갯수를 집계내주는 것을 확인할 수가 있습니다.

데이터 strings 변경

summary(HR$left)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.0000  0.0000  0.2381  0.0000  1.0000 

Work_accident, left, promotion_last_5years는 명목형 변수라 R에서 Factor형태로 들어와야하지만, R에서는 아직 해당 변수들을 integer로 인식하고 있습니다. 이건 원래 데이터의 특성이 아직 R에 반영이 되지 않은 것이기 때문에 strings변환을 통해 알맞게 변환을 해주어야 합니다.

HR$Work_accident=as.factor(HR$Work_accident)
HR$left=as.factor(HR$left)
HR$promotion_last_5years=as.factor(HR$promotion_last_5years)
summary(HR$left)
    0     1 
11428  3571 

left 변수가 numeric으로 되어 있을 때와 Factor로 되어 있을 때, 요약값이 다르게 표시 되는 것을 알 수 있습니다. 이렇게 분석하고자 하는 변수가 명목형, 순서형, 연속형인지 제대로 파악을 해야하는 작업은 아무리 강조해도 모자릅니다. 변수의 특성은 후에 분석 방법론을 정해주며, 잘못된 변수 척도의 이해는 잘못 된 분석의 시작이 됩니다. 변수의 척도에 대한 확인이 끝난 다음에는 변수의 분포를 직접 확인을 해보는 작업이 중요합니다.

변수의 분포확인이 중요한 이유는 다음과 같습니다.

먼저, 분석하고자 하는 변수의 분포를 보고 데이터 핸들링 방향을 설정하게 됩니다. 또한 앞으로 다루게 될 분석에서 쓰이는 선형모형들은 확률변수의 분포를 가정하고 진행하는 경우가 대부분입니다. 만약 분석하고자 하는 확률변수의 분포가 가정되어있는 분포와 같지 않다면 변환을 통해 분포를 맞추어 줘야합니다. 마지막으로 분포를 꼼꼼히 파악해야 데이터에서 인사이트를 발굴해 낼 수 있습니다. 의미 없는 분포를 가진 변수는 과감하게 버리고, 의미있는 데이터를 찾는데에 집중할 수 있는 열쇠가 됩니다.

3. 조건에 맞는 데이터 가공하기

데이터 핸들링은 분석에서 가장 중요한 부분을 차지하며, 실제 분석에 들이는 시간의 80 ~ 90%는 데이터 핸들링이 차지하는 경우가 많습니다. 먼저, 데이터 핸들링을 할 때 필수로 알아야 하는 내용에 대해 설명 드리도록 하겠습니다.
기본적으로 주어진 데이터를 Raw 데이터라고 합니다. 하지만 대부분의 경우 Raw 데이터에서 바로 모델링을 진행하는 경우는 없습니다. Raw 데이터로 분석을 진행하다, 중간에 분석이 틀어졌을 경우 다시 처음부터 시작해야하는 문제점이 존재하며, 이는 생각보다 매우 큰 시간을 소모하게 됩니다. 상황에 따라서는 데이터를 조건에 따라 뽑아야 될 때도 있고, 연속형 변수를 이산형 변수로 묶어줘야 할 때도 존재합니다. 즉, 분석하고자 하는 목적, 정보에 따라 과감하게 수정을 할 수 있는 능력이 필요합니다. 기존의 주어진 데이터에 갇혀있지 않으며, 주어진 정보를 최대한 활용할 수 있도록 데이터를 변형시키는 것, 그것이 데이터 분석가에게 가장 중요한 능력이라고 할 수 있습니다.

조건에 맞는 값 할당하기 ifelse

ifelse()는 R에서 매우 쓰임이 많은 조건 함수입니다. R에서 사용하는 방법은 엑셀에서의 쓰임과 매우 비슷합니다.

  • satisfaction_level이 0.5보다 크다면 ‘High’, 크지 않다면 ‘Low’ 부여.

ifelse(조건, TRUE,FALSE)

HR$satisfaction_level_group_1 = ifelse(HR$satisfaction_level > 0.5, 'High', 'Low')
HR$satisfaction_level_group_1 = as.factor(HR$satisfaction_level_group_1)
summary(HR$satisfaction_level_group_1)
 High   Low 
10187  4812 
  • satisfaction_level이 0.8보다 크다면 ‘High’, 0.5 ~ 0.8이면 ‘Mid’, 나머지는 ‘Low’
    조건이 추가가 되었을 경우에는 ifelse(ifelse()) 형태로 ifelse안에 ifelse문을 쓰면 됩니다.
HR$satisfaction_level_group_2 = ifelse(HR$satisfaction_level > 0.8, 'High',
                                   ifelse(HR$satisfaction_level > 0.5,'Mid','Low'))

HR$satisfaction_level_group_2 = as.factor(HR$satisfaction_level_group_2)
summary(HR$satisfaction_level_group_2)
High  Low  Mid 
4002 4812 6185 

조건에 맞는 데이터 추출하기 subset

subset() 함수는 조건에 맞는 데이터를 추출하는 명령어입니다.

subset(데이터, 추출 조건)

  • salary가 high인 직원들만 추출하여 HR_High라는 새로운 데이터 셋을 생성
HR_High = subset(HR,salary == 'high')
summary(HR_High$salary)
  high    low medium 
  1237      0      0 
  • salary가 high이면서, sales가 IT인 직원들만 추출하여 HR_High_IT 생성 (교집합)
HR_High_IT = subset(HR,salary == 'high' & sales == 'IT')
print(xtabs(~ HR_High_IT$sales + HR_High_IT$salary))
                HR_High_IT$salary
HR_High_IT$sales high low medium
     accounting     0   0      0
     hr             0   0      0
     IT            83   0      0
     management     0   0      0
     marketing      0   0      0
     product_mng    0   0      0
     RandD          0   0      0
     sales          0   0      0
     support        0   0      0
     technical      0   0      0
  • salary가 high이거나, sales가 IT인 직원들을 추출하여 HR_High_IT2 생성 (합집합)
HR_High_IT2 = subset(HR,salary == 'high' | sales == 'IT')
print(xtabs(~ HR_High_IT$sales + HR_High_IT$salary))
                HR_High_IT$salary
HR_High_IT$sales high low medium
     accounting     0   0      0
     hr             0   0      0
     IT            83   0      0
     management     0   0      0
     marketing      0   0      0
     product_mng    0   0      0
     RandD          0   0      0
     sales          0   0      0
     support        0   0      0
     technical      0   0      0

4. 조건에 맞는 집계 데이터 만들기

조건에 따라 새로운 집계된 데이터를 만드는 것은 분석할 때 매우 중요한 기법입니다. 엑셀을 사용하시는 분들이라면, 피벗테이블을 자주 만드실 겁니다. R에서는 비슷한 기능을 ‘plyr’ 패키지를 통해 만들 수가 있습니다.

패키지 설치

데이터를 편하게 집계 내기위해서는 다음의 패키지가 필요합니다.

install.packages("plyr")
library(plyr)

ddply를 활용한 집계 데이터 만들기

집계 데이터를 만드는 방법은 여러 방법이 있지만, 지금은 가장 기본적인 ddply()라는 함수를 사용해보도록 하겠습니다. 명령어의 사용방법은 다음과 같습니다.

  1. 분석할 데이터 설정
  2. 집계 기준 변수 설정
  3. 집계 값을 저장할 컬럼명 및 계산 함수 설정

ddply(데이터,집계기준, summarise, 요약 변수)

SS=ddply(HR, # 분석할 Data Set 설정
         c("sales","salary"),summarise, # 집계 기준 변수 설정
         M_SF = mean(satisfaction_level), # 컬럼명 및 계산 함수 설정
         COUNT =length(sales), 
         M_WH = round(mean(average_montly_hours),2))

명령어가 제대로 실행됐다면, SS라는 새로운 데이터가 만들어진 것을 볼 수 있습니다.

5. ggplot2 기본 시각화

ggplot2 패키지는 R, python에서 그래프를 쉽게 그릴 수 있는 패키지입니다. 처음에는 어려울 수 있지만, 그래프를 그리는 방식은 대부분 동일하기때문에 좀 그리다 보면, 원하시는 그래프를 자유자재로 그릴 수가 있습니다.

ggplot2 기본 문법구조

ggplot2를 이용해 그래프를 그리는 일은 우리가 직접 그래프를 그리는 과정과 유사합니다. 만약 손으로 그래프 그리게 되면 다음과 같은 과정을 따를 것입니다.

  1. 축을 그린다.
  2. 그래프를 그린다.
  3. 범례, 제목, 글씨 등 기타 옵션을 수정한다.

ggplot2 역시 마찬가지라고 생각하면 됩니다.

  • 축을 그린다 → ggplot(데이터명,aes(x=변수1,y=변수2)) (x축, y축을 정해준다.)
    • ggplot은 ggplot2의 시작 명령어이며, 여기서 그래프를 그릴 데이터와, 변수를 설정해 줍니다.
    • aes는 aesthetic의 약자로, 그래프에 변수를 설정해줄 때는 무조건 aes안에 들어가 있어야 합니다.
  • 그래프를 그린다
    • geom_bar( ) , 막대도표를 그리겠다.
    • geom_histogram( ) , 히스토그램을 그리겠다.
    • geom_boxplot( ), 박스플롯을 그리겠다.
    • geom_line( ), 선 그래프를 그리겠다.
  • 기타 옵션을 수정하여, 그래프를 정교하게 그린다.
    • labs( ) , 범례 제목 수정
    • ggtitle( ), 제목 수정
    • xlabs( ), ylabs( ), x축 y축 이름 수정

다음 예시에서 어떻게 그리는지 한번 보도록 하겠습니다.

library(ggplot2) # 패키지 부착
library(ggthemes)

HR$salary = factor(HR$salary,levels = c("low","medium","high"))
ggplot(HR)

ggplot(HR,aes(x = salary))

)

먼저, ggplot만 입력을 해보면, plot창에서 회색 바탕면이 생기는 것을 확인할 수 있습니다. 여기서 aes()와 함께 축설정을 해주면, x축에 변수명이 생기는 것을 확인할 수가 있습니다. 여기서 가장 중요한 것은 aes()입니다. aesthetic(미적)의 줄임말로, ggplot2에서 가장 핵심적인 역할을 수행합니다. aes의 용도는 매우 간단합니다. ggplot2에 들어갈 ’변수’들은 모두 aes()안에 들어가면 됩니다. 그 외의 값은 aes()에 설정값으로 입력될 필요가 없습니다. 다음의 예시를 보고 판단해보도록 하겠습니다.

ggplot(HR,aes(x=salary)) +  
  geom_bar()

ggplot(HR,aes(x=salary)) +  
  geom_bar(fill = 'royalblue') 

ggplot(HR,aes(x=salary)) +  
  geom_bar(aes(fill=salary)) 

)

ggplot()으로 만든 바탕색에 + geom_bar()을 해주면 바탕색 위에 막대도표가 만들어지는 것을 확인할 수가 있습니다.이제 여기서 막대도표에 색을 주고자 합니다. 막대도표에 ’royalblue’라는 색을 채워주고자 합니다. 이 경우, 간단하게 fill = ’royalblue’를 입력해주면, 막대도표가 파랑색으로 채워지는 것을 확인할 수가 있습니다. 하지만 막대 도표의 변수에 따라 색을 다르게 주고 싶을 경우, ’aes(fill = salary)’를 입력해주어야 합니다. 차이점을 아시겠나요? royalblue는 그냥 일반적인 설정값이지만, salary는 시각화 대상 데이터에 포함되어 있는 변수이기 때문에 aes() 안에 들어가야 합니다. 이러한 차이만 잘 이해하시면 ggplot2를 활용하는데 큰 문제는 없을 것입니다.

ggplot2는 이렇게 하나씩 그리고 싶은 조건들을 추가해주면서 그리면 편하게 그릴 수가 있습니다.

막대 도표(Bar plot)

  • 막대 도표 : 이산형 변수 하나를 집계 내는 그래프, 1차원

    자주 봤을 막대 도표입니다. 막대 도표는 이산형 변수를 x축으로 두고, y축은 자동으로 집계(Counting)된 값들을 표현하는 도표입니다.

library(ggplot2) # 패키지 부착
  • x축에 salary 설정, y축은 자동으로 집계된 값이 표현되기 때문에 설정을 하지 않습니다.
# 색 설정_1
ggplot(HR,aes(x=salary)) +  
  geom_bar(fill = 'royalblue') # royalblue색으로 색 채우기

# 색 설정_2
ggplot(HR,aes(x=salary)) +  
  geom_bar(aes(fill=left)) # left 값에 따라 색 채우기 

)

  • ggplot2에서는 col = , fill = 옵션을 줌으로써 그래프에 색을 더할 수가 있습니다. 점, 선과 처럼 면적이 없는 그래프는 col 옵션을 통해 색을 바꿔주며, 면적이 있는 그래프들은 fill 옵션을 통해 색을 변경해줍니다.

히스토그램(Histogram)

  • 히스토그램 : 연속형 변수 하나를 집계 내는 그래프, 1차원

    히스토그램은 연속형변수를 일정 범위로 구간을 만들어, x축으로 설정하고 y축은 집계된 값(Counting)을 나타내는 그래프입니다.

# 기본
ggplot(HR,aes(x=satisfaction_level))+
 geom_histogram()

# 구간 수정 및 색 입히기
ggplot(HR,aes(x=satisfaction_level))+
  geom_histogram(binwidth = 0.01,col='red',fill='royalblue') 

)

  • col은 테두리 색을, fill은 채워지는 색을 바꿔줍니다.

밀도그래프(Density Plot)

  • 밀도그래프 : 연속형 변수 하나를 집계 내는 그래프, 1차원

    밀도그래프는 연속형변수를 일정 범위로 구간을 만들어, x축으로 설정하고 y축은 집계된 값(percentage)을 나타내는 그래프입니다.

# 기본
ggplot(HR,aes(x=satisfaction_level))+
 geom_density()

# 색 입히기
ggplot(HR,aes(x=satisfaction_level))+
  geom_density(col='red',fill='royalblue') # col은 테두리, fill은 채우기박스플롯

)

박스플롯(Boxplot)

  • 박스플롯 : 이산형 변수에 따라 연속형 변수의 분포 차이를 표현해주는 2차원 그래프

    박스플롯은 이산형 변수와 연속형 변수를 한번에 표현하기 위한 그래프입니다. 데이터 탐색과정(EDA) 에서 매우 중요하게 쓰이는 플롯 중 하나이니, 꼭 기억해두시길 바랍니다.

# 기본
ggplot(HR,aes(x=left,y=satisfaction_level)) +
 geom_boxplot(aes(fill = left)) +
 xlab("이직여부") + ylab("만족도") + ggtitle("Boxplot") +
 labs(fill = "이직 여부")

  • alpha는 색 명도 조절 기능으로, 0 ~ 1 사이 값을 입력합니다.
# 기본에서 조금 더 추가
ggplot(HR,aes(x=left,y=satisfaction_level)) +
  geom_boxplot(aes(fill = left),alpha = I(0.4)) + 
  geom_jitter(aes(col = left),alpha = I(0.4)) + 
  xlab("이직여부") + ylab("만족도") + ggtitle("Boxplot") +
  labs(fill = "이직 여부", col = "이직 여부") 

# 기본에서 조금 더 추가에서 조금 변경
ggplot(HR,aes(x=left,y=satisfaction_level)) +
  geom_boxplot(aes(fill = salary),alpha = I(0.4),outlier.colour = 'red') +
  xlab("이직여부") + ylab("만족도") + ggtitle("Boxplot") +
  labs(fill = "임금 수준") 

)

산점도(Scatter Plot)

  • 산점도 : 두 연속형 변수의 상관관계를 표현해주는 2차원 그래프

    산점도는 분석에서 가장 활발히 쓰이는 그래프 중 하나입니다. 특히 산점도의 경우, 모델링 전에 변수들 간의 관계를 파악하는데 있어, 가장 효과적입니다.

# 기본
ggplot(HR,aes(x=average_montly_hours,y=satisfaction_level))+
  geom_point()

# 간단한 색칠로 인사이트 발굴하기
ggplot(HR,aes(x=average_montly_hours,y=satisfaction_level))+
  geom_point(aes(col = left)) + 
  labs(col = '이직 여부') + xlab("평균 근무시간") + ylab("만족도")

)

6. 연습문제

  1. HR 데이터의 행의 수, 열의 수를 구하시오.

  2. salary변수의 strings에 대해 답하시오.

  3. salary변수에 대하여 low는 1, medium은 2, high는 3의 값을 가져 서열정보를 가지게 하는 salary_New 변수를 만드시오.

  4. Salary_New 값이 2이면서 left는 1인 직원들만 뽑아 Medium_Left라는 새로운 데이터프레임을 만드시오.

  5. Medium_Left 데이터에 대해 sales변수 별로 time_spend_company의 평균을 구하여, Time_spend_Mean이라는 데이터프레임을 만드시오.

  6. Time_spend_Mean 데이터프레임을 이용하여 sales별 time_spend_company의 평균을 나타내는 막대도표를 그리시오.(stat = ‘identity’ 옵션 활용 필요)

'MustLearning with R 1편' 카테고리의 다른 글

6. R 중급문법 2단계  (0) 2020.01.29
5. R 기본문법 4단계  (2) 2020.01.29
4. R 기본문법 3단계  (0) 2020.01.29
2. R 기본문법 1단계  (2) 2020.01.29
1. R에 대한 소개  (1) 2020.01.29
Comments