[서울시 먹거리 분석 — 2] 1월 치킨 판매업종 이용 통화량 분석.2

미완성의 신
12 min readMar 26, 2019

--

지난 블로그: [서울시 먹거리 분석] — 1월 치킨 판매업종 이용 통화량 분석

이번에는 지난 블로그에 이어서 1월 치킨 판매 업종 통화량을 여러 각도로 보도록 해보자.

1. Data 확인

먼저 summary() 함수를 사용하여 Data에 대한 전반적인 확인을 해보자.

> summary(Call_chicken_01)
기준일 요일 성별 연령대 시도
Min. :20190101 금:4255 남:14498 10대 :3688 서울특별시:29850
1st Qu.:20190108 목:4655 여:15352 20대 :5695
Median :20190116 수:4670 30대 :6116
Mean :20190116 월:3493 40대 :6084
3rd Qu.:20190124 일:3896 50대 :4537
Max. :20190131 토:4142 60대이상:3730
화:4739
시군구 읍면동 업종 통화건수
강남구 : 2381 가양동 : 372 치킨:29850 Min. : 5.00
강서구 : 1916 개봉동 : 372 1st Qu.: 5.00
중구 : 1717 공릉동 : 372 Median : 5.00
영등포구: 1688 길동 : 372 Mean : 13.24
마포구 : 1552 내발산동 : 372 3rd Qu.: 14.00
서대문구: 1476 동선동2가: 372 Max. :242.00
(Other) :19120 (Other) :27618

summary를 해보니 뭔가 특이한점이 있다. 1) 날짜를 뜻하는 기준일이 뭔가 이상한점. 2) 요일이 금요일부터 시작한점. 그래서 이 Data의 형식이 어떠한지 알아 보기 위해 str() 함수를 사용해보자.

> str(Call_chicken_01)
'data.frame': 29850 obs. of 9 variables:
$ 기준일 : int 20190101 20190101 20190101 20190101 20190101 20190101 20190101 20190101 20190101 20190101 ...
$ 요일 : Factor w/ 7 levels "금","목","수",..: 7 7 7 7 7 7 7 7 7 7 ...
$ 성별 : Factor w/ 2 levels "남","여": 2 1 2 2 2 1 2 1 1 1 ...
$ 연령대 : Factor w/ 6 levels "10대","20대",..: 2 3 1 4 4 1 3 5 3 2 ...
$ 시도 : Factor w/ 1 level "서울특별시": 1 1 1 1 1 1 1 1 1 1 ...
$ 시군구 : Factor w/ 25 levels "강남구","강동구",..: 1 1 1 1 1 1 1 1 1 1 ...
$ 읍면동 : Factor w/ 234 levels "가락동","가산동",..: 49 93 46 46 180 35 180 46 117 35 ...
$ 업종 : Factor w/ 1 level "치킨": 1 1 1 1 1 1 1 1 1 1 ...
$ 통화건수: int 5 36 5 5 5 5 5 5 5 18 ...

보니 기준일은 날짜 형식이 아니라 int형식으로 되어 있고, 요일은 factor의 순서가 바뀌어 있다. 이를 바꾸어 주어야 한다.

  1. 날짜 형식으로 바꾸어 주기 위해 이를 as.character() 함수를 사용하여 문자열 형식으로 바꾸어 준 후 as.POSIXct() 함수를 사용하여 날짜 형식으로 바꾸어 주자. 이때 format 옵션이 있는데 “%Y%m%d” 옵션을 주어 주자 각각 y,m,d는 각각 년,월,일을 나타낸다.
  • 구글 키워드: 날짜형식 in r
  1. 이제 factor()함수를 사용하여 순서를 바꾸고 재 편집을 해주자.
  • 구글 키워드: factor 순서 변경 in r
Call_chicken_01$기준일 <- as.character(Call_chicken_01$기준일)
Call_chicken_01$기준일 <- as.POSIXct(Call_chicken_01$기준일, format = "%Y%m%d")
Call_chicken_01$요일 <- factor(Call_chicken_01$요일,
levels = c("월", "화", "수","목","금","토","일"))

이제 다시 확인을 해보면

