Rで、論文とかによくある表1相当を簡単につくるパッケージの{tableone}
で作成される、Overallを任意の文字列に変える方法のメモ。
とりあえず簡単に自作関数化したのでおいておく。
tableone.overall.rename <- function(x, rename.str){ if(class(x) != "TableOne"){ warning("The class is not TableOne, so it cannot be handled.") }else{ if(names(x[["ContTable"]])[1] != "Overall" || names(x[["CatTable"]])[1] != "Overall"){ warning("There is no Overall in the table to rename.") }else{ names(x[["ContTable"]])[1] <- rename.str names(x[["CatTable"]])[1] <- rename.str } } x }
例えば、次のように表1相当のデータを作る({tableone}
のCreateTableOne()
のExamples
のコードの一部改変)。
library(tableone) library(survival) data(pbc) varsToFactor <- c("status","trt","ascites","hepato","spiders","edema","stage") pbc[varsToFactor] <- lapply(pbc[varsToFactor], factor) vars <- c("time","status","age","sex","ascites","hepato", "spiders","edema","bili","chol","albumin", "copper","alk.phos","ast","trig","platelet", "protime","stage") # addOverallでOverall(全体)の列を作成する。 tableOne <- CreateTableOne(vars = vars, strata = c("trt"), data = pbc, addOverall = TRUE)
中身を見てみると次のとおりになる。
tableOne
## Stratified by trt
## Overall 1 2
## n 418 158 154
## time (mean (SD)) 1917.78 (1104.67) 2015.62 (1094.12) 1996.86 (1155.93)
## status (%)
## 0 232 (55.5) 83 (52.5) 85 (55.2)
## 1 25 ( 6.0) 10 ( 6.3) 9 ( 5.8)
## 2 161 (38.5) 65 (41.1) 60 (39.0)
## age (mean (SD)) 50.74 (10.45) 51.42 (11.01) 48.58 (9.96)
## sex = f (%) 374 (89.5) 137 (86.7) 139 (90.3)
## ascites = 1 (%) 24 ( 7.7) 14 ( 8.9) 10 ( 6.5)
## hepato = 1 (%) 160 (51.3) 73 (46.2) 87 (56.5)
## spiders = 1 (%) 90 (28.8) 45 (28.5) 45 (29.2)
## edema (%)
## 0 354 (84.7) 132 (83.5) 131 (85.1)
## 0.5 44 (10.5) 16 (10.1) 13 ( 8.4)
## 1 20 ( 4.8) 10 ( 6.3) 10 ( 6.5)
## bili (mean (SD)) 3.22 (4.41) 2.87 (3.63) 3.65 (5.28)
## chol (mean (SD)) 369.51 (231.94) 365.01 (209.54) 373.88 (252.48)
## albumin (mean (SD)) 3.50 (0.42) 3.52 (0.44) 3.52 (0.40)
## copper (mean (SD)) 97.65 (85.61) 97.64 (90.59) 97.65 (80.49)
## alk.phos (mean (SD)) 1982.66 (2140.39) 2021.30 (2183.44) 1943.01 (2101.69)
## ast (mean (SD)) 122.56 (56.70) 120.21 (54.52) 124.97 (58.93)
## trig (mean (SD)) 124.70 (65.15) 124.14 (71.54) 125.25 (58.52)
## platelet (mean (SD)) 257.02 (98.33) 258.75 (100.32) 265.20 (90.73)
## protime (mean (SD)) 10.73 (1.02) 10.65 (0.85) 10.80 (1.14)
## stage (%)
## 1 21 ( 5.1) 12 ( 7.6) 4 ( 2.6)
## 2 92 (22.3) 35 (22.2) 32 (20.8)
## 3 155 (37.6) 56 (35.4) 64 (41.6)
## 4 144 (35.0) 55 (34.8) 54 (35.1)
## Stratified by trt
## p test
## n
## time (mean (SD)) 0.883
## status (%) 0.894
## 0
## 1
## 2
## age (mean (SD)) 0.018
## sex = f (%) 0.421
## ascites = 1 (%) 0.567
## hepato = 1 (%) 0.088
## spiders = 1 (%) 0.985
## edema (%) 0.877
## 0
## 0.5
## 1
## bili (mean (SD)) 0.131
## chol (mean (SD)) 0.748
## albumin (mean (SD)) 0.874
## copper (mean (SD)) 0.999
## alk.phos (mean (SD)) 0.747
## ast (mean (SD)) 0.460
## trig (mean (SD)) 0.886
## platelet (mean (SD)) 0.555
## protime (mean (SD)) 0.197
## stage (%) 0.201
## 1
## 2
## 3
## 4
“全体”の項目が“Overall”となっている。これを任意の文字列(今回はALL)に書き換える。
# 一番最初に書いた自作関数を使う。 tableOne <- tableone.overall.rename(tableOne, "ALL") # 内容を表示する。 tableOne
## Stratified by trt
## ALL 1 2
## n 418 158 154
## time (mean (SD)) 1917.78 (1104.67) 2015.62 (1094.12) 1996.86 (1155.93)
## status (%)
## 0 232 (55.5) 83 (52.5) 85 (55.2)
## 1 25 ( 6.0) 10 ( 6.3) 9 ( 5.8)
## 2 161 (38.5) 65 (41.1) 60 (39.0)
## age (mean (SD)) 50.74 (10.45) 51.42 (11.01) 48.58 (9.96)
## sex = f (%) 374 (89.5) 137 (86.7) 139 (90.3)
## ascites = 1 (%) 24 ( 7.7) 14 ( 8.9) 10 ( 6.5)
## hepato = 1 (%) 160 (51.3) 73 (46.2) 87 (56.5)
## spiders = 1 (%) 90 (28.8) 45 (28.5) 45 (29.2)
## edema (%)
## 0 354 (84.7) 132 (83.5) 131 (85.1)
## 0.5 44 (10.5) 16 (10.1) 13 ( 8.4)
## 1 20 ( 4.8) 10 ( 6.3) 10 ( 6.5)
## bili (mean (SD)) 3.22 (4.41) 2.87 (3.63) 3.65 (5.28)
## chol (mean (SD)) 369.51 (231.94) 365.01 (209.54) 373.88 (252.48)
## albumin (mean (SD)) 3.50 (0.42) 3.52 (0.44) 3.52 (0.40)
## copper (mean (SD)) 97.65 (85.61) 97.64 (90.59) 97.65 (80.49)
## alk.phos (mean (SD)) 1982.66 (2140.39) 2021.30 (2183.44) 1943.01 (2101.69)
## ast (mean (SD)) 122.56 (56.70) 120.21 (54.52) 124.97 (58.93)
## trig (mean (SD)) 124.70 (65.15) 124.14 (71.54) 125.25 (58.52)
## platelet (mean (SD)) 257.02 (98.33) 258.75 (100.32) 265.20 (90.73)
## protime (mean (SD)) 10.73 (1.02) 10.65 (0.85) 10.80 (1.14)
## stage (%)
## 1 21 ( 5.1) 12 ( 7.6) 4 ( 2.6)
## 2 92 (22.3) 35 (22.2) 32 (20.8)
## 3 155 (37.6) 56 (35.4) 64 (41.6)
## 4 144 (35.0) 55 (34.8) 54 (35.1)
## Stratified by trt
## p test
## n
## time (mean (SD)) 0.883
## status (%) 0.894
## 0
## 1
## 2
## age (mean (SD)) 0.018
## sex = f (%) 0.421
## ascites = 1 (%) 0.567
## hepato = 1 (%) 0.088
## spiders = 1 (%) 0.985
## edema (%) 0.877
## 0
## 0.5
## 1
## bili (mean (SD)) 0.131
## chol (mean (SD)) 0.748
## albumin (mean (SD)) 0.874
## copper (mean (SD)) 0.999
## alk.phos (mean (SD)) 0.747
## ast (mean (SD)) 0.460
## trig (mean (SD)) 0.886
## platelet (mean (SD)) 0.555
## protime (mean (SD)) 0.197
## stage (%) 0.201
## 1
## 2
## 3
## 4
これでOverallを任意の文字列に変えることが簡単にできる。
簡単な説明
{tableone}
のCreateTableOne()
は、与えられたデータをいい感じにまとめて最終的にlist形式にまとめている。
Overallはこのとき、listの中の[["ContTable"]]
の1番目(つまり[["ContTable"]][1]
)と[["CatTable"]]
の1番目(つまり[[“CatTable”]])[1]
)に名前付きで格納されているのでこの名前を任意のものにすると、出力するときの名前も変更した任意のものになる。
この手法は、任意の層の名前も任意の名前に変える方法にも使える。また、この方法はstrata
で層化していないときのOverallにも使える。
そもそも{tableone}
で層化したときにも全体(Overall)を表示する方法をメモしておく
{tableone}
では特にstrata
を指定しなければOverallとして全体のみが集計される。
# IRISデータの表1を作る CreateTableOne(data = iris)
##
## Overall
## n 150
## Sepal.Length (mean (SD)) 5.84 (0.83)
## Sepal.Width (mean (SD)) 3.06 (0.44)
## Petal.Length (mean (SD)) 3.76 (1.77)
## Petal.Width (mean (SD)) 1.20 (0.76)
## Species (%)
## setosa 50 (33.3)
## versicolor 50 (33.3)
## virginica 50 (33.3)
ここでstrata
を指定すると指定した値で層化した表1が出る。
# 種別に層化して表1を作る CreateTableOne(data = iris, strata = "Species")
## Stratified by Species
## setosa versicolor virginica p
## n 50 50 50
## Sepal.Length (mean (SD)) 5.01 (0.35) 5.94 (0.52) 6.59 (0.64) <0.001
## Sepal.Width (mean (SD)) 3.43 (0.38) 2.77 (0.31) 2.97 (0.32) <0.001
## Petal.Length (mean (SD)) 1.46 (0.17) 4.26 (0.47) 5.55 (0.55) <0.001
## Petal.Width (mean (SD)) 0.25 (0.11) 1.33 (0.20) 2.03 (0.27) <0.001
## Species (%) <0.001
## setosa 50 (100.0) 0 ( 0.0) 0 ( 0.0)
## versicolor 0 ( 0.0) 50 (100.0) 0 ( 0.0)
## virginica 0 ( 0.0) 0 ( 0.0) 50 (100.0)
## Stratified by Species
## test
## n
## Sepal.Length (mean (SD))
## Sepal.Width (mean (SD))
## Petal.Length (mean (SD))
## Petal.Width (mean (SD))
## Species (%)
## setosa
## versicolor
## virginica
ここで、全体を表示するには、addOverall
をTRUE
とするとよい。この表だとよくわからないが、p値は層化されたグループのみで計算されたものにちゃんとなっているとのこと。
CreateTableOne(data = iris, strata = "Species", addOverall = TRUE)
## Stratified by Species
## Overall setosa versicolor
## n 150 50 50
## Sepal.Length (mean (SD)) 5.84 (0.83) 5.01 (0.35) 5.94 (0.52)
## Sepal.Width (mean (SD)) 3.06 (0.44) 3.43 (0.38) 2.77 (0.31)
## Petal.Length (mean (SD)) 3.76 (1.77) 1.46 (0.17) 4.26 (0.47)
## Petal.Width (mean (SD)) 1.20 (0.76) 0.25 (0.11) 1.33 (0.20)
## Species (%)
## setosa 50 (33.3) 50 (100.0) 0 ( 0.0)
## versicolor 50 (33.3) 0 ( 0.0) 50 (100.0)
## virginica 50 (33.3) 0 ( 0.0) 0 ( 0.0)
## Stratified by Species
## virginica p test
## n 50
## Sepal.Length (mean (SD)) 6.59 (0.64) <0.001
## Sepal.Width (mean (SD)) 2.97 (0.32) <0.001
## Petal.Length (mean (SD)) 5.55 (0.55) <0.001
## Petal.Width (mean (SD)) 2.03 (0.27) <0.001
## Species (%) <0.001
## setosa 0 ( 0.0)
## versicolor 0 ( 0.0)
## virginica 50 (100.0)
この関数のヘルプドキュメントから引用の説明を下に示しておく。
addOverall
(optional, only used if strata are supplied) Adds an overall column to the table. Smd and p-value calculations are performed using only the stratifed clolumns.
(CreateTableOne {tableone} R Documentation)
とのことで層化された部分のみでp値等が計算されているとのこと。
雑感
{tableone}
は使ったことがなかったが、人に{tableone}
の表のことについて聞かれて調べていて、(聞かれたことと全く関係ないが)Overallの文字列を変えるすべがわからなかった(もしかしたらドキュメントのどこかに書いてあるかもしれないが)。
別に変える必要性は今のところないが、力技で直接出力結果のリストの名前を変えることにした。
2021/04/07追記:パッケージ化した
今までブログ上で書き散らかした関数(以外もある)を少し関数名や細かい挙動を調整して、上記の関数もまとめたものをパッケージ化してGitHubからインストールできるようにした(GitHubでソースコードを管理したいだけ)。
install.packages("remotes") remotes::install_github("indenkun/infun")
でインストールできる。詳しくはないが関数の紹介はREADMEに書いたつもり。
自分で使いたい関数をパッケージ化した感じで今後も適当に自分で使いたい関数があれば適宜入れていく。自作関数であっても汎用性があるものは適宜パッケージ化したほうが名前空間的にいいし、Rスクリプトファイルの紛失が防げる。
:追記終了