(X축) 시간의 흐름에 따른 (Y축) 값의 추세, 변화 분석 및 탐색을 하는데 시계열 선 그래프(time series plot, line graph)를 많이 이용합니다. 


 이번 포스팅에서는 R ggplot2 패키지로 시계열 선그래프를 그리고, 거기에 세로선을 추가하는 작업을 해보겠습니다. 


ggplot2 에서 세로선을 추가할 때 geom_vline() 함수를 사용하는데요, 이게 시계열 데이터의 경우는 as.numeric() 함수를 사용해서 시계열 데이터를 숫자형 데이터로 변환을 해주어야 에러가 안나고 제대로 세로선이 그려집니다. 


이거 몰라서 한참을 구글링하면서 애 좀 먹었습니다. ^^;


간단한 시계열 데이터를 만들어서 예를 들어보겠습니다. 




> ##======================================================

> ## adding multiple vertical lines at time-series plot using R ggplot2

> ##======================================================

> # making time series data

> dt <- c("20170609100000", "20170609100100", "20170609100200", 

+         "20170609100300", "20170609100400", "20170609100500")

> val <- c(5.2, 3.4, 3.9, 6.3, 4.7, 5.6)

> dt_val <- data.frame(dt, val)

> dt_val <- transform(dt_val, 

+                     dt = as.POSIXct(dt, 

+                                     format = '%Y%m%d%H%M%S', 

+                                     origin = "1970-01-01", 

+                                     tz = "UTC"))

> dt_val

                   dt val

1 2017-06-09 10:00:00 5.2

2 2017-06-09 10:01:00 3.4

3 2017-06-09 10:02:00 3.9

4 2017-06-09 10:03:00 6.3

5 2017-06-09 10:04:00 4.7

6 2017-06-09 10:05:00 5.6

 




R ggplot2 패키지의 geom_line() 함수를 사용해서 시계열 선그래프를 그려보겠습니다. 



> # making time series plot

> library(ggplot2)

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size=1, color = "blue") + 

+   ggtitle("Time-series plot")

 




R ggplot2로 세로선을 추가할 때는 geom_vline(xintercept = x) 함수를 추가해주면 됩니다. 하지만 xintercept 에 들어가는 값이 날짜, 시간 포맷의 데이터일 경우 아래 처럼 에러가 납니다. 



> # To add vertical line at time series plot

> # Error in Ops.POSIXt((x - from[1]), diff(from)) : '/' not defined for "POSIXt" objects

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size = 1, color = "blue") +

+   geom_vline(xintercept = dt_val$dt[3], color =  "red", linetype = 2) +

+   ggtitle("Adding vertical line at time-series plot using geom_vline()")

Error in Ops.POSIXt((x - from[1]), diff(from)) : 

  '/' not defined for "POSIXt" objects

 




R ggplot2 시계열 선그래프에 X축이 날짜, 시간 포맷의 시계열 데이터인 경우 특정 날짜/시간에 세로선을 추가하기 위해서는 as.numeric(x) 함수를 사용해서 숫자형 데이터로 포맷을 바꾸어 주어야 합니다



> # Use as.numeric() function at xintercept

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size = 1, color = "blue") +

+   geom_vline(xintercept = as.numeric(dt_val$dt[3]), color = "red", linetype = 2) + # as.numeric() transformation

+   ggtitle("Adding vertical line at time-series plot using geom_vline() and as.numeric() transformation")

 







만약 복수의 세로선을 추가하고 싶다면 아래의 예제를 참고하세요. 만약 3번째와 5번째 x변수의 날짜/시간에 세로선을 추가하고 싶다면 dataset$variable[c(3, 5)] 처럼 indexing을 해서 xintercept 에 넣어주면 됩니다. 

(세로선 2개가 그려지기는 했는데요, 하단에 빨간색으로 "HOW_BACKTRACK environmental varialbe"이라는 경고메시지가 떴습니다. -_-; )



> # adding "Multiple" vertical lines

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size = 1, color = "blue") +

+   geom_vline(xintercept = as.numeric(dt_val$dt[c(3,5)]), color = "red", linetype = 2) +

+   ggtitle("Adding multiple vertical lines at time-series plot using geom_vline()")

HOW_BACKTRACE environmental variable.


 




