hist(iris$Sepal.Width)
여기서 막대의 너비, 즉 구간의 폭을 정하는 것이 히스토그램의 모양을 결정하는 중요한 요소이다.
기본값은 “Sturges"로 지정되어 있으며 이 방법은 막대의 너비를 [log2(n) + 1]로 지정한다.
hist()의 또 다른 파라미터는 freq이다. 기본값으누 NULL이며, 히스토그램의 막대가 각 구간별 데이터의 갯수로 그려진다.
FALSE이면 구간의 확률 밀도가 그려진다.
hist(iris$Sepal.Width, freq = FALSE)
확률밀도 그래프는 그 면적의 넓이가 1인 그래프이다.
x <- hist(iris$Sepal.Width, freq = FALSE)
x
## $breaks
## [1] 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0 4.2 4.4
##
## $counts
## [1] 4 7 13 23 36 24 18 10 9 3 2 1
##
## $density
## [1] 0.13333 0.23333 0.43333 0.76667 1.20000 0.80000 0.60000 0.33333
## [9] 0.30000 0.10000 0.06667 0.03333
##
## $mids
## [1] 2.1 2.3 2.5 2.7 2.9 3.1 3.3 3.5 3.7 3.9 4.1 4.3
##
## $xname
## [1] "iris$Sepal.Width"
##
## $equidist
## [1] TRUE
##
## attr(,"class")
## [1] "histogram"
sum(x$density) * 0.2
## [1] 1
위의 코드에서 볼 수 있듯이 density의 합에 구간의 너비 0.2를 곱하면 1이 나온다.
plot(density(iris$Sepal.Width))
밀도그림과 히스토그램을 다음과 같이 합쳐서 그릴 수 있다.
hist(iris$Sepal.Width, freq = FALSE)
lines(density(iris$Sepal.Width))
밀도 그림에 rug()함수를 사용해 실제 데이터의 위치를 표시할 수 있다.
plot(density(iris$Sepal.Width))
rug(iris$Sepal.Width)
데이터가 중첩되는 곳이 있으므로 jitter를 사용해 겹쳐지지 않게 표시할 수 있다.
plot(density(iris$Sepal.Width))
rug(jitter(iris$Sepal.Width))
barplot(tapply(iris$Sepal.Width, iris$Species, mean))
Sepal.Width의 평균을 종별로 구하고 막대그림으로 그렸다.
tapply는 데이터, 그룹을 나누는 변수, 그룹에 적용할 함수를 인자로 받는다.
cut(1:10, breaks = c(0, 5, 10))
## [1] (0,5] (0,5] (0,5] (0,5] (0,5] (5,10] (5,10] (5,10] (5,10] (5,10]
## Levels: (0,5] (5,10]
1부터 10을 (0, 5](0 < x ≤ 5) 와 (5, 10](5 < x ≤ 10)으로 나누어서, 1부터 10이 어느 구간에 포함되는지를 보여준다.
cut(1:10, breaks = 3)
## [1] (0.991,4] (0.991,4] (0.991,4] (4,7] (4,7] (4,7] (4,7]
## [8] (7,10] (7,10] (7,10]
## Levels: (0.991,4] (4,7] (7,10]
1부터 10을 3개의 구간으로 나누는 예이다. 정확히는 어느 구간에 포함되는지를 표시해주는 함수이다.
이제 Sepal.Width를 10개의 구간으로 나눠보자.
cut(iris$Sepal.Width, breaks = 10)
## [1] (3.44,3.68] (2.96,3.2] (2.96,3.2] (2.96,3.2] (3.44,3.68]
## [6] (3.68,3.92] (3.2,3.44] (3.2,3.44] (2.72,2.96] (2.96,3.2]
## [11] (3.68,3.92] (3.2,3.44] (2.96,3.2] (2.96,3.2] (3.92,4.16]
## [16] (4.16,4.4] (3.68,3.92] (3.44,3.68] (3.68,3.92] (3.68,3.92]
## [21] (3.2,3.44] (3.68,3.92] (3.44,3.68] (3.2,3.44] (3.2,3.44]
## [26] (2.96,3.2] (3.2,3.44] (3.44,3.68] (3.2,3.44] (2.96,3.2]
## [31] (2.96,3.2] (3.2,3.44] (3.92,4.16] (4.16,4.4] (2.96,3.2]
## [36] (2.96,3.2] (3.44,3.68] (3.44,3.68] (2.96,3.2] (3.2,3.44]
## [41] (3.44,3.68] (2.24,2.48] (2.96,3.2] (3.44,3.68] (3.68,3.92]
## [46] (2.96,3.2] (3.68,3.92] (2.96,3.2] (3.68,3.92] (3.2,3.44]
## [51] (2.96,3.2] (2.96,3.2] (2.96,3.2] (2.24,2.48] (2.72,2.96]
## [56] (2.72,2.96] (3.2,3.44] (2.24,2.48] (2.72,2.96] (2.48,2.72]
## [61] (2,2.24] (2.96,3.2] (2,2.24] (2.72,2.96] (2.72,2.96]
## [66] (2.96,3.2] (2.96,3.2] (2.48,2.72] (2,2.24] (2.48,2.72]
## [71] (2.96,3.2] (2.72,2.96] (2.48,2.72] (2.72,2.96] (2.72,2.96]
## [76] (2.96,3.2] (2.72,2.96] (2.96,3.2] (2.72,2.96] (2.48,2.72]
## [81] (2.24,2.48] (2.24,2.48] (2.48,2.72] (2.48,2.72] (2.96,3.2]
## [86] (3.2,3.44] (2.96,3.2] (2.24,2.48] (2.96,3.2] (2.48,2.72]
## [91] (2.48,2.72] (2.96,3.2] (2.48,2.72] (2.24,2.48] (2.48,2.72]
## [96] (2.96,3.2] (2.72,2.96] (2.72,2.96] (2.48,2.72] (2.72,2.96]
## [101] (3.2,3.44] (2.48,2.72] (2.96,3.2] (2.72,2.96] (2.96,3.2]
## [106] (2.96,3.2] (2.48,2.72] (2.72,2.96] (2.48,2.72] (3.44,3.68]
## [111] (2.96,3.2] (2.48,2.72] (2.96,3.2] (2.48,2.72] (2.72,2.96]
## [116] (2.96,3.2] (2.96,3.2] (3.68,3.92] (2.48,2.72] (2,2.24]
## [121] (2.96,3.2] (2.72,2.96] (2.72,2.96] (2.48,2.72] (3.2,3.44]
## [126] (2.96,3.2] (2.72,2.96] (2.96,3.2] (2.72,2.96] (2.96,3.2]
## [131] (2.72,2.96] (3.68,3.92] (2.72,2.96] (2.72,2.96] (2.48,2.72]
## [136] (2.96,3.2] (3.2,3.44] (2.96,3.2] (2.96,3.2] (2.96,3.2]
## [141] (2.96,3.2] (2.96,3.2] (2.48,2.72] (2.96,3.2] (3.2,3.44]
## [146] (2.96,3.2] (2.48,2.72] (2.96,3.2] (3.2,3.44] (2.96,3.2]
## 10 Levels: (2,2.24] (2.24,2.48] (2.48,2.72] (2.72,2.96] ... (4.16,4.4]
나눠진 데이터를 파이 그래프로 그리려면 factor데이터는 그대로 사용할 수 없으며, 나눠진 각 구간에 몇개의 데이터가 있는지 세야한다. table()함수가 이런 목적으로 사용되며 factor값을 받아 분할표를 만든다.
table(rep(c("a", "b", "c"), 1:3))
##
## a b c
## 1 2 3
table(cut(iris$Sepal.Width, breaks = 10))
##
## (2,2.24] (2.24,2.48] (2.48,2.72] (2.72,2.96] (2.96,3.2] (3.2,3.44]
## 4 7 22 24 50 18
## (3.44,3.68] (3.68,3.92] (3.92,4.16] (4.16,4.4]
## 10 11 2 2
이 table을 이용하여 파이그래프를 그려보자.
pie(table(cut(iris$Sepal.Width, breaks = 10)))
각 구간에 포함된 데이터가 얼마인지 대충 눈으로 확인할 수 있는데 유용한 것 같다.
str(Titanic)
## table [1:4, 1:2, 1:2, 1:2] 0 0 35 0 0 0 17 0 118 154 ...
## - attr(*, "dimnames")=List of 4
## ..$ Class : chr [1:4] "1st" "2nd" "3rd" "Crew"
## ..$ Sex : chr [1:2] "Male" "Female"
## ..$ Age : chr [1:2] "Child" "Adult"
## ..$ Survived: chr [1:2] "No" "Yes"
Titanic은 table클래스의 인스턴스이다.
가장 간단한 모자이크 플롯을 그리는 방법은 데이터를 그대로 mosaicplot()에 넘기는 것이다.
Titanic
## , , Age = Child, Survived = No
##
## Sex
## Class Male Female
## 1st 0 0
## 2nd 0 0
## 3rd 35 17
## Crew 0 0
##
## , , Age = Adult, Survived = No
##
## Sex
## Class Male Female
## 1st 118 4
## 2nd 154 13
## 3rd 387 89
## Crew 670 3
##
## , , Age = Child, Survived = Yes
##
## Sex
## Class Male Female
## 1st 5 1
## 2nd 11 13
## 3rd 13 14
## Crew 0 0
##
## , , Age = Adult, Survived = Yes
##
## Sex
## Class Male Female
## 1st 57 140
## 2nd 14 80
## 3rd 75 76
## Crew 192 20
mosaicplot(Titanic, color = TRUE)
color=TRUE는 사각형에 음영을 넣어서 구분하기 쉽게 한다.
하지만 모든 조건을 나열해 그림을 그리면 오히려 개별그룹에 대한 분포를 살펴보기 불편하다. 일부 그룹에 대해서만 살펴보려면 다음과 같이 한다.
mosaicplot(~Class + Survived, data = Titanic, color = TRUE)
pairs(~Sepal.Width + Sepal.Length + Petal.Width + Petal.Length, data = iris,
col = c("red", "green", "blue")[iris$Species])
c("red”,“green”,“blue”)[iris$Species]의 작동원리는 무엇일까…?
c("red", "green", "blue")[iris$Species]
## [1] "red" "red" "red" "red" "red" "red" "red" "red"
## [9] "red" "red" "red" "red" "red" "red" "red" "red"
## [17] "red" "red" "red" "red" "red" "red" "red" "red"
## [25] "red" "red" "red" "red" "red" "red" "red" "red"
## [33] "red" "red" "red" "red" "red" "red" "red" "red"
## [41] "red" "red" "red" "red" "red" "red" "red" "red"
## [49] "red" "red" "green" "green" "green" "green" "green" "green"
## [57] "green" "green" "green" "green" "green" "green" "green" "green"
## [65] "green" "green" "green" "green" "green" "green" "green" "green"
## [73] "green" "green" "green" "green" "green" "green" "green" "green"
## [81] "green" "green" "green" "green" "green" "green" "green" "green"
## [89] "green" "green" "green" "green" "green" "green" "green" "green"
## [97] "green" "green" "green" "green" "blue" "blue" "blue" "blue"
## [105] "blue" "blue" "blue" "blue" "blue" "blue" "blue" "blue"
## [113] "blue" "blue" "blue" "blue" "blue" "blue" "blue" "blue"
## [121] "blue" "blue" "blue" "blue" "blue" "blue" "blue" "blue"
## [129] "blue" "blue" "blue" "blue" "blue" "blue" "blue" "blue"
## [137] "blue" "blue" "blue" "blue" "blue" "blue" "blue" "blue"
## [145] "blue" "blue" "blue" "blue" "blue" "blue"
outer(1:5, 1:3, "+")
## [,1] [,2] [,3]
## [1,] 2 3 4
## [2,] 3 4 5
## [3,] 4 5 6
## [4,] 5 6 7
## [5,] 6 7 8
outer(1:5, 1:3, function(x, y) {
x + y
})
## [,1] [,2] [,3]
## [1,] 2 3 4
## [2,] 3 4 5
## [3,] 4 5 6
## [4,] 5 6 7
## [5,] 6 7 8
이변량 정규분포를 그려보자. X와 Y에 대해 Z는 확률밀도인데, 다변량 정규분포의 확률밀도는 dmvnorm()으로 계산한다.
다음의 예시를 살펴보자.
x=0, y=0에 대해 x,y의 평균이 각각 0이고, 공분산행렬이 단위행렬일 때의 확률밀도를 구하는 예이다.
dmvnorm(c(x, y), mean, sigma)의 형식이다.
library(mvtnorm)
dmvnorm(c(0, 0), rep(0, 2), diag(2))
## [1] 0.1592
다음 코드는 seq(-3,3, 0.1)의 x, y축 그리드 조합에 대해 z축 값을 구한다.
x <- seq(-3, 3, 0.1)
y <- x
dmvnorm()의 평균의 기본값은 영행렬이고, 공분산 행렬의 기본값은 단위행렬이다. 따라서 다음과 같다.
f <- function(x, y) {
dmvnorm(cbind(x, y))
}
이제 투시도를 그려보자.
persp(x, y, outer(x, y, f), theta = 30, phi = 30)
theta와 phi는 그림의 기울어진 각도를 지정하는 인자이다.
contour(x, y, outer(x, y, f))