본문 바로가기

서울시 먹거리 분석

19.01 치킨집 이용 통화량 분석

반응형

이번에는 지난 블로그에 이어서 19.01월 치킨 판매 업종 통화량을 여러 방면에서 보도록 하겠습니다.


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의 순서가 바뀌어 있습니다. 이를 바꿔야 합니다.

 

날짜 형식으로 바꾸어 주기 위해 이를 as.character() 함수를 사용하여 문자열 형식으로 바꾸어 준 후 as.POSIXct() 함수를 사용하여 날짜 형식으로 바꾸어 주겠습니다. 이때, format 옵션이 있는데 “%Y%m%d” 옵션을 주기로 합니다.

각각 y,m,d는 각각 년,월,일을 뜻합니다.

  • 구글 키워드: 날짜형식 in r

이제 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를 다룰지 생각해 봅시다. 기준일, 요일, 성별, 연령대, 시도, 시군구, 읍면동, 업종, 통화 건수 로 나뉘어져 있는데 어떻게 인사이트를 도출 할지 생각해봐야합니다.

 

분석을 하기 전에 도메인 지식이 없다면 이 데이터는 단순한 숫자와 문자로 의미가 없기에 방향을 잡아야합니다. 그러나 요식업계에 대해서 조그마한 지식이라도 있으니 이를 활용해서 의문을 가져보겠습니다.

  • 요일에 따라 통화 건수가 달라질 것인지?
  • 금,토에 많이 전화를 하지 않을지?
  • 연령에 따라 통화 건수가 달라질 것인지?
  • 10대, 20대보다 금전적 여유가 있는 3,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월 중국음식에 대해 알아보도록 하겠습니다. 아직까지는 쉬운 난이도로 설명하자니 분량이 많지만 점점 난이도를 높혀서 빠르게 분석을 해보도록 하겠습니다.

반응형

'서울시 먹거리 분석' 카테고리의 다른 글

시각화 해석  (0) 2020.02.18
19.01 요식업계 통화량 시각화  (0) 2020.02.18
19.01 피자집 이용 통화량 분석  (0) 2020.02.18
19.01월 중국집 이용 통화량 분석  (0) 2020.02.17
기획하기  (0) 2020.02.15