이번에는 세로선을 그릴 기준 날짜/시간 데이터를 다른 데이터프레임에서 가져와야 하는 경우를 예로 들어보겠습니다. 먼저 세로선의 기준이 되는 xintercept 에 들어갈 날짜/시간 정보가 들어있는 data frame 을 만들어보죠. 



> # adding multiple vertical lines with another data frame

> dt_2 <- c("20170609100150", "20170609100430")

> val_2 <- c("yes", "yes")

> dt_val_2 <- data.frame(dt_2, val_2)

> dt_val_2 <- transform(dt_val_2, 

+                       dt_2 = as.POSIXct(dt_2, 

+                                         format = '%Y%m%d%H%M%S', 

+                                         origin = "1970-01-01", 

+                                         tz = "UTC"))

> dt_val_2

                 dt_2 val_2

1 2017-06-09 10:01:50   yes

2 2017-06-09 10:04:30   yes

 




R ggplot2 시계열 선그래프를 그린 원본 데이터프레임(아래 예제에서는 dt_val)과는 다른 데이터프레임(아래 예제에서는 dt_val_2)의 날짜/시간 데이터를 사용해서 복수의 세로선을 그려보겠습니다.  두 개의 세로선이 그려지기는 했는데요, "HOW_BACKTRACE environmental variable"이라는 빨간색 경고 메시지가 떴습니다. 그런데, 예전에는 에러 메시지 뜨면서 안그려졌었는데, 블로그 쓰려고 다시 해보니 그려지기는 하는군요. ^^; 



> # time series plot with multiple vertical lines from another data frame

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size = 1, color = "blue") +

+   geom_vline(xintercept = as.numeric(dt_val_2$dt_2), color = "red", linetype = 2) +

+   ggtitle("Time-seires plot with multiple vertical line from another dataframe")

HOW_BACKTRACE environmental variable.




위의 예제처럼 했는데 혹시 Error: Aesthetics must be either length 1 or the same as the data (6): xintercept 와 같은 에러 메시지가 뜨고 그래프가 안그려진다면 아래처럼 geom_vline(data = dataframe, xintercept = ... ) 처럼 데이터를 가져오는 데이터프레임을 명시해주면 문제가 해결됩니다.  이걸 몰라서 또 한참을 고민하고, 구글링하고, 참 애먹었던 적이 있습니다. -_-;



> # time series plot with multiple vertical lines from another data frame(2)

> ggplot(dt_val, aes(x = dt, y = val)) +

+   geom_line(size = 1, color = "blue") +

+   geom_vline(data = dt_val_2, xintercept = as.numeric(dt_val_2$dt_2), color = "red", linetype = 2) +

+   ggtitle("Time-series plot with multiple vertical lines from another dataframe 2")



 



많은 도움이 되었기를 바랍니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾸욱 눌러주세요. ^^



728x90
반응형
Posted by Rfriend
,

그동안 R로 다양한 그래프를 그리는 방법을 알아보았습니다.  R로 그래프를 그렸다면, 보는 이의 가독성, 해석의 용이성을 높여주기 위해서 그래프 위에 텍스트, 가로선/세로선/대각선, 화살표, 음영 사각형, 제목 등과 같이 추가로 정보를 제공하거나 강조를 하고 싶은 부분에 주석을 달고 싶을 때가 있습니다.

 

 

- 텍스트 : annotate("text")

 

- 가로선/세로선/대각선 : geom_vline(), geom_hline(), geom_abline()

 

- 화살표 : annotate("segment", arrow=arrow()) , with grid package


- 음영 사각형 : annotate("rect")


- 제목 : ggtitle()

 

 

매번의 R 그래프/시각화 포스팅마다 주석 다는 방법을 간간이 곁들여서 소개해드리기는 했는데요, 이번 포스팅에서는 주석 다는 방법에 대해서 포괄적이고 종합적으로 정리를 해서 바로 찾아보기 편하도록 정리를 해보았습니다.

 

 

예제로 사용할 데이터는 Base Package에 내장되어 있는 iris 데이터 프레임의 Petal.Width, Petal.Length, Species 의 세개 변수를 사용하겠습니다. (iris 데이터셋은 데이터 마이닝 실습에 아주 많이 사용되는 데이터셋으로서, iris 꽃 품종 중 setosa 50개, versicolor 50개, virginica 50개를 꽃잎의 넓이와 길이를 측정해놓은 데이터셋입니다)

 

 

 

