[R] 서울시 먹거리 분석 — 2018년 CSV파일 불러오기

[R] 서울시 먹거리 분석 — 2018년 CSV파일 불러오기HSLeeBlockedUnblockFollowFollowingMay 28지금까지 2019년 1월 치킨, 중국음식, 피자업종 통화량 데이터를 분석했다.

이번에는 앞으로 남은 2019년의 요식업계 통화량 흐름을 파악하기 위하여 먼저 2018년 전체의 통화량 데이터를 파악해보자.

DataSK Data Hub에서 2018년의 치킨, 중국음식, 피자의 통화량 데이터를 다운받자.

특이점이 있다면 19년 1월의 데이터와 마찬가지로 피자의 경우만 업종 컬럼이 존재하지 않는다.

또한 치킨과 중국음식은 같은 컬럼명을 갖지만 피자의 경우는 다른 컬럼명을 갖는다.

이유를 짐작해보자면 치킨과 중국음식은 같은 13년 8월부터 데이터를 저장하였지만 피자의 경우 15년 7월부터 데이터를 저장하기 시작하였다.

그렇기 때문에 다른 양식을 사용한것으로 보인다.

Data Load이제 Data를 불러와보자.

이 Data들은 각 업종별, 월별로 저장되어 있으므로 우리가 불러와야 할 csv파일의 개수는 총 36개이다.

이 Data들을 모두 불러와 하나의 Data Frame으로 만들고자 한다.

제일 단순한 방법먼저 제일 간단한 방법을 생각해보자.

이는 이 36개의 파일을 전부 일일히 불러오는 방법이다.

chicken_01 <- read.

csv(“CALL_CHICKEN_01MONTH.

csv”)chicken_02 <- read.

csv("CALL_CHICKEN_02MONTH.

csv")chicken_03 <- read.

csv("CALL_CHICKEN_03MONTH.

csv").

파일 개수가 5개 이하라면 몰라도 36개의 파일을 이런식으로 전부 불러오려고 생각하면 너무 귀찮고 힘든 작업이다.

다른 방법을 생각해보자.

for문을 이용한 방법for문을 이용하여 36개의 data를 불러와보자.

업종이 chicken, cfood, pizza 세가지 이므로 이를 기준으로 구분하도록 하자.

또한 각 업종별로 월별로 파일이 존재하므로 for문을 두 번 사용하도록 하자.

이 때 변수지정은 assign 함수를 이용하였다.

> # food_list 생성> food_list <- c("CFOOD","CHICKEN","PIZZA")> # 경로 설정> dir <- ("/cloud/project/18years")> setwd(dir)> # 경로 내 파일 리스트 생성> file_list <- list.

files(dir)> #생성한 file list로 원하는 데이터 프레임 생성> for(j in food_list){+ food_list_index <- grep(j, file_list)+ #grep 함수를 이용하여 각 업종이 포함된 index 찾아내기+ df_name <- data.

frame()+ #찾아낸 index를 이용하여 rbind를 이용하여 업종별 데이터프레임 결합+ for(i in food_list_index){+ read_data_csv <- read.

csv(file_list[i])+ df_name <- rbind(df_name, read_data_csv)+ }+ #결합한 데이터에 변수를 지정+ assign(paste0(j,"_18"),df_name)+ }> #_18로 끝나는 변수들을 list로 묶어주기> dataframe_list <- mget(ls(pattern="_18"))그러나 이 방법에도 문제가 있는데 리스트와 시켜서 chicken, cfood, pizza 따로따로 데이터프레임으로 저장되었다.

이를 다시 합쳐줄 때 다시 컬럼명과 컬럼 순서를 고려해주어야한다.

실제로 이를 그대로 합치면 pizza가 컬럼개수와 컬럼명이 다르기 때문에 에러가 발생한다.

그리고 더 나아가서 36개가 아닌 100개, 1000개 이상의 csv 파일을 불러올 때를 대비해 더 나은 방법을 한번 알아보자.

폴더 내의 모든 csv파일을 한번에 불러오기for문보다 조금 더 효율적으로 불러오는 방법을 생각해보자.

tidyverse, fs, readr 패키지를 이용하려 한다.

이 방법은 박찬엽님의 블로그를 참고하였다.

이를 이용하여 모든 데이터를 하나의 dataframe으로 만들 수 있지만 for문에서 언급한 것과 마찬가지로 pizza 데이터의 컬럼명과 컬럼수가 다르므로 이를 처리해주어야 한다.

> #폴더명 생성> year_18_food <- "18years"> #폴더내 csv파일 리스트 불러오기> year_18_food_csv <- dir_ls(year_18_food)> #csv파일 불러오기> year_18_food_data <- year_18_food_csv %>%+ map_dfr(read_csv)Parsed with column specification:.

> #data frame으로 변경> year_18_food_data_frame <- as.

data.

frame(year_18_food_data)> #NA확인> sum(is.

na(year_18_food_data_frame))[1] 5645608NA가 이상하게 많아서 head()를 확인해보았다.

