본문 바로가기
데이터 사이언스 이야기/R & SAS Programming

[R Programming] R로 하는 데이터 전처리 & 시각화 예제

by Data_to_Impact 2019. 4. 1.
반응형

 

 

 

 

 

 

데이터분석에서 가장 시간과 에너지가 많이 뺏기는 것이 생각외로 이 데이터 전처리 과정이다. 데이터사이언티스트 들은 대략 70~80%의 시간을 데이터를 가공하는데 쓰고, 나머지 시간에는 모델링을 하거나 자료 정리를 하는데 할애한다. 데이터 전처리 과정을 얼마나 효율적으로 하느냐에 따라서 다른 디테일에 할애 할 수 있는 시간이 좌우되기 때문에 전처리에 사용되는 Package와 스텝을 체화시켜야 한다. R에는 다행히 tidyverse라는 우수한 Data handling package가 있기 때문에 이 과정이 다른 언어에 비해서 편리하다. 이번 글에서는 인터넷에서 긁어온 정돈되지 않은 데이터를 정돈해서 Time-series plot을 만들어 보는 예제를 시범해 보려고 한다.

1. Package Load

## Warning: package 'ggplot2' was built under R version 3.5.2
## Warning: package 'tidyverse' was built under R version 3.5.1
## -- Attaching packages --------------------------------------------------------------------------------- tidyverse 1.2.1 --
## √ tibble  1.4.2     √ purrr   0.2.5
## √ tidyr   0.8.1     √ dplyr   0.7.5
## √ readr   1.1.1     √ stringr 1.3.1
## √ tibble  1.4.2     √ forcats 0.3.0
## -- Conflicts ------------------------------------------------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
## Warning: package 'lubridate' was built under R version 3.5.1
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date

Package는 ggplot2, tidyverse, lubridate가 사용될 것이다.

2. 파일 읽기

setwd('C:\\r_temp')
# Read raw data by using read.csv function
midwest_gas<-read.csv('midwest_gas_prices.csv',header=T,na.strings=c("",NA), stringsAsFactors = F)
head(midwest_gas)
##   Year.Month   Week.1     X   Week.2   X.1   Week.3   X.2   Week.4   X.3
## 1       <NA> End Date Value End Date Value End Date Value End Date Value
## 2   1994-Nov     <NA>  <NA>     <NA>  <NA>     <NA>  <NA> 11/28/16 1.122
## 3   1994-Dec  12/5/16 1.086 12/12/16 1.057 12/19/16 1.039 12/26/16 1.027
## 4   1995-Jan   1/2/16 1.025   1/9/16 1.046  1/16/16 1.031  1/23/16 1.054
## 5   1995-Feb   2/6/16 1.045  2/13/16  1.04  2/20/16 1.031  2/27/16 1.052
## 6   1995-Mar   3/6/16 1.053  3/13/16 1.042  3/20/16 1.048  3/27/16 1.065
##     Week.5   X.4
## 1 End Date Value
## 2     <NA>  <NA>
## 3     <NA>  <NA>
## 4  1/30/16 1.055
## 5     <NA>  <NA>
## 6     <NA>  <NA>

원 자료는 미드웨스트의 기름 가격이 기록된 csv 파일이다. head() function을 통해서 자료를 보았더니 벌써부터 속이 답답해져 온다. 우리가 원하는 그래프를 그리기 위해서는 시간별로 Stacked 된 기름 가격의 데이터가 필요한데, 지금 보이는 데이터의 경우는 년-달을 기준으로 정렬이 되어 있고, 어떤 주에는 5번째주가 없는 경우도 있기 때문에 이에 대한 고려를 해서 전처리를 해야한다. 전처리의 방법은 여러가지가 있겠지만, 내가 생각하기에 효율적이라고 생각하는 방향은 다음과 같다.

3. tidvyverse를 통한 데이터 전처리

midwest_gas<-midwest_gas %>% filter(row_number()>=2)
# Make data to have a tibble format
midwest_gas<-as_tibble(midwest_gas)
# Extract years from it's 1st column and create new variables with format as MM/DD/YYYY.
midwest_gas_step1<-midwest_gas %>%
        mutate_at(vars(starts_with('Week.')), funs(MMDD=((paste(str_sub(.,1,-3), str_sub(Year.Month,1,4), sep=""))))) %>% 
        select(Year.Month,ends_with('MMDD'), starts_with('X'))

