이번에 제가 책을 쓰면서 그동안 만들어 두었던 여러 함수들과 데이타들을 모아서 moonBook 이라는 패키지로 만들었읍니다. CRAN과 github에 등록했읍니다. CRAN에는 version 0.1.0이 등록되었고 github에는 version 0.1.1이 등록되었읍니다.최신 버젼에는 mytable의 결과를 html과 csv로 변환하는 함수가 포함되어 있으니 github을 통해 설치하시는 것을 권합니다. CRAN에는 다시 올렸는데 과거의 예로 보아 upversion이 등록되려면 하루이틀 걸리니 github을 통해 설치하시길 권합니다. 패키지를 설치하는 방법은 다음과 같습니다.
install.packages("devtools") # devtools가 설치되어 있지 않은 경우 설치
devtools::install_github("cardiomoon/moonBook")
하루이틀만 지나면 CRAN을 통해 하셔도 됩니다.
install.packages("moonBook")
이 패키지에는 두개의 데이타가 들어있읍니다. 하나는 급성관동맥증후군 환자의 데이타인 acs이고 또 하나는 요골동맥의 혈관내 초음파 데이타인 radial입니다. 이 패키지의 주요 기능은 descriptive statistics 표를 만들어주는 것입니다. 의학논문을 작성할때 결과의 첫번째 표에 해당됩니다. 예를 들어 acs데이타에서 진단명(Dx)에 따른 descriptive statistics를 표로 만들려면 다음과 같이 합니다. mytable()함수를 씁니다.
require(moonBook) # 패키지불러오기
data(acs) # 데이타 불러오기
mytable(Dx~age+sex,data=acs)
Descriptive Statistics by 'Dx'
_________________________________________________________
NSTEMI STEMI Unstable Angina p
(N=153) (N=304) (N=400)
---------------------------------------------------------
age 64.3 ± 12.3 62.1 ± 12.1 63.8 ± 11.0 0.073
sex 0.012
- Female 50 (32.7%) 84 (27.6%) 153 (38.2%)
- Male 103 (67.3%) 220 (72.4%) 247 (61.8%)
---------------------------------------------------------
이때 formula를 사용하는데 틸트표시(~)의 왼쪽은 그룹변수이고 오른쪽은 보고자하는 변수들을 넣어줍니다. 다 아시겠지만 “.”은 전부를 뜻하고 “+”,“-”를 쓸수 있읍니다. 데이타를 전부 보려면 다음과 같이 하면 됩니다.
res=mytable(Dx~.,data=acs)
version 0.1.1에는 이 표를 html형식의 표로 만들어주는 myhtml()함수와 csv화일로 만들어주는 mycsv() 함수가 포함되어 있읍니다.
myhtml(res)
Dx |
NSTEMI (N=153) |
STEMI (N=304) |
Unstable Angina (N=400) | p |
---|---|---|---|---|
age | 64.3 ± 12.3 | 62.1 ± 12.1 | 63.8 ± 11.0 | 0.073 |
sex | 0.012 | |||
| 50 (32.7%) | 84 (27.6%) | 153 (38.2%) | |
| 103 (67.3%) | 220 (72.4%) | 247 (61.8%) | |
cardiogenicShock | 0.000 | |||
| 149 (97.4%) | 256 (84.2%) | 400 (100.0%) | |
| 4 ( 2.6%) | 48 (15.8%) | 0 ( 0.0%) | |
entry | 0.001 | |||
| 58 (37.9%) | 133 (43.8%) | 121 (30.2%) | |
| 95 (62.1%) | 171 (56.2%) | 279 (69.8%) | |
EF | 55.0 ± 9.3 | 52.4 ± 9.5 | 59.2 ± 8.7 | 0.000 |
height | 163.3 ± 8.2 | 165.1 ± 8.2 | 161.7 ± 9.7 | 0.000 |
weight | 64.3 ± 10.2 | 65.7 ± 11.6 | 64.5 ± 11.6 | 0.361 |
BMI | 24.1 ± 3.2 | 24.0 ± 3.3 | 24.6 ± 3.4 | 0.064 |
obesity | 0.186 | |||
| 106 (69.3%) | 209 (68.8%) | 252 (63.0%) | |
| 47 (30.7%) | 95 (31.2%) | 148 (37.0%) | |
TC | 193.7 ± 53.6 | 183.2 ± 43.4 | 183.5 ± 48.3 | 0.057 |
LDLC | 126.1 ± 44.7 | 116.7 ± 39.5 | 112.9 ± 40.4 | 0.004 |
HDLC | 38.9 ± 11.9 | 38.5 ± 11.0 | 37.8 ± 10.9 | 0.501 |
TG | 130.1 ± 88.5 | 106.5 ± 72.0 | 137.4 ± 101.6 | 0.000 |
DM | 0.209 | |||
| 96 (62.7%) | 208 (68.4%) | 249 (62.2%) | |
| 57 (37.3%) | 96 (31.6%) | 151 (37.8%) | |
HBP | 0.002 | |||
| 62 (40.5%) | 150 (49.3%) | 144 (36.0%) | |
| 91 (59.5%) | 154 (50.7%) | 256 (64.0%) | |
smoking | 0.000 | |||
| 42 (27.5%) | 66 (21.7%) | 96 (24.0%) | |
| 50 (32.7%) | 97 (31.9%) | 185 (46.2%) | |
| 61 (39.9%) | 141 (46.4%) | 119 (29.8%) |
기존에 있었던 compareGroups라는 패키지에서 영감을 많이 얻었는데 compareGroups패키지의 경우 combined table을 만들려면 조금 복잡했읍니다. 제가 만든 mytable()함수는 combined table을 아주 쉽게 만들 수 있읍니다. 예를 들어 전체 환자를 성별로 나누고 남자 데이타, 여자데이타를 따로 당뇨 유무에 따라 표를 만들려면 다음과 같이 하면 됩니다.
res1=mytable(sex+DM~.,data=acs)
res1
Descriptive Statistics stratified by 'sex' and 'DM'
_____________________________________________________________________________________
Male Female
-------------------------------- -------------------------------
No Yes p No Yes p
(N=380) (N=190) (N=173) (N=114)
-------------------------------------------------------------------------------------
age 60.9 ± 11.5 60.1 ± 10.6 0.472 69.3 ± 11.4 67.8 ± 9.7 0.257
cardiogenicShock 0.685 0.296
- No 355 (93.4%) 175 (92.1%) 168 (97.1%) 107 (93.9%)
- Yes 25 ( 6.6%) 15 ( 7.9%) 5 ( 2.9%) 7 ( 6.1%)
entry 0.552 0.665
- Femoral 125 (32.9%) 68 (35.8%) 74 (42.8%) 45 (39.5%)
- Radial 255 (67.1%) 122 (64.2%) 99 (57.2%) 69 (60.5%)
Dx 0.219 0.240
- NSTEMI 71 (18.7%) 32 (16.8%) 25 (14.5%) 25 (21.9%)
- STEMI 154 (40.5%) 66 (34.7%) 54 (31.2%) 30 (26.3%)
- Unstable Angina 155 (40.8%) 92 (48.4%) 94 (54.3%) 59 (51.8%)
EF 56.5 ± 8.3 53.9 ± 11.0 0.007 56.0 ± 10.1 56.6 ± 10.0 0.655
height 168.1 ± 5.8 167.5 ± 6.7 0.386 153.9 ± 6.5 153.6 ± 5.8 0.707
weight 68.1 ± 10.4 69.8 ± 10.2 0.070 56.5 ± 8.7 58.4 ± 10.0 0.106
BMI 24.0 ± 3.1 24.9 ± 3.5 0.005 23.8 ± 3.2 24.8 ± 4.0 0.046
obesity 0.027 0.359
- No 261 (68.7%) 112 (58.9%) 121 (69.9%) 73 (64.0%)
- Yes 119 (31.3%) 78 (41.1%) 52 (30.1%) 41 (36.0%)
TC 184.1 ± 46.7 181.8 ± 44.5 0.572 186.0 ± 43.1 193.3 ± 60.8 0.274
LDLC 117.9 ± 41.8 112.1 ± 39.4 0.115 116.3 ± 35.2 119.8 ± 48.6 0.519
HDLC 38.4 ± 11.4 36.8 ± 9.6 0.083 39.2 ± 10.9 38.8 ± 12.2 0.821
TG 115.2 ± 72.2 153.4 ± 130.7 0.000 114.2 ± 82.4 128.4 ± 65.5 0.112
HBP 0.000 0.356
- No 205 (53.9%) 68 (35.8%) 54 (31.2%) 29 (25.4%)
- Yes 175 (46.1%) 122 (64.2%) 119 (68.8%) 85 (74.6%)
smoking 0.386 0.093
- Ex-smoker 101 (26.6%) 54 (28.4%) 34 (19.7%) 15 (13.2%)
- Never 77 (20.3%) 46 (24.2%) 118 (68.2%) 91 (79.8%)
- Smoker 202 (53.2%) 90 (47.4%) 21 (12.1%) 8 ( 7.0%)
-------------------------------------------------------------------------------------
myhtml(res1)
sex | Male | Female | ||||
---|---|---|---|---|---|---|
DM |
No (N=380) |
Yes (N=190) | p |
No (N=173) |
Yes (N=114) | p |
age | 60.9 ± 11.5 | 60.1 ± 10.6 | 0.472 | 69.3 ± 11.4 | 67.8 ± 9.7 | 0.257 |
cardiogenicShock | 0.685 | 0.296 | ||||
| 355 (93.4%) | 175 (92.1%) | 168 (97.1%) | 107 (93.9%) | ||
| 25 ( 6.6%) | 15 ( 7.9%) | 5 ( 2.9%) | 7 ( 6.1%) | ||
entry | 0.552 | 0.665 | ||||
| 125 (32.9%) | 68 (35.8%) | 74 (42.8%) | 45 (39.5%) | ||
| 255 (67.1%) | 122 (64.2%) | 99 (57.2%) | 69 (60.5%) | ||
Dx | 0.219 | 0.240 | ||||
| 71 (18.7%) | 32 (16.8%) | 25 (14.5%) | 25 (21.9%) | ||
| 154 (40.5%) | 66 (34.7%) | 54 (31.2%) | 30 (26.3%) | ||
| 155 (40.8%) | 92 (48.4%) | 94 (54.3%) | 59 (51.8%) | ||
EF | 56.5 ± 8.3 | 53.9 ± 11.0 | 0.007 | 56.0 ± 10.1 | 56.6 ± 10.0 | 0.655 |
height | 168.1 ± 5.8 | 167.5 ± 6.7 | 0.386 | 153.9 ± 6.5 | 153.6 ± 5.8 | 0.707 |
weight | 68.1 ± 10.4 | 69.8 ± 10.2 | 0.070 | 56.5 ± 8.7 | 58.4 ± 10.0 | 0.106 |
BMI | 24.0 ± 3.1 | 24.9 ± 3.5 | 0.005 | 23.8 ± 3.2 | 24.8 ± 4.0 | 0.046 |
obesity | 0.027 | 0.359 | ||||
| 261 (68.7%) | 112 (58.9%) | 121 (69.9%) | 73 (64.0%) | ||
| 119 (31.3%) | 78 (41.1%) | 52 (30.1%) | 41 (36.0%) | ||
TC | 184.1 ± 46.7 | 181.8 ± 44.5 | 0.572 | 186.0 ± 43.1 | 193.3 ± 60.8 | 0.274 |
LDLC | 117.9 ± 41.8 | 112.1 ± 39.4 | 0.115 | 116.3 ± 35.2 | 119.8 ± 48.6 | 0.519 |
HDLC | 38.4 ± 11.4 | 36.8 ± 9.6 | 0.083 | 39.2 ± 10.9 | 38.8 ± 12.2 | 0.821 |
TG | 115.2 ± 72.2 | 153.4 ± 130.7 | 0.000 | 114.2 ± 82.4 | 128.4 ± 65.5 | 0.112 |
HBP | 0.000 | 0.356 | ||||
| 205 (53.9%) | 68 (35.8%) | 54 (31.2%) | 29 (25.4%) | ||
| 175 (46.1%) | 122 (64.2%) | 119 (68.8%) | 85 (74.6%) | ||
smoking | 0.386 | 0.093 | ||||
| 101 (26.6%) | 54 (28.4%) | 34 (19.7%) | 15 (13.2%) | ||
| 77 (20.3%) | 46 (24.2%) | 118 (68.2%) | 91 (79.8%) | ||
| 202 (53.2%) | 90 (47.4%) | 21 (12.1%) | 8 ( 7.0%) |
위의 명령어는 아래와 같이 한줄로 써도 되지만 저는 위와 같이 두줄로 쓰는 것을 선호합니다.
myhtml(mytable(sex+Dx~age+DM+HBP,data=acs))
sex | Male | Female | ||||||
---|---|---|---|---|---|---|---|---|
Dx |
NSTEMI (N=103) |
STEMI (N=220) |
Unstable Angina (N=247) | p |
NSTEMI (N=50) |
STEMI (N=84) |
Unstable Angina (N=153) | p |
age | 61.1 ± 11.6 | 59.4 ± 11.7 | 61.4 ± 10.6 | 0.133 | 70.9 ± 11.4 | 69.1 ± 10.4 | 67.7 ± 10.7 | 0.177 |
DM | 0.219 | 0.240 | ||||||
| 71 (68.9%) | 154 (70.0%) | 155 (62.8%) | 25 (50.0%) | 54 (64.3%) | 94 (61.4%) | ||
| 32 (31.1%) | 66 (30.0%) | 92 (37.2%) | 25 (50.0%) | 30 (35.7%) | 59 (38.6%) | ||
HBP | 0.016 | 0.084 | ||||||
| 43 (41.7%) | 122 (55.5%) | 108 (43.7%) | 19 (38.0%) | 28 (33.3%) | 36 (23.5%) | ||
| 60 (58.3%) | 98 (44.5%) | 139 (56.3%) | 31 (62.0%) | 56 (66.7%) | 117 (76.5%) |
mylatex 함수는 출력물의 폰트 크기를 조절할 수 있읍니다.
out=mytable(sex~age+Dx,data=acs)
for(i in c(3,5))
mylatex(out,size=i,caption=paste("Table ",i,". Fontsize=",i,sep=""))
mylatex(mytable(sex+DM~age+Dx,data=acs),size=4)
그 외에도 유용한 plot들을 만들어주는 함수들도 몇 개 있는데 하나만 소개하면 다음과 같습니다.
densityplot(age~sex,data=acs)
out=mytable(sex~age+Dx,data=acs)
myhtml(out)
sex |
Female (N=287) |
Male (N=570) | p |
---|---|---|---|
age | 68.7 ± 10.7 | 60.6 ± 11.2 | 0.000 |
Dx | 0.012 | ||
| 50 (17.4%) | 103 (18.1%) | |
| 84 (29.3%) | 220 (38.6%) | |
| 153 (53.3%) | 247 (43.3%) |
myhtml(mytable(sex+DM~age+Dx,data=acs))
sex | Male | Female | ||||
---|---|---|---|---|---|---|
DM |
No (N=380) |
Yes (N=190) | p |
No (N=173) |
Yes (N=114) | p |
age | 60.9 ± 11.5 | 60.1 ± 10.6 | 0.472 | 69.3 ± 11.4 | 67.8 ± 9.7 | 0.257 |
Dx | 0.219 | 0.240 | ||||
| 71 (18.7%) | 32 (16.8%) | 25 (14.5%) | 25 (21.9%) | ||
| 154 (40.5%) | 66 (34.7%) | 54 (31.2%) | 30 (26.3%) | ||
| 155 (40.8%) | 92 (48.4%) | 94 (54.3%) | 59 (51.8%) |
csv화일로 만들 때는 다음과 같이 하면 됩니다.
mycsv(out,file="test.csv")
생존분석에 쓰이는 cox proportional hazard model을 자동화하는 함수 mycph()와 hazard ratio를 쉽게 plot하는 HRplot함수도 만들었읍니다.
require(survival)
attach(colon)
colon$TS=Surv(time,status==1)
out=mycph(TS~.,data=colon)
mycph : perform coxph of individual expecting variables
Call: TS ~ ., data= colon
study was excluded : NaN
status was excluded : infinite
out
HR lcl ucl p
id 1.00 1.00 1.00 0.317
rxLev 0.98 0.84 1.14 0.786
rxLev+5FU 0.64 0.55 0.76 0.000
sex 0.97 0.85 1.10 0.610
age 1.00 0.99 1.00 0.382
obstruct 1.27 1.09 1.49 0.003
perfor 1.30 0.92 1.85 0.142
adhere 1.37 1.16 1.62 0.000
nodes 1.09 1.08 1.10 0.000
differ 1.36 1.19 1.55 0.000
extent 1.78 1.53 2.07 0.000
surg 1.28 1.11 1.47 0.001
node4 2.47 2.17 2.83 0.000
time 0.98 0.98 0.98 0.000
etype 0.81 0.71 0.92 0.001
HRplot(out)
HRplot(out,type=2,show.CI=TRUE,pch=2,sig=0.05)
HRplot(out,type=3,show.CI=TRUE,pch=2,cex=2,sig=0.05,
main="Hazard ratios of significant variables")