극값 Local Maximum(Minimum) Point With R
R 을 이용한 변곡점, 극값을 찾아보면 몇몇 잘못된 포스팅이 보입니다. 국내나 국외 모두요.
이를 정리하고자 본 포스팅을 계획했습니다.
본 포스팅은 다음의 정보를 담고 있습니다.
[1] 변곡점, 극값의 정의
[2] R에서 극값 찾기, ggplot2으로 극값 그리기
이를 위해 bitcoin 데이터를 활용하겠습니다.
[1] 변곡점, 극값의 정의
변곡점과 극값의 정의는 여기서 확인이 가능합니다.
변곡점 : https://en.wikipedia.org/wiki/Inflection_point
극값 : https://en.wikipedia.org/wiki/Maxima_and_minima
결국 변곡점은 두번 미분 가능한 함수에 대해 위로 볼록에서 아래로 볼록으로 변하는 점. 또는 그 반대입니다.
f’‘=0 이며 근방에서 f’’의 부호가 바뀌면 그 점이 볼록입니다.
따.라.서. f’=0 인 점과는 무관 합니다! 그러나 포스팅에 잘못 표현된 곳이 적지 않습니다.
여담입니다만 실제로 고객이 변곡점을 단순히 변곡이 발생한 지점
변동이 있는 점
로 해석하며 오용하기도 합니다.
이런 경우 고객이 표현을 고쳐주십사 하겠지만 데이터 분석가의 경우 용어 정의
에서 재정의하여 수용하는 것이 업무를 이해하는데 도움이 됩니다.
극값은 local max-min point 이므로 미분과 무관한 값입니다. 오히려 연속성이 의미가 있죠.
미분 가능한 함수에서는 극값은 f` =0 인 점이 됩니다. 그러나 현실세계에서는 완벽한 함수는 없습니다.
어떤 데이터간의 관계가 하나의 함수로 정의될 수 없다는 말입니다.
따.라.서. 현실세계 데이터로변곡점
, 극값
을 다루기 위해서는 샘플 points가지고 smoothing 작업으로 미분 가능한 것처럼 다뤄줘야 합니다.
다음은 현재 다루고자 하는 데이터의 그래프 입니다.
library(ggplot2, verbose=F,quietly=T, warn.conflicts=F)
source(paste0(getwd(),'/../../bitcoin/config/formarkdown_config.R'))
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
res<-callBTCWON(callConnection(), "2018-10-01",NA)
res[['candleDT']]<-1:nrow(res) # index
ggplot(data=res)+ geom_point(aes(x=candleDT, y=openingPrice))
여기서 극값을 찾아야 하는데요. 극값을 찾아보도록 하겠습니다.
[2] R에서 극값 찾기. ggplot2으로 극값 그리기.
다음은 인터넷에있는 극값 찾는 방법입니다.
## 극값 찾기
localMaxima <- function(x) {
# Use -Inf instead if x is numeric (non-integer)
y <- diff(c(-.Machine$integer.max, x)) > 0L
rle(y)$lengths
y <- cumsum(rle(y)$lengths)
y <- y[seq.int(1L, length(y), 2L)]
if (x[[1]] == x[[2]]) {
y <- y[-1]
}
y
}
mm_points<-localMaxima(res$openingPrice)
mm<-data.frame(mm_points=mm_points, values=res[mm_points,]$openingPrice)
ggplot(data=res,aes(x=candleDT, y=openingPrice))+ geom_point()+
geom_point(data=mm, aes(x=mm_points, y=values), color="red")
# length(res[mm_points,]$openingPrice)
# length(mm_points)
이건 stackoverflow 에서 확인한 내용인데 이것을 극값으로 받아들이긴 쉽지 않네요. 좀 더 가다듬어야 할 것 같습니다.
이번엔 Local Ploynomial Regression Fitting 을 활용해봤습니다.
lo <- loess(data=res, formula=openingPrice~candleDT)
x<-res$candleDT
xl <- seq(min(x),max(x), (max(x) - min(x))/30000)
out = predict(lo,xl)
pre<-data.frame(x=xl,out=out)
# ggplot(data=pre,aes(x=xl, y=out))+ geom_line()
ggplot(data=res,aes(x=candleDT, y=openingPrice))+ geom_line()+
geom_line(data=pre, aes(x=xl, y=out), color="red")
위 그래프를 보면 아시겠지만 fitting 선의 민감도가 낮아보입니다. 추세정도로만 활용 가능하겠군요.
loess 의 degree 와 span 을 수정하며 찾아보죠.
lo <- loess(data=res, formula=openingPrice~candleDT, degree=2, span=0.01) #k-d tree limited by memory. ncmax= 27509
x<-res$candleDT
xl <- seq(min(x),max(x), (max(x) - min(x))/length(res$candleDT))
out = predict(lo,xl)
pre<-data.frame(x=xl,out=out)
# ggplot(data=pre,aes(x=xl, y=out))+ geom_line()
ggplot(data=res,aes(x=candleDT, y=openingPrice))+ geom_line()+
geom_line(data=pre, aes(x=xl, y=out), color="red")
실험 결과, degree=2 span=0.01 이 적당한 것 같네요.
0.0005 로 내리니 k-d tree limited by memory. ncmax= 27509
에러가 뜨는군요. 이건 나중에 알아보겠습니다.
candleDT= 20000 근처에 극대값에 정확히 닿지는 않지만 그냥 이정도로 만족해야겠군요.
다음은 위의 loess 결과값에서 극값을 찾는 방식입니다. (인터넷에서 구해옴))
(하지만 여전히 문제는 있습니다.)
infl <- c(FALSE, diff(diff(out)>0)!=0) # 직전 값과의 관계로 극값 뽑음.연속 TRUE 이다가 FALSE 나오는 지점, FALSE 나오다가 TRUE 나오는 지점
ggplot(data=res,aes(x=candleDT, y=openingPrice))+ geom_line()+
geom_point(data=res[which(infl==T),], aes(x=candleDT, y=openingPrice), color="red")
제가 원하는 극값과 상당히 유사해졌군요.
여전히 못찾는 부분에 대해서는 다시 고민해보고 잡도록 해보겠습니다.
변곡점은 다음 포스팅으로 ~.
'정리 > 데이터 분석' 카테고리의 다른 글
[R] R과 C연동 (Rcpp 패키지 사용. R 속도 개선.) (0) | 2018.11.03 |
---|---|
[R] R 초보도 할 수 있는 Selenium을 이용한 크롤링 (0) | 2018.10.25 |
[R] Bitcoin 데이터로 Envelope 와 Bollinger Band 그리기 (ggplot2) (0) | 2018.10.22 |
[R] ggplot2 그래프 겹치기. (2) | 2018.10.19 |
[R] dplyr 사용하여 초보에서 중급되기 (0) | 2018.10.18 |