[R] CONSORT flow chart 그리기

임상시험이라고 불리는 randomized controlled trial (RCT) 는 의학 연구에 있어서 높은 수준의 근거를 생산하는 연구 방법입니다.
그 결과를 보고하는 데 있어서도 철저한 기준에 따라야만 인정을 받을 수가 있습니다.
CONSORT (CONsolidated Standards Of Reporting Trials) 는 그러한 기준을 제시하고 있는데, 많은 의학 학술지들이 이를 채택하고 있습니다.

그 중 RCT 에서 환자를 모집하고 연구를 진행하여 최종적으로 분석하기까지의 흐름을 보여주는 flow diagram 을 보여줘야만 하는데요, R 로 이를 그려 보고자 삽질에 착수해 보았습니다.

예시는 다음과 같습니다.

CONSORT flow chart template

이와 같은 그림을 그려야만 하는데… 쉽지 않았습니다. 아주 만족스럽진 않지만 상당히 많은 시행착오 끝에 성공하였습니다.

DiagrammeR 이라는 패키지를 이용하였는데요, 설치되어 있지 않다면 물론 일단

install.packages("DiagrammeR")

이렇게 설치를 하셔야겠죠.

DiagrammeR 패키지는 상당히 다양한 기능과 복잡한 문법을 지니고 있습니다. 솔직히 도큐먼트들만 보고 도대체 잘 파악이 안되더군요.
grViz 란 함수를 이용하면 비교적 알아먹을만 한 정도로 차트 그리기 위한 코딩을 할 수는 있었는데, 간단한 차트를 그리기는 쉽지만, 세밀한 콘트롤은 쉽지는 않았습니다.

참고로 한 웹사이트는 바로 요기 입니다. grViz 활용에 대해서 그나마 가장 자세히 나와 있는 것 같네요.

Node 를 만들고 연결하는 데 좀 이상해 보이는 게 있으실 겁니다만 그렇게 해야만 원하는 결과를 얻을 수 있다는 거…! 혹 사용하고 싶은데 이해가 영 안가시면 질문하시면 답변해드리겠습니다. 더 이상의 자세한 설명은 생략… ^^;;;;;

결과물은 웹 브라우저에 보여지는데, 이걸 직접 export 할 방법이 없다는 게 문제입니다. 할 수 없이 화면 캡쳐한 다음 잘라서 그림 파일로 저장해야 한다는…

이와 같은 챠트가 그려집니다.

코드는 다음과 같습니다.


#### Drawing CONSORT flow chart
library(DiagrammeR)

n_screened <- 148
n_screen_failed <- 3
n_randomized <- 145
n_g1 <- 71
n_g2 <- 74
n_do_g1 <- 6
n_do_g2 <- 8
n_g1_final <- 65
n_g2_final <- 66

fl_chart_values <- c(
    n_screened, n_screen_failed, n_randomized, n_g1, n_g2,
    n_do_g1, n_do_g2, n_g1_final, n_g2_final
)

intervention_1  <- "Single-pill group"
intervention_2  <- "Two-pill group"

# Defining Text Labels
text_labels <- c('Assessment for\neligibility',
          'Excluded',
          'Randomized',
          paste0('Allocated to\n', intervention_1),
          paste0('Allocated to\n', intervention_2),
          'Lost to follow-up',
          'Lost to follow-up',
          'Analysed',
          'Analysed')

# Defining Function for labels
paste1 <- function(x, y){
  paste0(x, ' (n=', y, ')')
}

grViz("
digraph randomization_chart {
graph [layout = dot]

## Main boxes
node [fontname = Helvetica, fontsize = 15, width = 3, shape = rectangle]
B1 [label = '@@1']
B2 [label = '@@2']
B3 [label = '@@3']
B4 [label = '@@4']
B5 [label = '@@5']
B6 [label = '@@6']
B7 [label = '@@7']
B8 [label = '@@8']
B9 [label = '@@9']

## Boxes for step label
node [fontsize = 12, shape = oval, style = filled, color = grey, width = 1]
S1 [label = 'Enrollment']
S2 [label = 'Allocation']
S3 [label = 'Follow up']
S4 [label = 'Analysis']

## Invisible point node for joints
node [shape = point, width = 0]
P1 P2 P3 P4

subgraph {
  rank = same; rankdir = LR; S1; B1;
}

subgraph {
  rank = same; rankdir = LR; P1; B2;
}

subgraph {
  rank = same; rankdir = LR; P2; P3; P4;
}

S1 -> B1 [arrowhead = none, penwidth = 0];
B1 -> P1 [arrowhead = none];
P1 -> B2;
P1 -> B3;
B3 -> P3;
S1 -> P2 [arrowhead = none, penwidth = 0]; # needed to perpendicular column arrangement
P2 -> P3 -> P4 [arrowhead = none, minlen = 10]; # minlen: for balanced bifurcation
P2 -> B4 -> B6 -> B8;
P3 -> S2 -> S3 -> S4 [arrowhead = none, penwidth = 0];
P4 -> B5 -> B7 -> B9;
}

[1]: paste1(text_labels[1], n_screened)
[2]: paste1(text_labels[2], n_screen_failed)
[3]: paste1(text_labels[3], n_randomized)
[4]: paste1(text_labels[4], n_g1)
[5]: paste1(text_labels[5], n_g2)
[6]: paste1(text_labels[6], n_do_g1)
[7]: paste1(text_labels[7], n_do_g2)
[8]: paste1(text_labels[8], n_g1_final)
[9]: paste1(text_labels[9], n_g2_final)
")

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다