역시 ggplot2는 다른 툴에 비해서 매우 뛰어난 시각화 기능을 가지고 있다. 실제 실무 사례에서도 많이 쓰일 수 있는 데이터 셋과 그래프로 구성 되어 있다.
글을 쓰고 있는 나도, 예전에 사내 주유소 시스템 만들어서 요일별, 시간 대별 주유 횟수를 그려, 그래프를 개발자에게 그려 달라고 하여, 기능을 사용하였다. 그 때 당시에는 굉장히 신기 했는데, 지금 ggplot2에서는 데이터만 있으면 아주 쉽게 이용 할 수 있다.
뉴욕 택시 데이터 셋 ggplot2 |
아래는 UCSanDiego 분석한 뉴욕 택시 자습서(New York Taxi cabs) 그래프 그리는 것이다.
이것은 쉽게 설명 하려고, 스크립트 코드를 길고 자세 하게 구성 하였다.
뉴욕 택시 자습서
이 데이터 세트는 2015년 6월에 뉴욕시 노란색 택시 데이터 셋으로, 1,200만회가 넘는 운행 기록을 가지고 있다. 전체 데이터를 사용하지 않으려는 경우 5%의 랜덤 서브 샘플 데이터가 있다. 이번에는 그것을 가지고 사용할 것이며, 개별 택시의 ID가 포함되어 있지 않으므로, 동일한 택시의 운전사의 기록을 살펴 볼 수가 없다.
아래는 5%의 샘플 셋을 사용한다.
# 뉴욕 택시 한글로 표현
library(tidyverse)
library(lubridate)
library(forcats)
library(scales)
library(rio)
library(readxl)
library(httr)
# 파일을 불러오는 path를 url 변수로 정의
url = "https://drive.google.com/u/0/uc?id=1d9Hi0eEvnlheBJsFGiavXxkwdcXzFKyT&export=download"
GET(url, write_disk(tf <- tempfile(fileext = ".xlsx")))
system.time( taxi <- read_excel(tf, 1L))
## user system elapsed
## 5.449 1.249 6.699
str(taxi)
## 'data.frame': 616247 obs. of 19 variables:
## $ VendorID : num 2 1 2 2 1 2 1 2 2 1 ...
## $ tpep_pickup_datetime : POSIXct, format: "2015-06-12 12:51:09" "2015-06-25 06:13:56" ...
## $ tpep_dropoff_datetime: POSIXct, format: "2015-06-12 13:02:49" "2015-06-25 06:36:35" ...
## $ passenger_count : num 1 1 5 1 2 1 1 4 5 1 ...
## $ trip_distance : num 1.58 5.3 4.47 0.88 3.8 1.35 0.4 0.88 2.36 2.4 ...
## $ pickup_longitude : num -74 -74 -74 -74 -74 ...
## $ pickup_latitude : num 40.8 40.8 40.7 40.7 40.7 ...
## $ RateCodeID : num 1 1 1 1 1 1 1 1 1 1 ...
## $ store_and_fwd_flag : chr "N" "N" "N" "N" ...
## $ dropoff_longitude : num -74 -73.9 -74 -74 -74 ...
## $ dropoff_latitude : num 40.8 40.8 40.8 40.7 40.7 ...
## $ payment_type : num 1 1 1 2 2 1 2 1 2 1 ...
## $ fare_amount : num 9 20 17.5 7.5 14.5 9.5 3.5 5.5 11 12 ...
## $ extra : num 0 0 0 0 0.5 0 0.5 0.5 0 0.5 ...
## $ mta_tax : num 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...
## $ tip_amount : num 1.96 4.15 2 0 0 0 0 1.36 0 1 ...
## $ tolls_amount : num 0 0 0 0 0 0 0 0 0 0 ...
## $ improvement_surcharge: num 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 ...
## $ total_amount : num 11.8 24.9 20.3 8.3 15.8 ...
위의 데이터의 성격을 보면, 택시를 승차한 시각(tpep_pickup_datetime), 택시를 하차한 시각(pep_dropoff_datetime)이 있다. 승객의 수( passenger_count) 거리 ( trip_distance) 그리고, GPS 위치 값으로 해서 승차한 위치가 있고, 가격정보가 있다. 데이터 성격으로 보았을때 누구나 이해하기 쉬운 데이터 셋으로 이루어 졌다.
🚚 데이터 전처리
taxi <- taxi %>%
mutate(weekday = wday(tpep_dropoff_datetime, label = TRUE, abbr = TRUE),
hour.trip.start = factor(hour(tpep_pickup_datetime)),
day = factor(mday(tpep_dropoff_datetime)),
trip.duration = as.numeric(difftime(tpep_dropoff_datetime,tpep_pickup_datetime,
units = "min")),
trip.speed = ifelse(trip.duration >=1, (trip_distance/60),NA),
payment_type_label = fct_recode(factor(payment_type),
"Credit Card" = "1",
"Cash" = "2",
"No Charge" = "3",
"Other" = "4"))
위 전처리에서 간단하게 기술 적으로 설명 하면 아래와 같다.
- wday : 시간 데이터를 일자로 바꾸는것
- factor : 그래프를 그리기 위해 숫자형 데이터를 범주형으로 바꾸는 것
- difftime : 택시에서 하차 한 시간과, 승차한 시간을 뺀것
- as.numeric : 시간 계산 된 것을 숫자형으로 바꾸는 것
- ifelse : 속도를 구하기 위한 최소 조건을 잡는것 1분 미만이면, 속도를 계산 하지 안흔다.
- fct_recode : 지불 방식을 factor (범주) 형태로 데이터 셋을 바꾸는 것 - 그래프를 그리기 위한 목적
숫자형은 계산을 위한 목적이고, 범주형은 그래프를 그릴 때 범주 형으로 분류 하는 목적이다.
이번 파트에서는 택시 운행 횟수와 운행 기간을 다룰 것이다.
🚚 택시 운행 횟수
# 택시 운행 회수
taxi %>%
ggplot(aes(x=day)) + geom_bar()
택시 운행 횟수 ggplot2 |
택시 결제 방법을 현금으로 필터하여 그린 것이다.
# 택시 결제 방법
taxi %>%
filter(payment_type_label =='Cash') %>%
ggplot(aes(x=day)) + geom_bar()
택시 현금 결재 ggplot2 |
카드와 현금 지불의 수를 비교하는 그래프이다.
# 현금 결재 방법과 카드 결재 방법
taxi %>%
filter(payment_type_label %in% c('Credit Card', 'Cash')) %>%
ggplot(aes(x =day, fill = payment_type_label)) +geom_bar()
일자별 카드와 현금 결재 ggplot2 |
신용카드 결재횟수가 현금 결재 횟수 보다 많다, geom_bar에 'dodge'라는 옵션을 그리면, 막대를 나란히 비교하면서 그릴 수 있다.
# 카드와 현금 결재와 비교
taxi %>%
filter(payment_type_label %in%c('Credit Card', 'Cash')) %>%
ggplot(aes(x=day, fill = payment_type_label)) + geom_bar(position = 'dodge')
일자별 운행 횟수 카드와 현금 결제 비교 |
시간대별 택시 운행 횟수를 그린 것이다. 자정이후 부터 새벽 5시까지는 점차적으로 운행 횟수가 감소 하고 있고, 운행에 대한 수요는 오후 6시부터 10까지 증가한다.
택시 시간대별 운행 횟수 |
택시 시간대별 카드와 현금 결재 비교한 그래프이다. 모든 시간대가 카드 결재가 많다.
# 시간대별 카트와 현금 결재 비교
taxi %>%
filter(payment_type_label %in% c('Credit Card', 'Cash')) %>%
ggplot(aes(x=hour.trip.start,fill = payment_type_label)) + geom_bar(position = 'dodge')
시간대별 카드와 현금 결재 비교 ggplot2 |
요일별 여행을 나눈다. 일요일하고, 월요일은 일정 하다가 화요일/수요일 변화가 있고 목/금토는 일정하다.
# week day 요일별 평균 운행 횟수
taxi %>%
group_by(day) %>%
summarise(n = n(),
wday = weekday[1]
) %>%
group_by(wday) %>%
summarise(n.trip.mean = mean(n)) %>%
ggplot(aes(x = wday, y =n.trip.mean)) +geom_bar(stat = 'identity')
요일별 택시 운행 횟수 ggplot2 |
일단위 운행 횟수에 대한 시계열 데이터 형태로 표현 하 수 있다. 여기에서 옵션 group = 1은 단순히 모든 것을 의미 한다.
# 일 단위 운행 횟수에 대한 시계열 데이터 형태로 표현 할 수 있다.
taxi %>%
count(day) %>%
ggplot(aes(x=day, y=n)) + geom_point() + geom_line(aes(group=1), linetype='dotted')
시간단위 운행 횟수 시계열 데이터 표현 방법이다. # 시간단위 운행 횟수 시계열 데이터 형태 표현
taxi %>%
count(hour.trip.start) %>%
ggplot(aes(x = hour.trip.start, n)) +
geom_point() +
geom_line(aes(group=1),linetype='dotted')
시간대별 택시 운행 횟수 ggplot2 |
카드와 현금 결재 색으로 구분해서 시계열 그래프를 그렸다. 위의 막대 그래프 보다는 확실하게 눈에 잘 띈다. 새벽과 아침시간대에는 카드와 현금 비중이 적어 보인다.
# 카드와 현금 결재 색 나누기
taxi %>%
filter(payment_type_label %in% c('Credit Card', 'Cash')) %>%
count (payment_type_label, hour.trip.start) %>%
ggplot(aes(x=hour.trip.start, y = n, color = payment_type_label, group=payment_type_label))+
geom_point() +
geom_line(linetype='dotted')
시간 대별 카드와 현금 결재 추세 ggplot2 |
🚚 택시 운행기간
# 운행 기간 히스토그램
taxi %>%
ggplot(aes(x=trip.duration)) + geom_histogram()
택시 운행기간 히스토그램 ggplot2 |
정확한 분포를 볼수 없으면, 운행 기간이 긴 것을 보고, 분포를 정하는데, 2시간 이상 운행하는 비중을 보면 0.9% 정도이다.
# 운행 기간 긴것 보기
taxi %>%
arrange(desc(trip.duration)) %>%
select(tpep_pickup_datetime,tpep_dropoff_datetime, trip.duration) %>%
slice(1:5)
## tpep_pickup_datetime tpep_dropoff_datetime trip.duration
## 1 2015-06-27 17:42:24 2015-06-30 10:53:08 3910.733
## 2 2015-06-18 22:37:26 2015-06-19 22:37:02 1439.600
## 3 2015-06-07 18:40:43 2015-06-08 18:40:08 1439.417
## 4 2015-06-27 23:47:54 2015-06-28 23:47:16 1439.367
## 5 2015-06-09 21:45:47 2015-06-10 21:45:09 1439.367
# 2시간 이상 운전하는 비중 보기
sum(taxi$trip.duration > 120) /nrow(taxi)
## [1] 0.0009330674
#0.9% 이상되는 2시간 이상 운행 하는 데이터를 빼고 히스토그램 그리기
taxi %>%
ggplot(aes(x=trip.duration)) +geom_histogram() +xlim(0,120)
택시 운행하는 기간 히스토그램 단위 분 ggplot2 |
일별 운행하는 기간을 시계열 그래프로 본다.
# 일별 운행하는 기간 중위 값 보기
taxi %>%
group_by(day) %>%
summarise(med.duration = median(trip.duration)) %>%
ggplot(aes(x= day, y=med.duration)) +
geom_point() +
geom_line(aes(group=1),linetype='dotted')
택시 일별 운행 하는 기간 ggplot2 |
여기에서 요일을 포인트를 줘서 시각적으로 분석 할 수 있다.
# 조금더 요일을 시각적으로 강조해서 보자
taxi %>%
group_by(day) %>%
summarise(med.duration = median(trip.duration),
weekday = weekday[1]) %>%
ggplot(aes(x =day, y = med.duration, group =1)) +
geom_point(aes(color = weekday), size = 5) +
geom_line(linetype = 'dotted')+
labs( x = 'Day of Month',
y = 'Median trip Duration (Mins.)',
titile ='Median Trip Duration by Day of Month')
일별 평균운행 기간 시계열 ggplot2 |
그래프에 요일 텍스트를 삽입 하여 그래프를 그린다.
# 그래프에 요일 텍스트를 넣을 수 있다.
taxi %>%
group_by(day) %>%
summarise(med.duration = median(trip.duration),
weekday = weekday[1]) %>%
ggplot(aes(x=day, y= med.duration)) + geom_text(aes(label=weekday)) +
geom_line(aes(group=1), linetype = 'dotted') +
labs( x = 'Day of Month',
y = 'Median Trip Duration (Mins.)',
title = 'Median Trip Duration by Day of Month')
요일을 텍스트를 나타냄 ggplot2 |
운행 기간의 중위수를 시간대 별로 계산하여 그래프를 그릴 수 있다.
운행 기간의 중위수를 시간대별로 계산 ggplot2 |
이 패턴이 일주일 내내 안정적으로 유지 되는가? 평일마다 관계를 정리 해 보겠다. facet_wrap형태로 데이터를 그리면 요일별로 분리되어 그래프가 그려진다. 이것은 복잡하지만 매우 유익한 것으로 아래의 명령어를 사용하면 쉽게 그릴 수 있다.
# 요일 별로 중위 수값을 볼수 있다.
taxi %>%
group_by(weekday, hour.trip.start) %>%
summarise(med.duration = median(trip.duration)) %>%
ggplot(aes(x = hour.trip.start, y = med.duration, group = weekday, color = weekday))+
geom_point(size = 3) +
geom_line(size = 0.5) +
facet_wrap(~weekday, nrow = 1)+
theme(legend.position = "none")+
scale_x_discrete(breaks = c(0, 3, 6, 9, 12, 15, 18, 21 ))
요일 시간대별 시계열 그래프 그리기 ggplot2 |
지불 유형에 따라서 2차원 facet을 이용하여 그리드 형태의 그래프를 그릴 수 있다.
#facect함수를 이용하여, 그래프를 2개의 요소로 그림을 그릴수 있다.
taxi %>%
filter(payment_type_label %in% c('Credit Card', 'Cash')) %>%
group_by(weekday, hour.trip.start, payment_type_label) %>%
summarize(med.duration = median(trip.duration)) %>%
ggplot(aes(x = hour.trip.start, y= med.duration, group = weekday, color = weekday)) +
geom_point(size = 3) +
geom_line(size = 0.5) +
facet_grid(weekday~payment_type_label) +
theme(legend.position = "none")+
scale_x_discrete(breaks = c(0, 3, 6, 9, 12, 15, 18, 21))
2차원 facet 그래프 ggplot2 |
요일 별로 facet 를 나누어 결재 유형을 나누어서 요일 시간대별 금액의 패턴을 볼수 있다.
# 각 요일별로 facet을 나누어서 카드와 현금의 금액의 패턴을 볼 수 있다.
taxi %>%
filter(payment_type_label %in% c('Credit Card', 'Cash')) %>%
group_by(weekday, hour.trip.start, payment_type_label) %>%
summarize(med.duration = median(trip.duration)) %>%
ggplot(aes(x = hour.trip.start, y= med.duration, group = payment_type_label,
color = payment_type_label, linetype = payment_type_label, shape = payment_type_label))+
geom_point(size = 2) +
geom_line(size = 0.5) +
facet_wrap(~weekday, nrow = 1) +
labs(x = 'Time of Day',
y = 'Median Trip Duration') +
scale_x_discrete(breaks = c(0,6,12,8))
각 요일별 facet을 나눈 시계열 차트 ggplot2 |
ggplot2에 위와 같이 사람 손이나 다른 툴에서는 그릴 수 없는 그래프를 아주 쉽게 그려 낼 수 있다는 것에 놀라울 뿐이다.
분석은 모델로 표현 하는 것이 모두라고 생각 하지만, 그래프로 표현하여, 분석 하는 것이 제일 좋다. 최고 의사 결정권자 대부분이 잘 정리된 그래프를 보고 의사 결정을 하지 않는가?
그리고 위의 내용은 아래의 사이트에서 가져온 것이다.
http://lab.rady.ucsd.edu/sawtooth/business_analytics_in_r/Viz1.html
댓글 없음:
댓글 쓰기