13.4 이차원 밀도 그래프
연속형 데이터를 시각화할 수 있는 방법 중의 하나가 이차원 밀도 그래프 (2D Density Plot) 입니다. ggplot2
패키지에서는 stat_density2d()
함수를 이용하여 이 그래프를 그릴 수 있습니다.
이차원 밀도 그래프 (2D Density Plot)은 2차원 커널 밀도 추정치를 구하여 이를 선으로 연결한 그래프 입니다. 우리가 일상 생활 중에 자주 쉽게 접하는 이차원 밀도 그래프로는 지도의 등고선이나 일기예보의 등압선 등이 있습니다.
13.4.1 데이터 세트
이번 절에서 사용할 데이터는 뉴욕의 기상을 1973년 5월부터 9월까지 매일 측정한 airquality
데이터 세트로 5월과 7월의 두 달의 Wind
, Temp
를 사용하겠습니다. (airquality
는 시계열 데이터이고, 이전 절에서 airquality
데이터 세트를 사용하여 ggplot2
로 (시계열 그래프를 그리는 방법)선 그래프와 시계열 그래프을 설명한 바 있으니 참고하시기 바랍니다)
먼저, airquality
데이터 세트의 데이터 구조를 살펴보겠습니다.
library(ggplot2)
# airquality 구조
str(airquality)
## 'data.frame': 153 obs. of 11 variables:
## $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ...
## $ Solar.R : int 190 118 149 313 NA NA 299 99 19 194 ...
## $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
## $ Temp : int 67 72 74 62 56 66 65 59 61 69 ...
## $ Month : Factor w/ 5 levels "5","6","7","8",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ Day : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Month.ch_temp: chr "5" "5" "5" "5" ...
## $ Day.ch_temp : chr "1" "2" "3" "4" ...
## $ Month.ch : chr "05" "05" "05" "05" ...
## $ Day.ch : chr "01" "02" "03" "04" ...
## $ Time : Date, format: "2021-05-01" "2021-05-02" ...
5월과 7월의 데이터만 선별해서 새로운 데이터 세트를 만들어 보겠습니다.
# 5월과 7월만 선택
<- subset(airquality,
airquality_May_July select = c(Month, Day, Wind, Temp),
subset = (Month %in% c(5, 7)))
head(airquality_May_July)
## Month Day Wind Temp
## 1 5 1 7.4 67
## 2 5 2 8.0 72
## 3 5 3 12.6 74
## 4 5 4 11.5 62
## 5 5 5 14.3 56
## 6 5 6 14.9 66
tail(airquality_May_July)
## Month Day Wind Temp
## 87 7 26 8.6 82
## 88 7 27 12.0 86
## 89 7 28 7.4 88
## 90 7 29 7.4 86
## 91 7 30 7.4 83
## 92 7 31 9.2 81
13.4.2 기본 2차원 밀도 그래프
13.4.2.1 기본 2차원 밀도 그래프
stat_density2d()
함수를 이용하여 Wind
와 Temp
데이터로 부터 2차원 커널 밀도 추청을 합니다. 그리고 이를 이용하여 데이터 포인트들에 대한 기본 2차원 밀도 그래프를 작성하면 다음과 같습니다.
<- ggplot(airquality_May_July,
air_basic aes(x = Wind,
y = Temp))
+
air_basic stat_density2d() +
ggtitle("기본 2차원 밀도 그래프 1")
13.4.2.2 데이터 포인트 표시하기
기본 2차원 밀도 그래프에 geom_point()
함수를 이용하여 데이터를 점으로 표시할 수 있습니다.
<- ggplot(airquality_May_July,
air_basic aes(x = Wind,
y = Temp))
+
air_basic stat_density2d() +
geom_point() +
ggtitle("기본 2차원 밀도 그래프 2")
13.4.2.3 등고선 높이 표시
한편 등고선의 높이(height)를 ..level..
을 이용하여 등고선의 색으로 다음과 같이 표현할 수도 있습니다.
+
air_basic stat_density2d(aes(colour = ..level..)) +
ggtitle("기본 2차원 밀도 그래프 : 등고선 높이 표시")
13.4.2.4 ..density..
의 이용
fill =
모수에서 ..density..
를 다음과 같이 매핑할 수 있습니다.
+
air_basic stat_density2d(aes(fill = ..density..),
geom = "raster",
contour = FALSE) +
ggtitle("기본 2차원 밀도 그래프 : ..density..의 이용 1")
alpha =
모수에서 ..density..
를 다음과 같이 매핑할 수 있습니다.
+
air_basic geom_point() +
stat_density2d(aes(alpha = ..density..),
geom = "tile",
contour = FALSE) +
ggtitle("기본 2차원 밀도 그래프 : ..density..의 이용 2")
13.4.2.5 geom_density2d_filled()
함수
geom_density2d_filled()
함수를 이용할 수도 있습니다.
+
air_basic geom_point() +
geom_density2d_filled(alpha = 0.5) +
ggtitle("기본 2차원 밀도 그래프 : geom_density2d_filled() 함수 이용")
13.4.3 월별로 모양과 색깔 구분하기
월을 나타내는 Month
변수가 정수형이기 때문에 이를 문자형 변수 Month.ch
라는 새로운 문자형 변수로 변환한 다음, 이를 사용해서 이차원 밀도 그래프를 Month.ch
별로 모양(shape =
)과 색깔(color =
)을 구분해서 그려보겠습니다.
13.4.3.1 숫자형 Month
를 문자형 Month.ch
로 변환하기
정수형인 Month
를 as.character()
함수를 이용하여 다음과 같이 문자형으로 변환시킬 수 있습니다.
# Month를 문자형 변수로 변환
<- transform(airquality_May_July,
airquality_May_July Month.ch = as.character(Month))
sapply(airquality_May_July, class)
## Month Day Wind Temp Month.ch
## "factor" "integer" "numeric" "integer" "character"
13.4.3.2 색 바꾸기
ggplot()
함수 내의 aes()
함수에 colour =
모수를 이용하여 2차원 커널 밀도 곡선과 점의 색을 바꿀 수 있습니다. 여기서는 월별로 그 모양을 바꿔야 하기 때문에 aes()
함수 내에 colour = Month.ch
를 입력해 줍니다.
<- ggplot(airquality_May_July,
air_basic1 aes(x = Wind,
y = Temp,
colour = Month.ch))
+
air_basic1 stat_density2d() +
geom_point() +
ggtitle("2차원 밀도 그래프 : 색 바꾸기")
13.4.3.3 점의 모양 바꾸기
ggplot()
함수 내의 aes()
함수에 shape =
모수를 이용하여 점의 모양을 바꿀 수 있습니다. 여기서는 월별로 그 모양을 바꿔야 하기 때문에 aes()
함수 내에 shape = Month.ch
를 입력해 줍니다.
<- ggplot(airquality_May_July,
air_basic2 aes(x = Wind,
y = Temp,
shape = Month.ch))
+
air_basic2 stat_density2d() +
geom_point() +
ggtitle("2차원 밀도 그래프 : 점의 모양 바꾸기")
13.4.3.4 점의 크기 바꾸기
ggplot()
함수 내의 geom_point()
함수에 size =
모수를 이용하여 점의 크기을 바꿀 수 있습니다. 여기서는 월별로 그 모양을 바꿔야 하기 때문에 geom_point()
함수 내에 size = 3
을 입력해 보겠습니다.
+
air_basic2 stat_density2d() +
geom_point(size = 3) +
ggtitle("2차원 밀도 그래프 : 점의 크기 바꾸기")
13.4.3.5 선의 모양 바꾸기
stat_density2d()
함수 내의 aes()
함수에 linetype = Month.ch
를 입력하여 등고선의 모양을 월 별(Month.ch
)로 달리할 수 있습니다.
+
air_basic2 stat_density2d(aes(linetype = Month.ch)) +
geom_point() +
ggtitle("2차원 밀도 그래프 : 선의 모양 바꾸기")
13.4.4 월별 레이블의 추가
범례가 있기는 하지만 사용자의 가독성을 조금 더 높여주기 위해 2차원 밀도 그래프의 5월, 7월 두 집단의 중앙 부위에 “년/월”을 annotate()
함수를 이용하여 “text
”로 레이블을 추가할 수 있습니다.
+
air_basic2 stat_density2d() +
ggtitle("2차원 밀도 그래프 : 레이블의 추가") +
annotate("text", x=11, y=65, label="1973년 5월", alpha=0.5) +
annotate("text", x=9, y= 83, label="1973년 7월", alpha=0.5)
13.4.5 등고선 효과 추가하기
그림이 조금 재미가 없네요… 등고선에 그래디언트 효과를 줘서 히트맵 형태로 표현을 해 보겠습니다.
stat_density2d()
함수 내에 aes()
함수를 이용하여 등고선 효과를 추가합니다.
그리고, scale_fill_gradient()
함수와 scale_alpha()
함수도 추가해 줍니다.
# 2차원 밀도 그래프 : 등고선 효과
+
air_basic2 stat_density2d(aes(
fill = ..level..,
alpha = ..level..),
size = 0.01,
bins = 20, # 등고선 간격 조절
geom = "polygon") +
scale_fill_gradient(low = "green", high = "red") +
scale_alpha(range = c(0, 0.5), guide = FALSE) +
ggtitle("2차원 밀도 그래프 : 등고선 효과 1") +
annotate("text", x=11, y=65, label="1973년 5월", alpha=0.5) +
annotate("text", x=9, y= 83, label="1973년 7월", alpha=0.5)
그래도 뭔가 불만이 있네요.. 등고선을 없애고 부드럽게 표현해 보겠습니다. ggplot()
함수 내의 colour = Month.ch
을 제거하고 다시 한번 더 그려보지요…
# 2차원 밀도 그래프 : 등고선 효과
+
air_basic stat_density2d(aes(fill = ..level..,
alpha = ..level..),
size = 0.01,
bins = 20, # 등고선 간격 조절
geom = "polygon") +
scale_fill_gradient(low = "green", high = "red") +
scale_alpha(range = c(0, 0.5), guide = FALSE) +
ggtitle("2차원 밀도 그래프 : 등고선 효과 2") +
annotate("text", x=11, y=65, label="1973년 5월", alpha=0.5) +
annotate("text", x=9, y= 83, label="1973년 7월", alpha=0.5)
참고로 aes()
함수 내의 bins =
는 등고선 간의 간격 갯수라고 이해하면 좋겠습니다. 간격의 갯수가 많아질수록 등고선의 간격이 좁아지겠지요…. bins
의 값을 5, 10, 15, 20, 25, 30 등으로 수정하면서 다시 그려보기 바랍니다.
13.4.6 facet_wrap()
함수 이용
한번 더 해 보지요… 이번에는 앞에서 제거한 Month.ch
변수를 facet_wrap()
함수 안에 추가해서 그림을 다시 그려보겠습니다. 그러면 5월과 7월의 지도가 따로 그려지겠지요…
# 2차원 밀도 그래프 : facet_wrap() 함수 이용
ggplot(data=airquality_May_July, aes(x=Wind, y=Temp)) +
# geom_point(size=4) +
stat_density2d(
aes(fill = ..level..,
alpha = ..level..),
size = 0.01,
bins = 20, # 등고선 간격 조절
geom = "polygon") +
scale_fill_gradient(low = "green", high = "red") +
scale_alpha(range = c(0, 0.5), guide = FALSE) +
ggtitle("2D desity plot of Wind and Tmep, at1973. May/July by Colour") +
annotate("text", x=11, y=65, label="May, 1973", alpha=1.5, color = "blue") +
annotate("text", x=9, y= 83, label="July, 1973", alpha=1.5, color = "blue") +
facet_wrap(vars(Month.ch))
연습문제
1. Cars93
데이터 세트의 Weight
(x 축)와 MPG.highwat
(y축) 데이터를 이용한 2차원 커널 밀도 그래프를 작성하시오.
library(MASS)
ggplot(Cars93,
aes(x = Weight,
y = MPG.highway)) +
stat_density2d()
2. 1.에서의 그래프를 자동차 구동방식(DriveTrain
) 별로 색을 달리하고, 각 자동차 구동방식(DriveTrain
) 별로 facet_wrap()
함수를 이용하여 2차원 커널 밀도 그래프를 작성하시오.
library(MASS)
ggplot(Cars93,
aes(x = Weight,
y = MPG.highway,
colour = DriveTrain)) +
stat_density2d() +
facet_wrap( ~ DriveTrain)