Source file ⇒ 세미나_3_.Rmd
tidyr - Wide and Narrowggplot2(2)데이터 분석에 있어 하나의 데이터 테이블을 사용하는 경우는 드물다. 많은 경우 서로 연관있는 다수의 데이터 테이블을 합쳐 사용하게 되는데, 이러한 서로 관련있는 다수의 데이터 테이블을 relational data이라 한다.
예시: Grades and Enrollment
두 데이터 테이블 Grades 와 Courses 한 학교에서의 grade와 course에 관해 연관된 정보를 제공한다.
Grades <- read.csv("http://tiny.cc/mosaic/grades.csv")
| sid | grade | sessionID | |
|---|---|---|---|
| 2197 | S31680 | B | session3518 |
| 259 | S31242 | B | session2897 |
| 4188 | S32127 | A | session2002 |
| 3880 | S32058 | A- | session2952 |
Courses <- read.csv("http://tiny.cc/mosaic/courses.csv")
| sessionID | dept | level | sem | enroll | iid | |
|---|---|---|---|---|---|---|
| 640 | session2568 | J | 100 | FA2002 | 15 | inst223 |
| 76 | session1940 | d | 100 | FA2000 | 16 | inst409 |
| 1218 | session3242 | m | 200 | SP2004 | 30 | inst476 |
여기서 기본키(primary key)와 외래키(foreign key)는 sessionID이다.
기본키(primary key)
하나의 값 혹은 여러 값의 조합으로 테이블의 각 case를 유일하게 식별
외래키(foreign key)
또 다른 테이블에 있는 유일하게 케이스를 식별하는 하나의 값(혹은 여러 값의 조합). 즉 외래키는 다른 테이블에 존재하는 테이블의 기본키이다.
join이라는 data verb는 left table와 right table을 합친다.
left table이 보통 기본 테이블이고 right table은 left table에서 얻을 수 없는 정보를 가진 테이블이 된다.
목표: 학생 별로 학급의 평균 크기를 찾는다.
sid)는 Grades테이블에 존재한다.enroll은 Courses 테이블에 존재한다.sessionID는 두 테이블 모두에 존재한다.Courses 테이블에서 enrollment에 대한 정보를 Grades 테이블로 가져와야 한다.
Grades %>%
left_join(Courses) %>% sample_n(size=4)
| sid | grade | sessionID | dept | level | sem | enroll | iid | |
|---|---|---|---|---|---|---|---|---|
| 4043 | S32061 | B+ | session3644 | K | 300 | SP2005 | 18 | inst239 |
| 1536 | S31518 | AU | session2901 | J | 100 | FA2003 | 22 | inst224 |
| 1844 | S31587 | B- | session3191 | b | 200 | SP2004 | 10 | inst403 |
| 3593 | S31962 | B | session3821 | W | 300 | SP2005 | 24 | inst138 |
Courses %>%
left_join(Grades) %>% sample_n(size=4)
| sessionID | dept | level | sem | enroll | iid | sid | grade | |
|---|---|---|---|---|---|---|---|---|
| 2050 | session2454 | Y | 200 | FA2002 | 13 | inst397 | S31587 | C+ |
| 3823 | session2990 | m | 200 | FA2003 | 20 | inst476 | S32310 | B+ |
| 3354 | session2851 | O | 300 | SP2003 | 14 | inst308 | S31509 | A |
| 5405 | session3573 | M | 100 | SP2005 | 23 | inst263 | S31830 | S |
Courses 와 Grades가 join되면, 다음과 같이 평균 학급 수를 찾을 수 있다.
AveClassEachStudent <- Grades %>%
left_join(Courses) %>%
group_by(sid) %>%
summarise(ave_enroll = mean(enroll, na.rm=TRUE))
| sid | ave_enroll |
|---|---|
| S32124 | 25.10000 |
| S32154 | 22.93333 |
| S32415 | 20.87500 |
예시:
Grades %>%
left_join(Courses, by = c(sessionID = "sessionID")) %>%
head(4)
| sid | grade | sessionID | dept | level | sem | enroll | iid |
|---|---|---|---|---|---|---|---|
| S31185 | D+ | session1784 | M | 100 | FA1991 | 22 | inst265 |
| S31185 | B+ | session1785 | k | 100 | FA1991 | 52 | inst458 |
| S31185 | A- | session1791 | J | 100 | FA1993 | 22 | inst223 |
| S31185 | B+ | session1792 | J | 300 | FA1993 | 20 | inst235 |
by=의 default 값은 양쪽의 테이블에서 같은 이름을 가지고 있는 변수이다. 하지만 직접 눈으로 확인하지 않는 한, default값을 신뢰할 수 없다.
Grades %>%
left_join(Courses) %>%
head(4)
| sid | grade | sessionID | dept | level | sem | enroll | iid |
|---|---|---|---|---|---|---|---|
| S31185 | D+ | session1784 | M | 100 | FA1991 | 22 | inst265 |
| S31185 | B+ | session1785 | k | 100 | FA1991 | 52 | inst458 |
| S31185 | A- | session1791 | J | 100 | FA1993 | 22 | inst223 |
| S31185 | B+ | session1792 | J | 300 | FA1993 | 20 | inst235 |
Grades %>%
left_join(Courses, by="sessionID") %>%
head(4)
| sid | grade | sessionID | dept | level | sem | enroll | iid |
|---|---|---|---|---|---|---|---|
| S31185 | D+ | session1784 | M | 100 | FA1991 | 22 | inst265 |
| S31185 | B+ | session1785 | k | 100 | FA1991 | 52 | inst458 |
| S31185 | A- | session1791 | J | 100 | FA1993 | 22 | inst223 |
| S31185 | B+ | session1792 | J | 300 | FA1993 | 20 | inst235 |
#install.packages("nycflights13")
library(nycflights13)
데이터 테이블 nycflights13::flights에서 몇 가지 변수를 선택하여 join 예시를 살펴보자.
flights2 <- flights %>%
select(year:day, hour, tailnum, carrier)
head(flights2,2)
| year | month | day | hour | tailnum | carrier |
|---|---|---|---|---|---|
| 2013 | 1 | 1 | 5 | N14228 | UA |
| 2013 | 1 | 1 | 5 | N24211 | UA |
또 다른 데이터 테이블 airlines은 약자로 표현된 항공사 정보의 full name을 알 수 있도록 해준다.
head(airlines,2)
| carrier | name |
|---|---|
| 9E | Endeavor Air Inc. |
| AA | American Airlines Inc. |
또 다른 weather이라는 데이터 테이블은 NYC 공항의 시간당 날씨 정보를 알려준다.
head(weather,2)
| origin | year | month | day | hour | temp | dewp | humid | wind_dir | wind_speed | wind_gust | precip | pressure | visib | time_hour |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| EWR | 2013 | 1 | 1 | 0 | 37.04 | 21.92 | 53.97 | 230 | 10.35702 | 11.91865 | 0 | 1013.9 | 10 | 2013-01-01 09:00:00 |
| EWR | 2013 | 1 | 1 | 1 | 37.04 | 21.92 | 53.97 | 230 | 13.80936 | 15.89154 | 0 | 1013.0 | 10 | 2013-01-01 10:00:00 |
세 데이터 테이블의 관계는 다음과 같다:
flights데이터는 carrier변수를 통해 airlines 데이터와 연결되어 있다.
flights데이터는 origin(the location), year, month, day 그리고 hour(the time)를 통해 weather데이터와 연결되어 있다.
만약 flight2데이터에 존재하는 항공사 이름들의 full name을 얻고 싶다면 airlines 과 flights2 데이터를 left_join()으로 합칠 수 있다:
flights2 %>%
left_join(airlines, by="carrier") %>%
head(3)
| year | month | day | hour | tailnum | carrier | name |
|---|---|---|---|---|---|---|
| 2013 | 1 | 1 | 5 | N14228 | UA | United Air Lines Inc. |
| 2013 | 1 | 1 | 5 | N24211 | UA | United Air Lines Inc. |
| 2013 | 1 | 1 | 5 | N619AA | AA | American Airlines Inc. |
left_join()의 결과는 flight2에 새로 생긴 name 변수이다.
키(key)
위의 열에서 색칠된 부분이 “키”에 해당한다. 키는 테이블 간 열을 합칠 때 사용된다.
값(value)
회색으로 칠해진 부분은 “값”에 해당한다.
위의 그림에서는 키와 값이 각각 하나씩 존재하지만, 여러개 존재할 수도 있다.
join은 x 테이블의 각각의 열을 y 테이블의 열과 연결하는 것이다. 아래의 다이어그램은 케이스간 match가 어떻게 이루어지는지 보여준다.
실제 join()에서, match는 점으로 표현된다. 점의 개수는 match의 수를 의미하고 이는 곧 join 결과에서 그만큼의 열이 생성됨을 의미한다.
join 중 가장 단순한 형태가 inner join이다. inner join은 두 테이블의 key가 값을 때 match가 일어나는 형태이다.
inner join의 output은 key, x 테이블의 값(values), y 테이블의 값(values)이 들어있는 새로운 데이터 프레임이다. 명령에서는 by=를 이용하여 dplyr에 어떠한 변수가 key로 사용되는지를 알려준다.
x %>%
inner_join(y, by="key")
inner join에서 match되지 못한 열들은 결과에 나열되지 않는다. 이는 즉, 데이터 분석에 inner join이 사용될 때, 손실되는 케이스가 있음을 의미하고 따라서 대부분의 데이터 분석에서 적절한 join 방법은 아니다.
inner join은 두 테이블 모두에 나타난 관측값만을 결과로 전송한다. outer join의 경우 최소 한 테이블에 나타난 관측값 모두를 결과로 전송한다. outer join에는 3가지 종류가 있다.
x의 모든 관측값을 유지한다.y의 모든 관측값을 유지한다.x 와 y에 나타난 모든 관측값을 유지한다.joins은 key를 중심으로 이루어지며, match되는 key가 없는 경우 NA를 반환한다.
다이어그램으로 표현하면:
이 중 가장 흔히 쓰이는 것은 left join이다: left join에서는 기존의 데이터의 모든 정보가 그대로 반환되기 때문에 부가적인 정보를 기존의 데이터 테이블에 join할 때 유용하게 사용된다.
따라서 left join이 default join으로 사용되어야 한다: 다른 join을 선호할 특별한 이유가 없는 한 left join을 사용하는 것이 좋다. 만약 NA가 있어서는 안되는 경우, 특별히 inner join을 사용할 수는 있지만 특별한 경우가 아니라면 기존 데이터에 손실이 없는 left join을 사용하는 것이 기본이다.
Venn diagram으로 여러 joins을 살펴보면:
두 데이터 테이블이 있다고 가정하자:
clinicName, postalCode.| clinicName | postalCode |
|---|---|
| A | 22120 |
| B | 35752 |
| C | 56718 |
| D | 35752 |
| E | 67756 |
| F | 69129 |
| G | 73455 |
| H | 73455 |
| I | 76292 |
postalCode, over65, etc.| over65 | postalCode |
|---|---|
| 0.46 | 35752 |
| 0.72 | 22120 |
| 0.93 | 22120 |
| 0.26 | 92332 |
| 0.46 | 84739 |
| 0.94 | 67756 |
아래의 다이어그램은 left와 right 테이블의 cases가 어떻게 연결되어 있는지를 시각적으로 보여준다. 그리고 line은 match를 의미한다. 총 5번의 match가 있고 그중 중복되는 case도 존재하는 것을 볼 수 있다. match되지 않은 case 또한 양측의 테이블에 존재한다.
inner join 은 match가 된 짝들을 반환한다. clinic A는 두 번의 match가 있는 것을 볼 수 있는데, 이는 우측의 테이블에서 clinc A와 두 번의 match가 발생하였기 때문이다.
LL %>% inner_join(RR)
| clinicName | postalCode | over65 |
|---|---|---|
| A | 22120 | 0.72 |
| A | 22120 | 0.93 |
| B | 35752 | 0.46 |
| D | 35752 | 0.46 |
| E | 67756 | 0.94 |
outer join 은 match가 없는 cases까지도 포함하여 결과로 반환한다. 세부 디테일은 left, right, full join 중 어떤 것을 사용하는지에 따라 달라진다.
LL %>% left_join( RR)
| clinicName | postalCode | over65 |
|---|---|---|
| A | 22120 | 0.72 |
| A | 22120 | 0.93 |
| B | 35752 | 0.46 |
| C | 56718 | NA |
| D | 35752 | 0.46 |
| E | 67756 | 0.94 |
| F | 69129 | NA |
| G | 73455 | NA |
| H | 73455 | NA |
| I | 76292 | NA |
LL %>% right_join(RR)
| clinicName | postalCode | over65 |
|---|---|---|
| B | 35752 | 0.46 |
| D | 35752 | 0.46 |
| A | 22120 | 0.72 |
| A | 22120 | 0.93 |
| NA | 92332 | 0.26 |
| NA | 84739 | 0.46 |
| E | 67756 | 0.94 |
LL %>% full_join(RR)
| clinicName | postalCode | over65 |
|---|---|---|
| A | 22120 | 0.72 |
| A | 22120 | 0.93 |
| B | 35752 | 0.46 |
| C | 56718 | NA |
| D | 35752 | 0.46 |
| E | 67756 | 0.94 |
| F | 69129 | NA |
| G | 73455 | NA |
| H | 73455 | NA |
| I | 76292 | NA |
| NA | 92332 | 0.26 |
| NA | 84739 | 0.46 |
tidyr - Wide and Narrowtidyr 패키지의 tidyr::narrow()와 tidyr::gather() 두 가지 data verbs를 살펴보자.
데이터 테이블은 wide 혹은 narrow의 형태로 표현될 수 있다. 각각은 각각의 이점이 있다.
Wide format의 경우 각 환자 별 sbp (systolic blood pressure)의 전과 후 차이를 도출하는데 유용하다. 하지만 세미나(1)에서 살펴본 내용에 따르면 아래의 데이터는 tidy하지 않다.
BP_wide
| subject | before | after |
|---|---|---|
| BHO | 120 | 160 |
| GWB | 115 | 135 |
| WJC | 105 | 145 |
아래는 narrow format (tidy)이다. 종종 그래프를 그리기 위해서 우리는 데이터를 narrow format으로 표현해야할 경우가 있을것이다.
BP_narrow
| subject | when | sbp |
|---|---|---|
| BHO | before | 160 |
| GWB | before | 115 |
| WJC | after | 145 |
| GWB | after | 135 |
| WJC | before | 105 |
| BHO | after | 160 |
data verbs spread() 와 gather()이 wide format과 narrow format 사이를 변환시켜준다.
gather(): wide -> narrow데이터 셋의 행(column)의 이름이 변수의 이름이 아닌, 변수의 값인 경우 우리는 데이터가 tidy하지 못하다는 문제를 가지게 된다. 이때 우리는 gather()을 사용한다. 변수의 이름이 아닌 값을 가진 행들은 새로운 변수를 통해 정리되어야 할 필요가 있다. 이 작업을 수행하기 위해서 아래의 3가지 매개변수(parameters)가 필요하다.
key: column이 변수의 이름이 아닌 값을 가지고 있는 경우, 변수 값을 포괄할 새로운 이름이 필요하다. 이때의 새로운 이름이 key가 된다. 위의 예시의 경우 before과 after이 column 이름 위치에 존재하지만 변수의 이름이 아닌 값에 해당한다. 따라서 새로운 이름인 when을 지어주기로 하자. 따라서 key는 when이 된다.
value: 셀에 있는 값들을 통합할 이름. 즉 wide 테이블에서 before과 after 행에 존재하는 값들을 부를 이름을 의미한다. 여기서 이들을 sbp라고 하기로 하자.
변수가 아닌 값을 대표하는 column(행)의 집합. 여기서는 before 과 after.
BP_narrow1 <- BP_wide %>%
gather(key= when, value = sbp, `before`, `after`) # before or after are legal names so it isn't necessary to use backticks (but it doesn't hurt)
BP_narrow1
| subject | when | sbp |
|---|---|---|
| BHO | before | 120 |
| GWB | before | 115 |
| WJC | before | 105 |
| BHO | after | 160 |
| GWB | after | 135 |
| WJC | after | 145 |
spread(): narrow -> wideSpreading 은 gathering과 반대의 작업을 수행한다. 관측값들이 여러 열에 걸쳐 산포되어 있을 때 spread를 사용한다. 이를 수행하기 위해서는 아래의 2가지 매개변수(parameters)가 필요하다:
key: 새로 형성할 데이터 테이블의 column 이름으로 만들고 싶은 값이 들어 있는 기존 테이블의 column. 여기서는 when이 새로 만들 테이블에서 column의 이름이 될 after과 before을 포함하고 있으므로 key가 된다.
value: key 맞게 정렬되어야 할 값들을 가진 기존 테이블에서의 column의 이름. 여기서는 새롭게 만들 테이블에서 after과 before의 키 아래 sbp값들이 값으로 정렬될 것이므로 sbp값을 값으로 가지고 있는 sbp column이 value가 된다.
BP_wide1 <- BP_narrow %>%
spread(key= when, value = sbp)
BP_wide1
| subject | after | before |
|---|---|---|
| BHO | 160 | 160 |
| GWB | 135 | 115 |
| WJC | 145 | 105 |
a <- c("Afghanistan","Brazil", "China")
b <- c(745,37737,212258)
c <- c(266,80488,213766)
df_wide <- data.frame(a,b,c)
names(df_wide) <- c("countries","1999", "2000")
df_wide
| countries | 1999 | 2000 |
|---|---|---|
| Afghanistan | 745 | 266 |
| Brazil | 37737 | 80488 |
| China | 212258 | 213766 |
테이블을 gather을 사용하여 tidy form으로 만들고자 한다.
| countries | year | population |
|---|---|---|
| Afghanistan | 1999 | 745 |
| Brazil | 1999 | 37737 |
| China | 1999 | 212258 |
| Afghanistan | 2000 | 266 |
| Brazil | 2000 | 80488 |
| China | 2000 | 213766 |
아래 어떠한 명령이 들어가야 할까:
df_narrow <- df_wide %>%
gather(fill__this__out)
df_narrow
## # A tibble: 3 x 3
## # Groups: name [3]
## name F M
## * <chr> <int> <int>
## 1 Allen 1836 263375
## 2 Mary 4112464 15151
## 3 Sue 144410 519
## # A tibble: 6 x 3
## # Groups: name [3]
## name sex value
## <chr> <chr> <int>
## 1 Allen F 1836
## 2 Mary F 4112464
## 3 Sue F 144410
## 4 Allen M 263375
## 5 Mary M 15151
## 6 Sue M 519
ggplot2(2)Aesthetics은 그래프의 특징 중 변수들과 연관된 것들이다. (ex. col=as.factor(cyl))
Attribute은 그래프의 특징 중 변수들과 연관이 없는 것들이다. 따라서 특정한 고정 값을 가진다. (ex. col=“red”)
mtcars %>% ggplot(aes(x=wt,y=mpg)) + geom_point(aes(col=as.factor(cyl)))
mtcars %>% ggplot(aes(x=wt,y=mpg)) + geom_point(col="red")
Note: attributes는 특정하게 정해진 값이기 때문에 이에 대해 legend가 존재하지 않는다.
theme은 ggplot2에서 non-data를 사용자의 뜻에 따라 변경할 수 있게 해준다.
예를들어 할 수 있는 것들에는:
theme의 변경은 그래프 자체가 보이는 방식을 바꾸지만 data와는 independent하다. 이러한 것들을 theme elements (i.e. aspects of a ggplot object that are capable of modifying its appearance but are neither directly related to data nor aesthetics associated with data)라고 부른다.
아래의 그래프로 시작해보자:
p <- ggplot2::mpg %>% ggplot( aes(x = cty, y = hwy, color = factor(cyl))) +
geom_jitter() +
labs(
x = "City mileage/gallon",
y = "Highway mileage/gallon",
color = "Cylinders"
)
p
ggplot2의 theme은 다음의 것들로 구성되어 있다:
theme elements, data와는 무관한 그래프의 특징. 예를들어 축에 표현되는 텍스트 (ex: axis.text);
theme element functions, theme elements를 변경할 수 있도록 해주는 함수 (ex: axis.text = element_text(size = 14));
theme functions, 그래프의 전체적인 테마를 바꾸기 위한 함수
p +
theme(axis.text =
element_text(colour = "blue", size = 15, face = "italic"),
axis.text.y =
element_text(size = rel(0.7), angle = 90))
library(ggthemes) #in console: install.packages("ggthemes") to install
p + theme_igray()
만약 색을 바꾸고 싶은 경우 scale_colour_brewer() 함수를 사용하여 원하는 팔레트를 지정할 수 있다.
ggplot2 help.
p + scale_colour_brewer(palette = "Dark2")
theme elements는 대응하는 element function을 이용하여 그래프의 특정 오브젝트가 가지는 특징을 바꿀 수 있다.
element_text()element_line()element_rect()element_blank()element_xx()의 함수는 theme element의 attributes를 변형시킬 수 있다 (e.g., color, text size).
그래프에서 다음의 사항을 변경하고 싶을 때:
다음의 명령은 위의 변경사항을 실행한다:
p +
theme(
axis.text = element_text(size = 14),
legend.background = element_rect(fill = "white"),
legend.position = c(0.14, 0.70),
panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "navy")
)
theme element functions를 자세히 살펴보자:
element_text()목적: label과 heading에 관여.
## Argument Description Default
## 1 family font family “”
## 2 face font face plain
## 3 colour font color black
## 4 size font size 10
## 5 hjust horizontal justification 0.5
## 6 vjust vertical justification 0.5
## 7 angle text angle 0
## 8 lineheight line height 1.1
element_line()목적: To draw lines and segments such as graphics region boundaries, axis tick marks and grid lines.
## Arument Description Default
## 1 colour line color black
## 2 size line thinkness 0.5
## 3 linetype type of line 1
element_rect()목적: To draw rectangles. It is mostly used for background elements and legend keys.
## Arguement Description Default
## 1 fill fill color none
## 2 colour border color black
## 3 size thinkness of border line 0.5
## 4 linetype type of border line 1
element_blank()목적: To draw nothing.
Arguments: 없음.
다음 그래프를 보고 명령어를 이해해보라.
# Use theme() to modify theme elements
p + labs(title = "Highway vs. city mileage per gallon") +
theme(
axis.text = element_text(size = 20),
plot.title = element_text(size = 20,color = "red"),
legend.key = element_rect(fill = "black"),
legend.background = element_rect(fill = "white"),
legend.position = "right",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "grey40")
)
theme functions을 이용하면 다른 사용자가 이미 만들어준 theme을 그래프에 적용시킬 수 있다.
library(ggthemes) #need to install ggthemes
mpg %>% ggplot( aes(x = cty, y = hwy, color = factor(cyl))) +
geom_jitter() +
labs(
x = "City mileage/gallon",
y = "Highway mileage/gallon",
color = "Cylinders"
) + theme_igray()
색은 RGB의 16진법으로 표현된다. 예를들어, “#0066CC”의 경우 처음 두 자리수는 빨간색의 정도, 그 다음 두 자리는 초록색의 정도, 그리고 마지막은 파란색의 정도를 의미한다. 각각의 정도는 16진법으로 00에서 FF까지로 표현된다. 예를들어 “#FFFFFF”은 하얀색이며, “#990000” 은 짙은 빨간색이다.
예시:
set.seed(955)
# Make some noisily increasing data
dat <- data.frame(xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
ggplot(dat, aes(x=xvar, y=yvar)) +
geom_point(shape=1) + # Use hollow circles
geom_smooth(method=lm, fill="#013A59") + # Add linear regression line
theme_igray() #default theme
mtcars %>% ggplot(aes(x=wt, y=mpg)) +geom_point() +geom_smooth(method="lm") + geom_point(aes(x=mean(wt),y=mean(mpg)),size=5)
두 개의 연속형 변수 X 와 Y가 있다. 예를들어, mtcars 데이터 테이블에서, X=wt 와 Y=mpg.
mtcars %>% ggplot(aes(x=wt, y=mpg)) +geom_point() +geom_smooth(se=FALSE, method = "loess")
Loess 알고리즘
\(x_0\)를 하나의 관측치라고 하자. 예를들어, \(x_0=3.435\) (3435파운드)이다.
span이라 한다.span=.4이라면 우리는 중량 3.435 근방의 가장 가까운 13개 (정확히는 0.4*32=12.8)의 관측치를 찾는다 (아래 파란색으로 표현).위의 예시에서는, 중량이 3.435 근방인 경우 1에 가까운 가중치를, 그리고 멀어질 수록 낮은 가중치를 가진다. 모든 빨간 점들은 가중치가 0이다.
\(\widehat{\beta_0}\)와 \(\widehat{\beta_1}\) 중 \[ \sum_{i=1}^{n} K_{i0}(y_i-\beta_0 -\beta_1x_i)^2. \] 를 최소화하는 값을 구한다. simple linear regression과 다른 점은 여기에 가중치\(K_{i0}\)가 포함된다는 것이다.
\(x_0\)의 적합값: \[\widehat{M}(x_0)=\widehat{\beta_0} + \widehat{\beta_1}x_0\]
이러한 절차를 데이터셋에 주어진 모든 \(x_0\)에 대하여 실행한다. 그리고 \(\widehat{M}(x_0)\) point를 연결시킨다. 우리는 각각의 \(x_0\)에 대하여 서로 다른 \(\widehat{\beta_0}\) 와 \(\widehat{\beta_1}\) 를 얻게 된다. (점들을 어떻게 연결하는지에 대한 구체적인 내용은 생략) 여기서 우리가 이해해야 할 점은 만약 span이 0에 가깝다면 regression line의 정확성(accuracy)은 아주 작은 범위 내에서 한정된다. 따라서 각각의 관측치마다 regression line의 방향이 바뀔 것이고, 그것이 wiggly한 직선을 형성한다. 만약 span이 1에 가깝다면 regression line은 넓은 범위의 관측치에 대해 정확할 것이고, Loess 커브는 직선에 가깝게 형성된다.
mtcars %>% ggplot(aes(x=wt, y=mpg)) +geom_point() +stat_smooth(se=FALSE,method="loess", span=.4)
mtcars %>% ggplot(aes(x=wt, y=mpg)) +geom_point() +stat_smooth(se=FALSE,method="loess", span=.8)
Loess방법은 분포에 대한 아무런 가정이 없다(linearity의 가정이 없음)는 점에서 non parametric 방법에 해당한다.