# Print first 6 rows of data
head(midwest_gas_step1)
## # A tibble: 6 x 11
##   Year.Month Week.1_MMDD Week.2_MMDD Week.3_MMDD Week.4_MMDD Week.5_MMDD
##   <chr>      <chr>       <chr>       <chr>       <chr>       <chr>      
## 1 1994-Nov   NA1994      NA1994      NA1994      11/28/1994  NA1994     
## 2 1994-Dec   12/5/1994   12/12/1994  12/19/1994  12/26/1994  NA1994     
## 3 1995-Jan   1/2/1995    1/9/1995    1/16/1995   1/23/1995   1/30/1995  
## 4 1995-Feb   2/6/1995    2/13/1995   2/20/1995   2/27/1995   NA1995     
## 5 1995-Mar   3/6/1995    3/13/1995   3/20/1995   3/27/1995   NA1995     
## 6 1995-Apr   4/3/1995    4/10/1995   4/17/1995   4/24/1995   NA1995     
## # ... with 5 more variables: X <chr>, X.1 <chr>, X.2 <chr>, X.3 <chr>,
## #   X.4 <chr>

이 부분에서는 우선 필요없는 두 번째 행을 날렸고, as_tibble을 선언함으로서 조금 더 데이터프레임의 가독성을 좋게 만들었다. 그리고 반복적인 Column들의 이름을 기준으로 월/일/년 순으로 데이터를 포함하도록 처리하였다. 이는 후에 lubridate라는 패키지를 사용해서 날짜 데이터로 전환할때 필요한 과정이다.

4. 최종 전처리 아웃풋

# Assign # of data frame
N=5*nrow(midwest_gas_step1)
# Create empty data frame
Ohio_gas_df<-as.data.frame(matrix(,N,2))

# Define a loop for stacking data
for (i in 1:nrow(midwest_gas_step1)){
        j=5*(i-1)
           Ohio_gas_df[j+1,1]=midwest_gas_step1$Week.1_MMDD[i]
           Ohio_gas_df[j+2,1]=midwest_gas_step1$Week.2_MMDD[i]
           Ohio_gas_df[j+3,1]=midwest_gas_step1$Week.3_MMDD[i]
           Ohio_gas_df[j+4,1]=midwest_gas_step1$Week.4_MMDD[i]
           Ohio_gas_df[j+5,1]=midwest_gas_step1$Week.5_MMDD[i]
           
           Ohio_gas_df[j+1,2]=as.numeric(midwest_gas_step1$X[i])
           Ohio_gas_df[j+2,2]=as.numeric(midwest_gas_step1$X.1[i])
           Ohio_gas_df[j+3,2]=as.numeric(midwest_gas_step1$X.2[i])
           Ohio_gas_df[j+4,2]=as.numeric(midwest_gas_step1$X.3[i])
           Ohio_gas_df[j+5,2]=as.numeric(midwest_gas_step1$X.4[i])
}




# Change the date form by using mdy function from lubridate pacakge & filter NA in week 5
Ohio_gas_df<-Ohio_gas_df %>% filter(!is.na(V2)) %>% mutate(Date=mdy(V1)) %>% rename(GasPrice=V2)
Ohio_gas_df<-Ohio_gas_df<-Ohio_gas_df %>% select(Date,GasPrice)

#Final output data
head(Ohio_gas_df)
##         Date GasPrice
## 1 1994-11-28    1.122
## 2 1994-12-05    1.086
## 3 1994-12-12    1.057
## 4 1994-12-19    1.039
## 5 1994-12-26    1.027
## 6 1995-01-02    1.025

이 과정은 루프를 사용해서 위에 있던 행을 차례대로 읽어서 Column에 날짜, 가격 별로 스텍을 쌓아주는 것이다. 그 이전에 우리이미 5 주차에 대한 정보가 있을 것임을 알고 있음으로 최종 아웃풋의 행 갯수를 미리 선언해 주었다. 그리고 이렇게 쌓은 다음에 5주차에 NA가 되어 있는 정보들을 지우고 lubrdiate 패키지의 mdy function을 이용해서 날짜변수를 선언해 주었다. 데이터 프레임 이름을 왜 Midwest 에서 Ohio로 바꿧는지 모르겠지만, 최종 전처리 아웃풋은 위와 같다.

5. 마무리: 시각화


# Plot data
ggplot()+geom_line(aes(x=Date,y=GasPrice),data=Ohio_gas_df,size=1)+scale_x_date()+
		 labs(x="Time",y="Price for Unleaded Gasoline (dollas/gallon)",title="Timeplot of the Average Weekly Midwestern Gas Price 1995-2012")+
         theme_bw()
시계열 시각화

Time을 X 축으로 가격을 Y축으로 하는 Line plot을 ggplot 패키지를 통해서 시각화 해 보았다. tidyverse와 ggplot는 시각화, 자료정리에 정말 강력한 툴임으로
데이터를 다루는 사람이라면 꼭 배워야 하는 필수 툴이라고 생각을 한다.

반응형

댓글