> str(Call_chicken_01)
'data.frame': 29850 obs. of 9 variables:
$ 기준일 : POSIXct, format: "2019-01-01" "2019-01-01" ...
$ 요일 : Factor w/ 7 levels "월","화","수",..: 2 2 2 2 2 2 2 2 2 2 ...
$ 성별 : Factor w/ 2 levels "남","여": 2 1 2 2 2 1 2 1 1 1 ...
$ 연령대 : Factor w/ 6 levels "10대","20대",..: 2 3 1 4 4 1 3 5 3 2 ...
$ 시도 : Factor w/ 1 level "서울특별시": 1 1 1 1 1 1 1 1 1 1 ...
$ 시군구 : Factor w/ 25 levels "강남구","강동구",..: 1 1 1 1 1 1 1 1 1 1 ...
$ 읍면동 : Factor w/ 234 levels "가락동","가산동",..: 49 93 46 46 180 35 180 46 117 35 ...
$ 업종 : Factor w/ 1 level "치킨": 1 1 1 1 1 1 1 1 1 1 ...
$ 통화건수: int 5 36 5 5 5 5 5 5 5 18 ...

기준일, 요일이 원하는대로 바뀐 것을 볼 수 있다.

2. NA 값 여부 확인

Data를 원활하게 다루기 위해서 Data에 NA값이 있는지 확인 해보자. 이는 is.na()함수를 통하여 NA 여부를 TRUE/FALSE로 확인한 후, sum() 함수로 TRUE만 모두 더해서 확인 한 결과이다.

> sum(is.na(Call_chicken_01))
[1] 0

3. 어떻게 분석을 해볼까? (도메인 지식, Domain knowledge)

이제 이 Data를 다룰지 생각을 해보자. 기준일, 요일, 성별, 연령대, 시도, 시군구, 읍면동, 업종, 통화 건수 로 나뉘어져 있는데 어떻게 Insight를 도출 할까? 분석을 하기 전에 도메인 지식이 없다면 이 데이터는 단순한 숫자와 문자로 의미가 없기에 방향을 잡아 주어야 한다. 그러나 요식업계에 대해서 아주 얄팍한 지식이라도 있으니 이를 활용해서 질문을 던져 보자.

  • 요일에 따라 통화 건수가 달라질까??
  • 보통 금,토에 많이 전화를 하지 않을까?
  • 연령에 따라 통화 건수가 달라질까??
  • 10대, 20대보다는 금전적 여유가 있는 30,40대가 더 많이 전화를 하지 않을까?

간단하게나마 이렇게 방향을 잡아주고 나아가보자.

4. 분석을 위한 Data구축

이제 Data를 알맞게 분석하기 위해 Data를 조정 해보자. 요일과, 연령에 따라 통화건수가 어떻게 달라지는지 확인 하기로 했으니 이에 맞게 조정을 해주어야 한다. 먼저 쉬운 코드를 통해 확인 해보자.

첫번째는, 매우 단순하고 직관적인 코드이다. 각각 원하는 바를 직접 정해서 필터링 한거고 이는 객체가 10개나 생성 되고, 또 같이 볼 수가 없어서 좋은 방법이 아니다.

Call_chicken_01_10years <- Call_chicken_01[Call_chicken_01$연령대 == "10대",]
Call_chicken_01_20years <- Call_chicken_01[Call_chicken_01$연령대 == "20대",]
Call_chicken_01_30years <- Call_chicken_01[Call_chicken_01$연령대 == "30대",]
Call_chicken_01_40years <- Call_chicken_01[Call_chicken_01$연령대 == "40대",]
Call_chicken_01_50years <- Call_chicken_01[Call_chicken_01$연령대 == "50대",]
Call_chicken_01_60years <- Call_chicken_01[Call_chicken_01$연령대 == "60대이상",]
Call_chicken_01_Mon <- Call_chicken_01[Call_chicken_01$요일 == "월",]
Call_chicken_01_Tue <- Call_chicken_01[Call_chicken_01$요일 == "화",]
Call_chicken_01_Wed <- Call_chicken_01[Call_chicken_01$요일 == "수",]
Call_chicken_01_Thu <- Call_chicken_01[Call_chicken_01$요일 == "목",]
Call_chicken_01_Fri <- Call_chicken_01[Call_chicken_01$요일 == "금",]
Call_chicken_01_Sat <- Call_chicken_01[Call_chicken_01$요일 == "토",]
Call_chicken_01_Sun <- Call_chicken_01[Call_chicken_01$요일 == "일",]

두번째는, aggregate()함수를 사용 한다. 옵션으로는 sum 함수를 사용 하여 통화 건수를 모두 더했다. 이는 아까보다 단축되어 편해 보이진 하지만, 역시 연령별, 요일별 통화 건수를 확인 해보고 싶다.
구글 키워드: aggregate in r

> aggregate(Call_chicken_01$통화건수, 
by=list(Call_chicken_01$연령대), FUN=sum)
1 10대 26681
2 20대 65140
3 30대 95924
4 40대 122028
5 50대 56655
6 60대이상 28905
> aggregate(Call_chicken_01$통화건수,
by=list(Call_chicken_01$요일), FUN=sum)
1 월 38808
2 화 59152
3 수 55211
4 목 55768
5 금 63117
6 토 64817
7 일 58460