> head(year_18_food_data_frame) 기준일 요일 성별 연령대 시도 시군구 읍면동 업종 통화건수 일자 연령 발신지_시도 발신지_구 발신지_동1 20180101 월 남 10대 서울특별시 강남구 도곡동 중국집 5 NA <NA> <NA> <NA> <NA>2 20180101 월 남 10대 서울특별시 강남구 삼성동 중국집 5 NA <NA> <NA> <NA> <NA>3 20180101 월 남 20대 서울특별시 강남구 논현동 중국집 16 NA <NA> <NA> <NA> <NA>4 20180101 월 남 20대 서울특별시 강남구 삼성동 중국집 19 NA <NA> <NA> <NA> <NA>5 20180101 월 남 30대 서울특별시 강남구 개포동 중국집 5 NA <NA> <NA> <NA> <NA>6 20180101 월 남 30대 서울특별시 강남구 삼성동 중국집 64 NA <NA> <NA> <NA> <NA>역시 컬럼명이 다르기 때문에 NA가 발생한것으로 보인다.

그럼 이제 한가지를 확인해보고자 한다.

그것은 바로 pizza데이터에 존재하던 컬럼의 데이터 값이 NA이면 같은 행에 있는 chicken과 cfood에 존재하던 컬럼의 데이터 값이 반드시 존재하는가?.그리고 그 반대도 데이터 값이 반드시 존재하는가?.이를 확인해보자> #시도의 NA index와 발신지_시도dml NA가 아닌 곳의 index 확인> sum(+ which(is.

na(year_18_food_data_frame$시도)) != which(!is.

na(year_18_food_data_frame$발신지_시도)))[1] 0> #시군구의 NA index와 발신지_구의 NA가 아닌 곳의 index 확인> sum(+ which(is.

na(year_18_food_data_frame$시군구)) != which(!is.

na(year_18_food_data_frame$발신지_구)))[1] 0> #읍면동의 NA index와 발신지_동의 NA가 아닌 곳의 index 확인> sum(+ which(is.

na(year_18_food_data_frame$읍면동)) != which(!is.

na(year_18_food_data_frame$발신지_동)))[1] 0모두 0인 것을 보아 다행히 서로 반드시 존재하는 것이다.

이제 시도, 시군구, 읍면동의 NA 위치에 발신지_시도, 발신지_구, 발신지_동의 data를 입력해주자.

> #시도가 NA인 컬럼에 발신지_시도의 NA가 아닌 값의 값을 대입> year_18_food_data_frame$시도[which(is.

na(year_18_food_data_frame$시도))] <- + year_18_food_data_frame$발신지_시도[which(!is.

na(year_18_food_data_frame$발신지_시도))]> #시군구가 NA인 컬럼에 발신지_구의 NA가 아닌 값의 값을 대입> year_18_food_data_frame$시군구[which(is.

na(year_18_food_data_frame$시군구))] <- + year_18_food_data_frame$발신지_구[which(!is.

na(year_18_food_data_frame$발신지_구))]> #읍면동이 NA인 컬럼에 발신지_동의 NA가 아닌 값의 값을 대입> year_18_food_data_frame$읍면동[which(is.

na(year_18_food_data_frame$읍면동))] <- + year_18_food_data_frame$발신지_동[which(!is.

na(year_18_food_data_frame$발신지_동))]> #NA확인> sum(is.

na(year_18_food_data_frame$시도))[1] 0> sum(is.

na(year_18_food_data_frame$시군구))[1] 0> sum(is.

na(year_18_food_data_frame$읍면동))[1] 0다행히 모두 NA가 0이다.

이제 기준일과 일자, 연령대와 연령도 같은 방식으로 진행하자.

> #기준일, 일자> sum(+ which(is.

na(year_18_food_data_frame$기준일)) != which(!is.

na(year_18_food_data_frame$일자)))[1] 0> year_18_food_data_frame$기준일[which(is.

na(year_18_food_data_frame$기준일))] <- + year_18_food_data_frame$일자[which(!is.

na(year_18_food_data_frame$일자))]> sum(is.

na(year_18_food_data_frame$기준일))[1] 0> #연령대, 연령> sum(+ which(is.

