R에서 마크다운으로 작업을 하다보면 컬럼만 다른 똑같은 그래프 혹은 테이블을 여러개 만들어야 하는 경우가 있다.
한 두개라면 그냥 복사 + 붙여넣기로 chunk를 새로 만들면 되지만, 그 수가 많아지면 일일이 만들기가 번거롭다. 이럴 때 하나의 chunk 안에 for 문으로 여러 chunk를 생성하는 방법을 소개하고자 한다.
1. Create multi Headers using for loop in one chunk
예제 데이터는 iris를 사용한다.
1
|
data < -iris
|
cs |
한 번에 for loop로 여러개의 Header를 만드는 방법은 다음과 같다.
1. chunk 생성시 results = 'asis' option 지정하기
2. for loop안에 cat() 으로 내용 입력하기
다음은 data의 컬럼명을 헤더로 출력하는 코드이다.
1
2
3
4
5
6
7
8
9
10
|
# header
```{r, results='asis'}
for (i in 1:ncol(data)) {
cat("\n\n## ",names(data)[i], "\n\n")
cat("contens", i) ## contens
cat("\n\n")
}
```
|
cs |
결과는 다음과 같다.
여기서 중요한 것은 chunk를 정의할 때 results = 'asis' option을 설정해 주는 것이다.
results = 'asis' option은 chunk의 output으로 출력되는 값들을 테두리 없이 출력해주는 옵션이다.(chunk 내의 output이 아니라 chunk 밖에 직접 쓴 효과)
참고) 해당 옵션을 지정해 주지 않으면 다음과 같은 결과가 생성된다.
2. Create multi Plots using for loop in one chunk
2-1. Create multi plots using for loop in one chunk
for loop로 한 번에 plot 그리는 방법은 다음과 같다.
1. chunk 생성시 results = 'asis' option 지정하기
2. for loop 안에 plot 입력하기
다음은 data에서 numerical 변수인 Sepal.Length, Sepal.Width, Petal.Length, Petal.Width 에 대해서 Trend plot을 출력하는 코드이다.
1
2
3
4
5
6
7
8
9
10
|
# header + plot
```{r, results='asis'}
for (i in 1:4) {
cat("\n\n## ",names(data)[i], "\n\n")
plot(data[,i])
cat("\n\n")
}
```
|
cs |
결과는 다음과 같다.
Petal.Length, Petal.Width 변수에 대한 그래프도 생성되었지만 캡처의 한계로 생략한다.
기본 plot은 특별한 문법없이 기존에 사용하던데로 for loop안에 입력해주면 된다.
하지만, ggplot 같은 경우는 print() 혹은 grid.arrange() 로 그래프를 출력해주어야 한다.
참고) print() or grid.arrange() 없이 그냥 실행하면 다음과 같이 그래프는 출력되지 않는다.
1
2
3
4
5
6
7
8
|
# header + ggplot
```{r, results='asis'}
for (i in 1:4) {
cat("\n\n## ",names(data)[i], "\n\n")
ggplot(data,aes(x = 1:nrow(data), y = data[,i])) + geom_point()
}
```
|
cs |
2-2. Create multi Header + ggplotly using for loop in one chunk
ggplotly처럼 인터랙티브한 그래프는 다음과 같이 출력한다.
* 인터랙티브 그래프란? 마우스 움직임에 반응하며 실시간으로 형태가 바뀌는 그래프
1. results = 'asis'
2. 그래프를 list 형태로 저장
3. HTML Tag 형태로 생성 (renderTags(x)$html)
4. 만들어진 Tag(Dependencies)를 HTML File에 Attach
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
|
# header + ggplotly
```{r, results='asis'}
output <- list()
for (i in 1:4) {
fig1 <- ggplot(data,aes(x = 1:nrow(data), y = data[,i])) + geom_point()
output[[i]] <- ggplotly(fig1)
}
for (i in 1:4) {
cat("\n\n## ",names(data)[i], "\n\n")
x <- output[[i]]
cat(renderTags(x)$html)
cat("\n\n")
}
deps <- lapply(
Filter(function(x){inherits(x,"htmlwidget")},output),
function(hw){
renderTags(hw)$dependencies
}
)
attachDependencies(
tagList(),
unlist(deps,recursive=FALSE)
)
```
|
cs |
결과는 다음과 같다.
캡처 이미지라서 다이나믹함이 보이지 않지만, 마우스를 가져다 대면 값이 보이고 확대, 축소도 가능한 인터랙티브 그래프이다.
HTML에서 Tag는 hyperlink를 의미한다. 아마 R에서 생성되는 테이블이나 그래프들을 하이퍼링크로서 입력시키는 듯 하다.
2-3. Create multi Header + dygraph using for loop in one chunk
ggplotly처럼 인터랙티브하지만 훨신 가벼운 dygraph 역시 같은 방법으로 출력할 수 있다.
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
32
33
34
35
36
|
# dygraph
```{r, results='asis'}
library(dygraphs)
output <- list()
for (i in 1:4) {
plot.dat <- data.frame(idx = 1:nrow(data), dat = data[,i])
p <- dygraph(plot.dat) %>%
dyRangeSelector()
output[[length(output) + 1]] <- p
}
for (i in 1:4) {
cat("\n\n## ",names(data)[i], "\n\n")
x <- output[[i]]
cat(renderTags(x)$html)
cat("\n\n")
}
deps <- lapply(
Filter(function(x){inherits(x,"htmlwidget")},output),
function(hw){
renderTags(hw)$dependencies
}
)
attachDependencies(
tagList(),
unlist(deps,recursive=FALSE)
)
```
|
cs |
* 개인적으로 plotly보다는 dygraph를 더 선호한다.
데이터의 크기가 작을 때는 ggplotly와 dygraph 중 무엇을 쓰던 상관없지만, 데이터 크기가 클 때는 dygraph가 훨씬 가볍다는걸 느낄 수 있다.
y축도 왼쪽, 오른쪽을 따로 지정할 수 있어 Scale을 해주지 않아도 두 변수에 대한 Trend를 바로 비교할 수 있는 등 여러 옵션이 많다.
3. Create multi Tables using for loop in one chunk
이번에는 그래프가 아닌 테이블을 for loop로 출력하는 방법이다.
3-1. kable
R Markdown에서 table을 출력하는데 대표적으로 사용하는 funcion 이다. knitr 패키지에 있으며 이를 for loop로 출력하는 방법은 다음과 같다.
첫번째 컬럼부터 2번째, 3번째, ..., 5번째 컬럼까지의 데이터를 출력하는 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# kable {.tabset}
```{r, results='asis'}
for (i in 2:ncol(data)) {
cat("\n\n## ",names(data)[i], "\n\n")
print(kable(data[,c(1:i)]))
cat("\n\n")
}
```
|
cs |
위 ggplot처럼 그냥 출력하면 안되고 print() 로 출력해주어야한다.
만약, 작동하지 않는다면 kable() 안에 format = "html" 를 추가해보는 걸 추천한다.
* 참고로 {.tabset} 으로 아래 그림과 같이 Tab을 생성할 수 있다. 이렇게 하면 각 결과가 아래로 쭉 붙는 것이 아니라 Tab으로 생성되어 클릭하면 해당 결과를 볼 수 있다.
3-2. Summary
데이터에 대한 Summary 결과는 테이블 형태로 떨어지는 것이 아니기 때문에 pander로 출력해주어야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
|
# Summary
```{r, results='asis'}
for (i in 1:ncol(data)) {
cat("\n\n## ",names(data)[i], "\n\n")
cat(summary(data[,i]) %>% pander::pander())
}
```
|
cs |
참고) pander
Sepal.Length 에 대해 pander없이 그냥 summary한 결과 cat으로 출력하면 다음과 같다.
이를 pander로 출력하면 다음과 같이 테이블 형태로 출력된다.
3-3. DT::datatable
마크다운에서 테이블을 출력하는 다른 방법은 DT 패키지 안에 있는 datatable function이다.
kable은 row가 몇 개이던 간에 전체 데이터를 아래로 쭉 출력하는 반면, DT::datatable은 10개씩 나누어 보여주고, 컬럼명 클릭시 sorting도 가능하며, 검색기능도 있다.
첫번째 컬럼부터 2번째, 3번째, ..., 5번째 컬럼까지의 데이터를 DT 패키지로 출력하는 코드는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# DT
```{r, results='asis'}
for (i in 2:4) {
cat("\n\n## ",names(data)[i], "\n\n")
print(htmltools::tagList(DT::datatable(data[,(1:i)])))
cat("\n\n")
}
```
|
cs |
DT 테이블을 tagList안에 넣어주고, print로 출력한다.
All in one
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# All in One {.tabset}
```{r, results='asis'}
## list of graph
ggplotly_list <- list()
dygraph_list <- list()
for (i in 1:4) {
## col to draw plot
plot.dat <- data.frame(idx = 1:nrow(data), dat = data[,i])
## ggplotly
fig1 <- ggplot(plot.dat,aes(x = idx, y = dat)) + geom_point()
ggplotly_list[[i]] <- ggplotly(fig1)
## dygraph
fig2 <- dygraph(plot.dat) %>%
dyRangeSelector()
dygraph_list[[i]] <- fig2
}
## print graphs
for (i in 1:4) {
## header
cat("\n\n## ",names(data)[i], "\n\n")
## print Summary
cat("<b><font size='3' face='verdana'>[Summary]</font></b>", "<br><br>\n")
cat(summary(data[,i]) %>% pander::pander())
cat("\n\n<hr>\n\n") ## horizon line
## ggplot
cat("<b><font size='3' face='verdana'>[ggplot]</font></b>", "<br><br>\n")
print(ggplot(data,aes(x = 1:nrow(data), y = data[,i])) + geom_point())
cat("\n\n<hr>\n\n") ## horizon line
## print ggplotly
cat("<b><font size='3' face='verdana'>[ggplotly]</font></b>", "<br><br>\n")
cat(renderTags(ggplotly_list[[i]])$html)
cat("\n\n<hr>\n\n") ## horizon line
## print dygraph
cat("<b><font size='3' face='verdana'>[dygraph]</font></b>", "<br><br>\n")
cat(renderTags(dygraph_list[[i]])$html)
cat("\n\n<hr>\n\n") ## horizon line
## DT
cat("<b><font size='3' face='verdana'>[DT]</font></b>", "<br><br>\n")
print(htmltools::tagList(DT::datatable(data[,(1:(i+1))])))
cat("\n\n<hr>\n\n") ## horizon line
cat("\n\n<br><br>\n\n")
}
## Attach
deps <- lapply(
Filter(function(x){inherits(x,"htmlwidget")},ggplotly_list),
function(hw){
renderTags(hw)$dependencies
}
)
attachDependencies(
tagList(),
unlist(deps,recursive=FALSE)
)
##
deps <- lapply(
Filter(function(x){inherits(x,"htmlwidget")},dygraph_list),
function(hw){
renderTags(hw)$dependencies
}
)
attachDependencies(
tagList(),
unlist(deps,recursive=FALSE)
)
```
|
cs |
참고
1. Markdown 기본 설정값
---
title: "Rmarkdown Train"
author: "by SK C&C 이다경 선임 - 2020/07/31"
output:
rmdformats::readthedown:
code_folding: hide
---
<style>
#TOC {
top: 1%;
opacity: 0.5;
}
#TOC:hover {
opacity: 1;
}
</style>
2. 마크다운 기본 옵션 설정값
knitr::opts_chunk$set(echo=TRUE, warning=FALSE, message=FALSE)
3. 사용 Library
library(xtable)
library(magrittr)
library(dlookr)
library(dplyr)
library(ggplot2)
library(gridExtra)
library(moments)
library(knitr)
library(kableExtra)
library(DT)
library(plotly)
library(magrittr)
library(htmltools)
library(pander)
4. ggplot 기본 옵션 설정값
old <- theme_set(theme_bw())
'R > MarkDown' 카테고리의 다른 글
[R Markdown] Plot과 Table을 한 Row에 그리기 (0) | 2022.03.16 |
---|---|
[R Markdown] Markdown, DT datatable, dygraph 기본 옵션 (0) | 2021.04.29 |
[R Markdown] DT datatable in for loop showing white space after render to html (2) | 2021.04.29 |
[R Markdown] DT datatable 커스터마이징 :: 파라미터 알아보기 (2) | 2020.12.22 |
[R Markdown] toc customizing :: R 마크다운 목차 커스터마이징 (0) | 2019.12.23 |