세번째가 포인트인데, dplyr 패키지를 사용하여 효율적으로 data를 다루는 것이다. dplyr 패키지는 이미 r에서 매우 유명한 패키지이므로 사용해보길 바란다. 먼저 패키지를 설치 하자.

# install.packages("dplyr")
library(dplyr)

group_by() 함수를 사용해 그룹화 시키고, 이중에 통화 건수를 sum 하여 만들어 준다. 그 후 data 형식을 data.frame 로 바꿔 준것이다. 각각의 연결은 %>% 함수를 사용하여 사용 하였다.
이는 모두 dplyr 패키지에서 지원하는 함수로 dplyr은 자세하게 다루어 보고 익혀 보는것이 좋을 것이다. 매우 중요!!!!!
구글 키워드: dplyr in r

data_by_days <- Call_chicken_01 %>%
group_by(요일) %>%
summarize(통화건수 = sum(통화건수)) %>% as.data.frame()

이를 확인해보면 다음과 같이 깔끔하게 나뉜것을 알 수 있다.

> data_by_days
요일 통화건수
1 월 38808
2 화 59152
3 수 55211
4 목 55768
5 금 63117
6 토 64817
7 일 58460

이제 이 기능을 좀 더 확장 해보자.

data_by_day_years <- Call_chicken_01 %>%
group_by(요일,연령대) %>%
summarize(통화건수 = sum(통화건수)) %>% as.data.frame()
> data_by_day_years
요일 연령대 통화건수
1 월 10대 3009
2 월 20대 7002
3 월 30대 9297
4 월 40대 11069
5 월 50대 5390
6 월 60대이상 3041
7 화 10대 4147
8 화 20대 10095
9 화 30대 14282
10 화 40대 17828
......

먼가 맘에 들지가 않는다 이는 group_by()에 요일, 연령대 순서로 해서 그런것 같다. 이 순서를 연령대, 요일 순서로 바꾸어 보자.

data_by_years_days <- Call_chicken_01 %>%
group_by(연령대,요일) %>%
summarize(통화건수 = sum(통화건수)) %>% as.data.frame()
> data_by_years_days
연령대 요일 통화건수
1 10대 월 3009
2 10대 화 4147
3 10대 수 4108
4 10대 목 3963
5 10대 금 4155
6 10대 토 3896
7 10대 일 3403
8 20대 월 7002
9 20대 화 10095
10 20대 수 9556
......

이제 원하는 분석을 하기 위해 깔끔하게 완성 했다. 이제 이를 통해 무엇을 알아볼까?

5. 통화 건수를 순서대로 정리 해볼까?

arrange() 함수를 사용하여 통화건수만 순서대로 정리 해보았다.

> data_by_years_days %>% arrange(통화건수)
연령대 요일 통화건수
1 10대 월 3009
2 60대이상 월 3041
3 10대 일 3403
4 10대 토 3896
5 10대 목 3963
6 10대 수 4108
7 10대 화 4147
8 10대 금 4155
9 60대이상 일 4183
10 60대이상 수 4193
......
35 30대 금 15479
36 30대 토 15959
37 40대 수 16200
38 40대 목 17162
39 40대 화 17828
40 40대 일 18362
41 40대 금 20609
42 40대 토 20798

분포를 보아 하니 40대가 가장 많이, 그리고 10대가 가장 적게 전화를 했음을 알 수 있다. 특이 40대에서 는 토,금이 가장 많이 전화를 했음을 알 수가 있다.

왜 이런 결과가 나왔을까?

이제 이 결과에 대해서 생각을 해보자.
1. 10대에 비해 40대가 금전적으로 여유가 있다.
- 그러나 이는 30대 역시 치킨을 시켜먹을만한 충분한 금전적 여유가 있으나 30대와 5천건이나 차이가 나는것이 이상하게 생각이 될 수도 있다.
2. 40대면 보통 가정을 갖고 있을수 있고, 자녀도 역시 10대 일 수 있다.
- 이러면 30대와 차이를 생각해 볼 수 있는게, 40대의 10대 자녀가 부모님을 통해 전화를 할 수가 있을 수 있다고 해석해 볼 수 있다.

이정도 까지만 해두고 다음블로그에는 1월 중국음식에 대해 알아보도록 하자. 아직까지는 쉬운 난이도로 설명하자니 분량이 많지만 점점 난이도를 높혀서 빠르게 분석을 해보자.

--

--

미완성의 신

우리 인간은 미완성의 신들이다. 뛰어난 데이터 과학자를 꿈꾸는. 책을 좋아하는. 그런 사람입니다.