na(year_18_food_data_frame$연령대)) != which(!is.

na(year_18_food_data_frame$연령)))[1] 0> year_18_food_data_frame$연령대[which(is.

na(year_18_food_data_frame$연령대))] <- + year_18_food_data_frame$연령[which(!is.

na(year_18_food_data_frame$연령))]> sum(is.

na(year_18_food_data_frame$연령대))[1] 0> str(year_18_food_data_frame)'data.

frame': 1074310 obs.

of 14 variables: $ 기준일 : num 20180101 20180101 20180101 20180101 20180101 .

$ 요일 : chr "월" "월" "월" "월" .

$ 성별 : chr "남" "남" "남" "남" .

$ 연령대 : chr "10대" "10대" "20대" "20대" .

$ 시도 : chr "서울특별시" "서울특별시" "서울특별시" "서울특별시" .

$ 시군구 : chr "강남구" "강남구" "강남구" "강남구" .

$ 읍면동 : chr "도곡동" "삼성동" "논현동" "삼성동" .

$ 업종 : chr "중국집" "중국집" "중국집" "중국집" .

$ 통화건수 : num 5 5 16 19 5 64 5 28 5 65 .

$ 일자 : num NA NA NA NA NA NA NA NA NA NA .

$ 연령 : chr NA NA NA NA .

$ 발신지_시도: chr NA NA NA NA .

$ 발신지_구 : chr NA NA NA NA .

$ 발신지_동 : chr NA NA NA NA .

이제 필요없는 컬럼들을 제거하자.

필요없는 컬럼은 열 번째 컬럼부터이다.

> year_18_food_data_frame <- year_18_food_data_frame[,1:9]> #NA확인> for(i in 1:9) {+ print(sum(is.

na(year_18_food_data_frame[,i])))+ }[1] 0[1] 0[1] 0[1] 0[1] 0[1] 0[1] 0[1] 274058[1] 0여덟번 째 컬럼에 NA가?!… pizza는 업종 데이터가 처음부터 존재하지 않았기 때문이다.

그러므로 여덜번 째 컬럼 중 NA값을 갖는 곳에 ‘피자’ 라는 값을 부여하자.

> year_18_food_data_frame$업종[which(is.

na(year_18_food_data_frame$업종))] <- "피자"이제 최종적으로 NA값을 확인해보자> sum(is.

na(year_18_food_data_frame))[1] 0마지막으로 head와 str로 대략적인 데이터를 파악해보자> head(year_18_food_data_frame) 기준일 요일 성별 연령대 시도 시군구 읍면동 업종 통화건수1 20180101 월 남 10대 서울특별시 강남구 도곡동 중국집 52 20180101 월 남 10대 서울특별시 강남구 삼성동 중국집 53 20180101 월 남 20대 서울특별시 강남구 논현동 중국집 164 20180101 월 남 20대 서울특별시 강남구 삼성동 중국집 195 20180101 월 남 30대 서울특별시 강남구 개포동 중국집 56 20180101 월 남 30대 서울특별시 강남구 삼성동 중국집 64> str(year_18_food_data_frame)'data.

frame': 1074310 obs.

of 9 variables: $ 기준일 : num 20180101 20180101 20180101 20180101 20180101 .

$ 요일 : chr "월" "월" "월" "월" .

$ 성별 : chr "남" "남" "남" "남" .

$ 연령대 : chr "10대" "10대" "20대" "20대" .

$ 시도 : chr "서울특별시" "서울특별시" "서울특별시" "서울특별시" .

$ 시군구 : chr "강남구" "강남구" "강남구" "강남구" .

$ 읍면동 : chr "도곡동" "삼성동" "논현동" "삼성동" .

$ 업종 : chr "중국집" "중국집" "중국집" "중국집" .

$ 통화건수: num 5 5 16 19 5 64 5 28 5 65 .

마무리2018년의 데이터를 가지고 여러개의 csv파일을 한번에 읽어오는 방법을 알아보았다.

확실히 코드의 길이를 보면 두 번째 방법이 더 간단하고 쉬워 보인다.

하지만 세 번째 방법을 알고 있다면 언젠가 도움이 되는 일이 있을 것이다.

다음 글에서는 19년 1월 데이터를 가지고 알아본 것 처럼 2018년 전체 데이터를 가지고 업종별 데이터를 비교하며 파악해보고자 한다.

참고 : 미완성의 신 — [서울시 먹거리 분석-8].

. More details

Leave a Reply