위 함수들의 차이를 알아보기 앞서 1~100의 숫자 중 30개를 추출한 데이터를 생성하였다.
x=sample(1:100,30)
summary()와 fivenum()을 이용한 결과 값은 다음과 같다. (quantile()은 참고용으로 사용)
summary(x)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 5.00 25.75 69.00 56.93 83.50 99.00
fivenum(x)
## [1] 5 24 69 86 99
quantile(x)
## 0% 25% 50% 75% 100%
## 5.00 25.75 69.00 83.50 99.00
fivenum()은 최솟값, 제1사분위수, 중간값, 제3사분위수, 최댓값을 출력하며 summary()는 평균까지 추가적으로 출력함을 알 수 있다. 하지만 제1사분위수와 제3사분위수의 값은 다른 것을 확인할 수 있다.
y=sample(1:100,29)
summary(y)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.00 21.00 38.00 43.59 60.00 100.00
fivenum(y)
## [1] 1 21 38 60 100
데이터의 갯수가 홀수인 경우에는 위처럼 같은 값을 출력하지만 짝수인 경우에만 다른 값이 출력된다. 그 이유는 사분위수를 찾는 방법의 차이 때문이다. fivenum()함수는 간단하게 1,2,3,4라는 데이터가 주어졌다고 할 때 중간값 (2.5)을 찾은 뒤 중간값 이하의 좌측 데이터를 찾아 제1사분위수를 계산한다. 즉, 1,2를 찾을 수 있고 제1사분위수는 1,2의 중간값인 1.5가 된다. 제3분위수 또한 중간값 (2.5)이상의 데이터 3,4를 찾아 이들의 중간값인 3.5가 제3사분위수가 된다. 이때 제1사분위수를 lower hinge, 제3사분위수를 upper hinge라 한다. 이와 다르게 quantile()은 9가지의 알고리즘을 가지고 있으며 type인수를 이용하여 선택할 수 있다. type=7이 기본값으로 사용되며 summary() 또한 type=7을 이용하여 결과를 출력한다. type7의 계산법: R=(N-1)k/4+1 (N은 데이터의 수, k는 사분위수 (1분위수일 때 k=1)) 이 때 k분위수는 [R]번째 값 + (R-[R])([R+1]번째 값-[R]번째 값) 1,2,3,4라는 데이터가 주어졌다면 제1사분위수를 구해보면 R=31/4+1=1.75이고 1분위수는 1+(1.75-1)*(2-1)=1.75이다.
ToothGrowth 데이터 셋은 R 내장 데이터로 ToothGrowth라는 명령어로 불러올 수 있다. 데이터의 설명을 간략하게 하자면 비타민C의 투여량과 방법에 따른 60마리의 돼지들의 치아세포 길이 측정값들이다. head()함수와 summary()함수를 통하여 데이터와 변수를 확인했다.
head(ToothGrowth)
## len supp dose
## 1 4.2 VC 0.5
## 2 11.5 VC 0.5
## 3 7.3 VC 0.5
## 4 5.8 VC 0.5
## 5 6.4 VC 0.5
## 6 10.0 VC 0.5
summary(ToothGrowth)
## len supp dose
## Min. : 4.20 OJ:30 Min. :0.500
## 1st Qu.:13.07 VC:30 1st Qu.:0.500
## Median :19.25 Median :1.000
## Mean :18.81 Mean :1.167
## 3rd Qu.:25.27 3rd Qu.:2.000
## Max. :33.90 Max. :2.000
편의를 위해 attach()함수를 이용하여 바로 변수들을 사용할 수 있게 하였다. supp와 dose 두 변수를 시각화하기 위해 factor화하였다.
attach(ToothGrowth)
supp<-as.factor(supp)
dose<-as.factor(dose)
다음으로 치아세포의 성장에 비타민C의 투여량과 방법에 따른 차이를 boxplot으로 확인하였다.
boxplot(len~supp+dose,
xlab="Supplement type",ylab="length", main="Pigs` Tooth Growth",
notch=TRUE,col=c("red","blue"))
## Warning in bxp(list(stats = structure(c(8.2, 9.7, 12.25, 16.5, 21.5, 4.2, : some
## notches went outside hinges ('box'): maybe set notch=FALSE
legend(4,10,c("Orange juice","Ascorbic acid"),fill=c("red","blue"))
빨간 색은 Orange juice, 파란 색은 Ascorbic acid의 방법을 이용하여 투여한 자료이며 x값의 OJ는Orange juice, VC는 Ascorbic acid를 나타내며 옆의 숫자는 투여량을 의미한다. 마지막으로 y값은 치아의 길이이다. 또한, notch=TRUE로 설정하였기 때문에 각 box들이 잘록한 모양으로 나타나며 이 잘록한 구간은 중간값의 신뢰 구간이며 만약 두 notch구간이 겹치지 않는다면 두 중간값은 95%신뢰수준에서 유의미한 차이가 있다고 볼 수 있다. 몇몇 box는 이상한 모양으로 꺾여 있는 것을 볼 수 있는데 notch가 크기 때문이다. 보통 데이터 수가 적은 경우 이러한 모습이 나타난다고 한다. 먼저 투여량의 변화로 인한 치아의 길이를 비교해보고자 한다. 먼저 Ascorbic acid를 살펴보면 notch를 통해 중간값이 점점 증가하고 있으며 각 중간값의 신뢰구간이 겹치지 않는 것을 확인할 수 있다. 이를 통해 각각의 중간값이 유의미하게 다르며 투여량이 치아의 길이에 영향을 미친다고 볼 수 있다. 즉, Ascorbic acid를 통한 방법은 투여량이 늘어날수록 치아의 길이가 길어진다고 판단할 수 있다. 다음으로 Orange juice를 살펴보면 notch를 통해 투여량이 0.5에서 1로 증가하였을 때는 중간값의 신뢰구간이 겹치지 않지만 1에서 2로 증가하였을 때는 신뢰구간이 겹치는 것을 확인할 수 있다. 즉, Orange juice를 통한 방법은 투여량을 0.5에서 1로 늘렸을 경우에 한해 치아의 길이 성장에 유의미한 영향을 미치고 있다고 볼 수 있다. 마지막으로 투여 방법간 차이를 확인해보고자 한다. 투여량이 0.5와 2인 경우에는 notch가 겹치고 있는데 반해 1인 경우에는 notch가 겹치지 않고 Orange juice 치아 길이의 중간값이 높은 것을 확인할 수 있다. 결국, 투여량이 1인 경우에만 투여 방법 간의 차이가 유의미하다고 볼 수 있을 것이다.
airquality 데이터 셋은 R 내장 데이터로 airquality 라는 명령어로 불러올 수 있다. 데이터의 설명을 간략하게 하자면 뉴욕의 공기질을 측정한 자료이다. Ozone변수에 몇몇 NA값이 존재하였으나 작업을 수행하는데 지장이 없다 생각하여 그대로 진행하였다. 편의를 위해 attach()함수를 이용하여 바로 변수들을 사용할 수 있게 하였다.
head(airquality)
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
summary(airquality)
## Ozone Solar.R Wind Temp
## Min. : 1.00 Min. : 7.0 Min. : 1.700 Min. :56.00
## 1st Qu.: 18.00 1st Qu.:115.8 1st Qu.: 7.400 1st Qu.:72.00
## Median : 31.50 Median :205.0 Median : 9.700 Median :79.00
## Mean : 42.13 Mean :185.9 Mean : 9.958 Mean :77.88
## 3rd Qu.: 63.25 3rd Qu.:258.8 3rd Qu.:11.500 3rd Qu.:85.00
## Max. :168.00 Max. :334.0 Max. :20.700 Max. :97.00
## NA's :37 NA's :7
## Month Day
## Min. :5.000 Min. : 1.0
## 1st Qu.:6.000 1st Qu.: 8.0
## Median :7.000 Median :16.0
## Mean :6.993 Mean :15.8
## 3rd Qu.:8.000 3rd Qu.:23.0
## Max. :9.000 Max. :31.0
##
attach(airquality)
5숫자요약과 상자그림은 아래와 같다.
fivenum(Ozone)
## [1] 1.0 18.0 31.5 63.5 168.0
5숫자 요약을 살펴보면 중간값과 최소값의 차이에 비해 중간값과 최대값의 차이가 매우 큼을 확인할 수 있다. 즉, 중간값 아래에 데이터들이 많이 존재하고 있을 것이며 오른쪽으로 길게 늘어나 있는 분포라 짐작할 수 있을 것이다. 또한, boxplot을 통해 특이값을 확인해 볼 필요성이 있다.
boxplot(Ozone, main="Measurement of Ozone")
먼저 예상대로 2개의 특이 값을 확인할 수 있다. 또한, 아래 수염에 비해 위 수염이 매우 긴 것을 볼 수 있으며 중간값이 상자의 아래부분에 위치하고 있다. 5숫자 요약에서 확인한 바와 같이 오른쪽으로 길게 늘어져 있음을 다시 한번 확인할 수 있었다.
###(2) 바람이 7mph 미만과 이상으로 불 때의 Ozone의 상자그림과 문자값전시를 이용하여 서로 비교하여라. 바람이 오존량에 미치는 영향은 어떠한가?
아래와 같이 데이터를 나누고 4장 스크립트를 참조하여 boxplot과 문자값전시 결과값을 얻었다.
airquality$divw=ifelse(airquality$Wind<7,"Low","High")
airquality[airquality$divw=="Low",]$Ozone
## [1] 7 115 NA NA NA NA NA 135 64 77 97 97 48 61 79 16 39 78 66
## [20] 122 59 168 NA 118 84 85 96 78 73 91 28 46 30
length(airquality[airquality$divw=="Low",]$Ozone)
## [1] 33
length(airquality[airquality$divw=="High",]$Ozone)
## [1] 120
## Letter Value display
source("http://mgimond.github.io/ES218/es218.R")
lsum(airquality[airquality$divw=="Low",]$Ozone)
## letter depth lower mid upper spread
## 1 M 14.0 78.0 78.00 78.0 0.0
## 2 H 7.5 53.5 75.00 96.5 43.0
## 3 E 4.0 30.0 74.00 118.0 88.0
## 4 D 2.5 22.0 75.25 128.5 106.5
## 5 C 1.5 11.5 81.50 151.5 140.0
lsum(airquality[airquality$divw=="High",]$Ozone)
## letter depth lower mid upper spread
## 1 M 45.0 23.0 23.00 23 0.0
## 2 H 23.0 14.0 27.50 41 27.0
## 3 E 12.0 11.0 37.00 63 52.0
## 4 D 6.5 8.5 43.25 78 69.5
## 5 C 3.5 6.5 46.75 87 80.5
boxplot(Ozone~airquality$divw,xlab="wind",main="Measurement of Ozone",
names=c("More than 7","Under 7"),col=c("yellow","green"),notch=TRUE)
먼저 boxplot을 확인해보고자 한다. 2번문제에서 다룬 바와 같이 notch 구간이 겹치지 않고 있어 둘의 중간값은 95% 신뢰수준에서 유의미한 차이가 있다고 볼 수 있다. 즉, 바람이 더 세게 불 때 오존량이 줄어든다고 판단할 수 있다. 또한, 바람이 7mph 미만인 경우는 위, 아래 수염의 길이가 비슷하지만 7mph 이상일 때는 위 수염의 길이가 훨씬 길다. 마지막으로 7mph 미만인 경우 특이값이 1개, 7mph 이상인 경우 특이값이 5개 관찰되었다. 다음으로 문자값전시를 이용하여 두 자료를 비교해보았다. mid는 위, 아래의 분위수들의 평균을 말하며 산포(spread)는 위, 아래 분위수간 차이를 말한다. 중간값(mid)의 추이를 통해 왜도를 알 수 있고 산포의 추이를 통해 분포의 첨도를 알 수 있다. 책의 식(spr(E)/ spr(H)-1.704)을 이용하여 첨도를 구하면 바람이 7mph 미만인 경우 0.3425, 바람이 7mph 이상인 경우 0.2219이다. 첨도는 정규분포의 경우 0이 되도록 되어 있는데 위 자료들은 0보다 크므로 정규분포보다 긴 꼬리를 갖고, 분포가 중앙부분에 덜 집중되어 있을 것이다. 두 자료를 비교해보면 7mph미만일 때 첨도가 조금 더 크기 때문에 7mph이상일때보다 중앙부분에 덜 집중되어 있다고 볼 수 있다. 왜도는 mid를 이용하여 확인해볼 수 있다. 바람이 7mph 미만인 경우에는 mid값이 일정한 반면 바람이 7mph 이상인 경우에는 mid값이 점점 커지고 있는 것을 확인할 수 있다. 즉, 바람이 7mph미만인 경우는 7mph이상인 경우보다 대칭적인 분포를 가지고 있을 것이다. 또한, 7mph이상인 경우 mid값이 점점 커지고 있으므로 값들이 왼쪽으로 치우친 분포일 것이라고 예상해볼 수 있다. 마지막으로 바람이 7mph 미만인 경우의 데이터는 33개, 이상인 경우에는 120개로 데이터의 개수가 동등하지 않다. 그렇기 때문에 이 부분을 염두하고 위의 해석을 받아들일 필요성이 있다.
아래와 같이 데이터를 나누고 4장 스크립트를 참조하여 boxplot과 문자값전시 결과값을 얻었다.
airquality$divt=ifelse(airquality$Temp<80,"Low","High")
lsum(airquality[airquality$divt=="Low",]$Ozone)
## letter depth lower mid upper spread
## 1 M 30.0 20 20.00 20.0 0.0
## 2 H 15.5 13 20.50 28.0 15.0
## 3 E 8.0 9 23.00 37.0 28.0
## 4 D 4.5 7 25.75 44.5 37.5
## 5 C 2.5 5 28.75 52.5 47.5
lsum(airquality[airquality$divt=="High",]$Ozone)
## letter depth lower mid upper spread
## 1 M 29.0 63.0 63.0 63.0 0
## 2 H 15.0 36.0 59.0 82.0 46
## 3 E 8.0 27.0 62.0 97.0 70
## 4 D 4.5 18.0 66.0 114.0 96
## 5 C 2.5 12.5 70.5 128.5 116
length(airquality[airquality$divt=="Low",]$Ozone)
## [1] 80
length(airquality[airquality$divt=="High",]$Ozone)
## [1] 73
boxplot(Ozone~airquality$divt, xlab="Temperature",main="Measurement of Ozone",
names=c("More than 80","Under 80"),col=c("brown","yellow"),notch=TRUE)
2번과 같은 방식으로 먼저 boxplot을 확인해보고자 한다. 두 boxplot의 notch 구간이 겹치지 않아 둘의 중간값은 95% 신뢰수준에서 유의미한 차이가 있다고 볼 수 있다. 즉, 온도가 더 높을수록 오존량이 늘어난다고 판단할 수 있다. 또한, 특이값이 80도 이상에서는 1개, 80도 미만에서는 2개가 확인되었다. 다음으로 문자값전시를 이용하여 두 자료를 비교해보았다. 첨도를 구하면 온도가 80도 미만인 경우 0.1627, 온도가 80도 이상인 경우 -0.1823이다. 첨도는 정규분포의 경우 0이 되도록 되어 있는데 온도가 80도 미만인 경우는 0보다 크므로 정규분포보다 긴 꼬리를 갖고, 분포가 중앙부분에 덜 집중되어 있을 것이다. 반대로 80도 이상인 경우에는 0보다 작아 정규분포보다 짧은 꼬리를 갖고 분포가 중앙부분에 더 집중되어 있을 것이다. 왜도는 mid를 이용하여 확인해볼 수 있다. 2번과 다르게 온도가 80도 미만인 경우와 이상인 경우 모두 중간값과 크게 다르지 않은 mid값이 관찰되고 있다. 이는 큰 치우침 없이 분포되어 있을 것이라 예측해 볼 수 있다. 좀 더 구체적으로 확인해보면 두 데이터 모두 mid값이 증가하고 있으므로 오른쪽으로 조금 늘어진 분포일 것이다.
setwd("C://Users/R/Desktop/4학년 1학기/탐자분/datafile")
library(readr)
read.any <- function(text, sep = "", ...) {
encoding <- as.character(guess_encoding(text)[1,1])
setting <- as.character(tools::file_ext(text))
if(sep != "" | !(setting %in% c("csv", "txt")) ) setting <- "custom"
separate <- list(csv = ",", txt = "\n", custom = sep)
result <- read.csv(text, sep = separate[[setting]], fileEncoding = encoding, ...)
return(result)
}
구인구00=read.any("광역시-구 인구2000.csv",header=T)
구인구19=read.any("광역시-구 인구2019.csv",header=T)
시=reorder(구인구00$지역명,구인구00$지역코드)
boxplot(구인구00$인구~시,
xlab="지역명",ylab="인구수",col="orange",main="광역시별 인구변화",
boxwex = 0.3, at = 1:7 - 0.2,ylim=c(0,7e+5))
boxplot(구인구19$인구~시,
xlab="지역명",ylab="인구수",col="green",
boxwex = 0.3, at = 1:7 + 0.2,add=TRUE)
legend(5, 6e+5, c("2000년", "2019년"), fill = c("orange", "green"))
```
notch까지 표현하고자 하였지만 plot의 형태가 오히려 알아보기 힘들어 notch를 추가하지 않았다.
대도시별 인구의 변동 추이
서울: 7개의 대도시중 가장 중간값이 높은 것을 가장 먼저 확인할 수 있으며 2000년과 2019년의 중간값과 상자그림이 크게 차이 나지 않는다. 눈 여겨 볼 점은 2000년에 인구수가 적었던 2곳이 상자그림이 아래로 늘어남(1분위수가 낮아졌다)에 따라 안울타리가 낮아져 수염에 포함되었다는 점이다. 2000년에 최대값이었던 송파구는 여전히 최대값을 유지하며 특이값으로 남아있다. 마지막으로 우리나라 인구증가 추세에 비해 서울시 인구는 생각보다 크게 증가하고 있지 않는 것으로 확인되었다. 이는 주변 도시의 발달로 인해 많은 인구가 유출되어 나타난 결과라고 한다.
부산: 2000년과 2019년을 비교해보았을 때 큰 차이는 없다. 중간값이 약간 낮아졌고 수염의 길이가 조금 짧아졌다는 것이 눈에 보이는 특징이라 할 수 있다. 다만 2019년에 최대값이 특이값으로 나타나게 되었는데 이 곳은 부산 강서구로 개발로 인해 폭발적으로 인구가 증가하는 추세라고 한다. 대구: 최댓값과 최솟값은 비슷하게 유지되고 있으나 이전 두 도시에 비해 중간값이 낮아졌고 상자 또한 아래로 내려가게 되었다. 이는 전체적으로 대구의 인구 수가 감소하였음을 예측해볼 수 있다.
인천: 수염의 길이가 타 도시에 비해 길게 나타나고 있으며 2000년에 비해 상자의 길이가 약간 짧아졌다. 수염의 길이가 가장 길다는 것은 1분위수와 3분위수의 차이가 가장 크다는 의미로 각 지역간 인구격차가 크다고 예상해 볼 수 있다. 또한 중간값이 2000년에 비해 크게 감소하였지만 최대값과 최솟값은 비슷하게 유지되고 있어 인구집중현상이 2000년보다 더 심해졌을 것이다.
광주: 중간값이 커진 몇 안되는 대도시 중 하나이다. 특이한 점으로는 2000년의 최솟값이 특이값으로 존재하였다면 2019년 상자의 길이가 늘어남에 따라 수염에 포함되었다는 것과 최댓값 또한 수염에 포함되었다. 상자의 길이가 급격하게 늘어난 이유는 5개의 데이터만 존재하여 변화에 민감한 것이라 생각한다.
대전: 타 대도시들에 비해 가장 눈에 띄게 변화한 지역이다. 2000년에 최솟값이 특이값으로 존재하였지만 2019년에는 특이값으로 나타나지 않았다. 2000년에는 상자의 길이가 짧아 대부분 지역에 고르게 인구가 분포하고 있음을 알 수 있다. 또한 중간값이 다른 대도시과 비등하였다. 하지만 2019년에 상자의 길이가 길어졌고 중간값이 가장 크게 떨어진 것을 보아 인구가 꾸준하게 유출되었으며 지역내 인구격차가 생긴 것으로 유추해 볼 수 있다. 인구의 급격한 감소이유가 궁금하여 찾아본 결과 세종특별자치시가 2012년 출범하게 되면서 인구가 현저하게 줄어들었다고 한다.
울산: 이 곳 또한 중간값이 커진 대도시이다. 또한 위 수염의 길이가 매우 짧아졌고 광주만큼 눈에 띄게 상자가 길이가 늘어났다. 이 곳 또한 데이터의 수가 적어 이러한 변화가 나타난 것으로 추정된다. 2000년에 비해 각 도시의 인구수 격차가 더 커진 것은 사실이다.