티스토리 뷰

반응형

ggplot2 로 정규분포표, 확률밀도함수 그래프를 그려보기로 한다. 아래 그림은 인터넷 서핑해서 구해놓은 그래프인데, R - ggplot2 로 똑같이 구현할 예정이다. 그래프만 그리는 건 아니고, 화살표며 f(x) 같은 수식 등 다 넣어보려 한다. 

 

분포함수, 확률밀도함수

하기전에 알아야 할 몇가지 함수가 있다. dnorm, pnorm, qnorm 을 알아야 한다. 위 그래프 기준으로 우선 참고해서 이해하면 쉽다.

# x축의 값을 입력하면, 확률밀도함수의 f(x) 의 값을 리턴.
dnorm(1) # [1] 0.2419707  --> y 값을 뜻함.

# x축의 값을 입력하면, x값이하의 f(x)의 적분값(확률밀도함수의 넓이)를 리턴
pnorm(1) # [1] 0.8413447  --> x <= 1 이하인 면적, 84.13%을 뜻함.

# f(x)의 적분값(확률밀도함수의 넓이)를 입력하면, x값를 역으로 리턴
qnorm(0.8413447) # [1] 0.9999998  --> 약 x = 1 이 리턴됨.

 

정규분포표 그래프를 그려보자

위 함수가 이해가 되었다면, 확률밀도함수를 그리고, 원하는 면적에 파란색으로 색칠까지만 우선 만든다. 

library(tidyverse)

ggplot(tibble(x = c(-4,4)), aes(x)) +
  geom_area(stat = "function", fun = dnorm, fill = 4, 
            alpha = 0.5, xlim = c(qnorm(0.93),-4)) +
  geom_function(fun = dnorm, n = 1001) +
  theme_minimal()

반응형

x축에도 눈금 하나만 남기고 다 지우고, expansion 이용해서 x 축과 y 축에 있던 공백을 조정한다. 그리고 x축에 너무 붙다보니 그림이 안맞아서, my_fun 을 정의해서 y 값을 + 0.02 했다.

# 너무 x축 하고 딱 붙어있다보니 임의로 0.02 y 값을 이동했다.
my_fun = function(i){
  dnorm(i) + 0.02
}

ggplot(tibble(x = c(-4,4)), aes(x)) +
  geom_area(stat = "function", fun = my_fun, fill = 4, 
            alpha = 0.5, xlim = c(qnorm(0.93),-4)) +
  geom_function(fun = my_fun, n = 1001) +
  scale_x_continuous(breaks = qnorm(0.93), labels = "x", 
                     expand = expansion(0)) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) + 
  theme_minimal()

 

1차로 만든것도 괜찮지만, 따라해보고자한 그래프에는 수식도 있고 화살표도 있다. 더 구현해본다. labs, theme 와 annotate 를 추가해서 그래프에 대한 디자인을 하고, 여백도 좀 주고 필요한 표식과 수식도 추가한다. (화살표, 수식 등)

ggplot(tibble(x = c(-4,4)), aes(x)) +
  geom_area(stat = "function", fun = my_fun, fill = 4, 
            alpha = 0.5, xlim = c(qnorm(0.93),-4)) +
  geom_function(fun = my_fun, n = 1001) +
  scale_x_continuous(breaks = qnorm(0.93), labels = "x", 
                     expand = expansion(0)) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) + # 0.05 가 디폴트임.
  theme_minimal() +
  labs(y = "", sec.y = "") + 
  theme(axis.text.y = element_blank(),
        axis.text.x = element_text(size = 15),
        axis.title.x = element_blank(),
        axis.title.y.left = element_text(margin = margin(0, .3, 0, 0, "cm")),
        axis.title.y.right = element_text(margin = margin(0, .3, 0, 0, "cm")),
        panel.grid = element_blank(),
        axis.ticks.x = element_line(),
        axis.ticks.length.x = unit(3, "mm"),
        axis.line.x = element_line()) +
  annotate(geom = "curve", x = 2, y = 0.3, xend = 0, yend = 0.25,
           curvature = .3, arrow = arrow(length = unit(3, "mm"))) +
  annotate(geom = "text", x = 2.4, y = 0.3, label = "F(x)", size = 5) +
  annotate(geom = "text", x = -3.6, y = 0.29, label = "확률 밀도 함수",
           hjust = "left", family = "Apple SD Gothic Neo", size = 4.3) +
  annotate("segment", x = -2, xend = -0.9, 
           y = 0.29, yend = 0.29, size = 0.6, 
           arrow = arrow(angle = 30, length = unit(0.3,"cm"))) +
  annotate("segment", x = qnorm(0.93), xend = qnorm(0.93), 
           y = my_fun(qnorm(0.93)), yend = 0, size = 0.6, 
           arrow = arrow(angle = 20, ends = "both", length = unit(0.3,"cm"), type = "closed")) +
  annotate(geom = "curve", x = 3, y = 0.17, xend = qnorm(0.93), yend = 0.07, 
           curvature = -0.3, arrow = arrow(length = unit(3, "mm"))) +
  annotate(geom = "text", x = 3, y = 0.2, label = "f(x)", size = 4.5)

거의 똑같이 구현했다. 사실 ggplot 으로 더 디자인이 잘나온듯 하다. 여백주고, x 축만남기고, 한글을 표현하는 폰트를 지정하는 등 생각보다 시행착오를 많이 겪었고 오랜시간이 걸렸다. 그래도 ggplot 으로 계속 구현하다보니, 데이터를 시각화하고 디자인하는데 전혀 부족함이 없다. 그래프에 대한 대부분의 옵션을 제공하고 있는 듯하고, 몰라서 못쓰는 기능이 많다보니 더 찾아서 연습이 필요할 듯 하다.

 

ggplot2 - geom_density 밀도 그래프 그리기

ggplot2 의 geom_density 함수를 이용해서 밀도 그래프를 그려보고자 한다. 대략 아래와 같은 그래프이고, 특정값의 빈도수를 가지고 밀도를 구해 그래프를 만드는 과정이다. ggplot2 를 이용해서 아래

emflant.tistory.com

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함