> str(iris)
'data.frame':	150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ... 

 

 

ggplot2는 별도의 설치 및 호출이 필요한 패키지이므로 아래의 절차를 먼저 실행하시기 바랍니다.

 

> install.packages("ggplot2")
Installing package into ‘C:/Users/user/Documents/R/win-library/3.2’
(as ‘lib’ is unspecified)
trying URL 'http://cran.rstudio.com/bin/windows/contrib/3.2/ggplot2_1.0.1.zip'
Content type 'application/zip' length 2676992 bytes (2.6 MB)
downloaded 2.6 MB

package ‘ggplot2’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
	C:\Users\user\AppData\Local\Temp\RtmpEfAwCj\downloaded_packages
> library(ggplot2) 

 

(1) iris의 Petal.Width를 x축으로, Petal.Length를 y축으로 하고, 품종(Species)에 따라서 색깔을 달리해서 산포도(scatter plot)을 그려보겠습니다.

 

> # scatter plot of iris dataset
> a1 <- ggplot(iris, aes(x=Petal.Width, y=Petal.Length, fill=Species)) + 
+   geom_point(colour="grey", shape=21, size=6) +
+   scale_fill_brewer(palette="Reds")
> 
> a1
 

 

 

 

 

(2) 텍스트(text) 추가 : annotate("text")

 

> # 텍스트(text) 추가 : annotate("text")
> 
> a2 <- a1 + 
+   annotate("text", x=0.25, y=2.4, label="Setosa", size=7) + # text annotation
+   annotate("text", x=1.3, y=3.3, label="Versicolor", size=7) + 
+   annotate("text", x=1.7, y=6.8, label="Virginica", size=7)
> 
> a2

 

 

 

 

 

 

(3) 선(line) 추가 : geom_vline(), geom_hline(), geom_abline()

 

> # 선(line) 추가 : geom_vline(), geom_hline(), geom_abline()
> 
> a3 <- a2 + 
+   geom_hline(yintercept=2.6, colour="grey", lty="dashed", size=1) + # horizontal line
+   geom_hline(yintercept=4.9, colour="grey", lty="dashed", size=1) + 
+ 
+   geom_vline(xintercept=0.8, colour="grey", lty="dashed", size=1) + # vertical line
+   geom_vline(xintercept=1.75, colour="grey", lty="dashed", size=1) + 
+   
+   geom_abline(intercept=8, slope=-2.1, colour="red", lty="dotted", size=1.5) # abline
>   
> a3

 

 

 

 

 

(4) 화살표(arrow) 추가 : annotate("segment")

 

단, grid 패키지를 호출해서 사용해야 합니다.

 

> # 화살표(arrow) 추가 : annotate("segment")
> library(grid) # grid 패키지 호출
> 
> a4 <- a3 + 
+   annotate("segment", x=2, xend=2.1, y=2, yend=3.5, size=1.5, colour="red", arrow=arrow())
> 
> a4
> 
> 
> # 텍스트 추가 : annotate("text")
> a5 <- a4 + 
+   annotate("text", x=2, y=1.8, size=6, colour="red", label="y=8 - 2.1x")
> 
> a5

 

 

 

 

 

 

 

(5) 음영 사각형(shadowed box) 추가 : annotate("rect")

 

> # 음영 사각형(shadowed box) 추가 : annotate("rect")
> a6 <- a5 + 
+   annotate("rect", xmin=0, xmax=0.8, ymin=0, ymax=2.6, alpha=0.1, fill="red") + 
+   annotate("rect", xmin=0.8, xmax=1.75, ymin=2.6, ymax=4.9, alpha=0.2, fill="red") + 
+   annotate("rect", xmin=1.3, xmax=2.7, ymin=4.3, ymax=7.2, alpha=0.3, fill="red")
> 
> a6

 

 

 

 

 

(6) 제목(title) 추가 : ggtitle()

 

> # 제목 추가 : ggtitle()
> 
> a7 <- a6 + 
+   ggtitle("Annotation of Text, Line, Arrow, Shadowed Box, Title")
> 
> a7

 

 

 

 

많은 도움 되었기를 바랍니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

728x90
반응형
Posted by Rfriend
,