#r #dataframe #ggplot2 #plot
#r #фрейм данных #ggplot2 #график
Вопрос:
Я хочу объединить два ggplots с двумя калибровочными графиками, созданными riskRegression
в.
Я пробовал много подходов, например par(mfrow)
(см. Ниже), но потерпел неудачу. Я считаю, что должен быть способ комбинировать ggplots
с другими графиками таким par(mfrow=c(2,2))
образом.
Вопрос: почему этот подход недействителен и как его можно исправить?
Образец данных o
можно найти ниже.
Я использую
library(riskRegression)
library(survival)
library(tidyverse)
Сначала выполните калибровку
i <- Score(list("WHO w/o TERT" = coxph(Surv(event.tid, event==1) ~ WHO, data=o, x=T, y=T),
"WHO TERT " = coxph(Surv(event.tid, event==1) ~ WHO tert.mut, data=o, x=T, y=T)),
Surv(event.tid, event==1)~1,
data=o,
times=c(60,90),
plots = "calibration",
summary="risks")
Затем два калибровочных графика
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=60,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
И
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=90,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
А затем два ggplot
ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==60),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
И
ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==90),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
Попытка # 1
par(mfrow=c(2,2), mai=c(.65,.75,.3,.3))
# the first two goes well
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=60,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=90,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
# here it goes wrong
ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==60),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==90),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
Попытка # 2 создавала a ggarrange
для объединения с par(mfrow)
, что также не удалось.
Ожидаемый результат
Образец данных
o <- structure(list(event.tid = c(56, 127, 29.6, 18, 13.2, 41, 96,
146.83, 45.37, 1, 105.29, 55, 13.84, 12, 26, 10.8, 1, 7.2, 22.68,
59, 16, 8.4, 75.3, 25.7, 13, 21, 19, 22, 48, 93, 26, 72, 73.5,
125, 31, 63, 2.02, 28.2, 2, 8, 60, 46.7, 53, 4, 85, 12, 75.9,
1, 5, 2.5), event = c(0, 0, 1, 1, 1, 0, 0, 2, 1, 2, 0, 0, 1,
1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 2, 0,
0, 0, 1, 0, 0, 1, 2, 0, 0, 1, 0, 1, 0, 2, 0, 1), WHO = structure(c(3L,
3L, 3L, 2L, 3L, 2L, 3L, 2L, 3L, 3L, 3L, 1L, 2L, 1L, 2L, 3L, 2L,
3L, 2L, 3L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L,
3L, 2L, 1L, 3L, 2L, 2L, 2L, 1L, 2L, 3L, 2L, 2L, 3L, 1L, 2L, 3L,
2L), .Label = c("WHO-I", "WHO-II", "WHO-III"), class = "factor"),
tert.mut = structure(c(1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L), .Label = c("0",
"1"), class = "factor")), row.names = c(NA, -50L), class = "data.frame")
Комментарии:
1. Вы пробовали
patchwork
пакет?2. Привет @markus. Да, но я не смог заставить его работать. Вы можете отправить ответ, используя patchwork.
Ответ №1:
Вот один из используемых подходов cowplot
.
Вы можете использовать as_grob
для преобразования своих plotCalibration
графиков в grob, которые можно комбинировать с вашими 2 ggplots.
Вы можете дополнительно настроить свои калибровочные графики, добавив базовые графические операторы R в свои функции.
С plot_grid
помощью from cowplot
вы можете поместить свои графики 2×2 в упорядоченную форму, в данном случае с 2 строками 2 столбцами.
library(riskRegression)
library(survival)
library(tidyverse)
library(cowplot)
i <- Score(list("WHO w/o TERT" = coxph(Surv(event.tid, event==1) ~ WHO, data=o, x=T, y=T),
"WHO TERT " = coxph(Surv(event.tid, event==1) ~ WHO tert.mut, data=o, x=T, y=T)),
Surv(event.tid, event==1)~1,
data=o,
times=c(60,90),
plots = "calibration",
summary="risks")
make_pc1 <- function() {
par(mgp=c(4,1,0), mar=c(5,6,4,2) 0.1, cex.lab=1.4, cex.axis=1.5)
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=60,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
mtext("10-year prediction", adj=0.05, line = -1.4, cex=1, font=2)
}
pc1 <- as_grob(make_pc1)
make_pc2 <- function() {
par(mgp=c(4,1,0), mar=c(5,6,4,2) 0.1, cex.lab=1.4, cex.axis=1.5)
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=90,
col=c("#6DBCC3","#8B3A62"),
ylab="Observed frequency",
xlab="Predicted risk of recurrence",
auc.in.legend = TRUE)
mtext("10-year prediction", adj=0.05, line = -1.4, cex=1, font=2)
}
pc2 <- as_grob(make_pc2)
gg1 <- ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==60),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
gg2 <- ggplot(arrange(o, event.tid) %>%
transmute(ID = 1:nrow(o),
WHO = WHO,
tert.mut = tert.mut) %>%
left_join(i$Calibration$plotframe,
.,
by="ID") %>%
select(ID, times, model, risk, WHO, tert.mut) %>%
pivot_wider(names_from = model, values_from = risk) %>%
rename(., "woTERT" = "WHO w/o TERT", "wTERT" = "WHO TERT ") %>%
filter(times==90),
aes(x=woTERT, y=wTERT, shape=WHO, col=tert.mut, fill=tert.mut))
geom_point(size = 7)
# Draw all 4 plots
plot_grid(pc1, pc2, gg1, gg2, ncol = 2)
График
Немного изменив интервал между графиками калибровки (например, используя title
для меток осей и корректируя mgp
линию полей заголовка оси), вы можете сделать:
make_pc1 <- function() {
par(mar=c(5,6,4,2) 0.1, cex.lab=1.4, cex.axis=1.5)
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=60,
col=c("#6DBCC3","#8B3A62"),
ylab="",
xlab="",
auc.in.legend = TRUE)
mtext("10-year prediction", adj=0.05, line = -1.4, cex=1, font=2)
title(ylab = "Observed frequency", mgp = c(4.5,1,0))
title(xlab = "Predicted risk of recurrence", mgp = c(2.5,1,0))
}
pc1 <- as_grob(make_pc1)
make_pc2 <- function() {
par(mar=c(5,6,4,2) 0.1, cex.lab=1.4, cex.axis=1.5)
plotCalibration(i,
cens.method = "local",
legend.x=.215,
legend.y=.225,
cex=1,
times=90,
col=c("#6DBCC3","#8B3A62"),
ylab="",
xlab="",
auc.in.legend = TRUE)
mtext("10-year prediction", adj=0.05, line = -1.4, cex=1, font=2)
title(ylab = "Observed frequency", mgp = c(4.5,1,0))
title(xlab = "Predicted risk of recurrence", mgp = c(2.5,1,0))
}
pc2 <- as_grob(make_pc2)
# Draw all 4 plots
plot_grid(pc1, pc2, gg1, gg2, ncol = 2)
График
Комментарии:
1. Спасибо @Ben. Это очень приятно. Я пытаюсь добавить
mtext
кplotCalibration
afteras.grob
— т.е.pc1 mtext("10-year prediction", adj=0.05, line = -1.4, cex=1, font=2)
. Однако это приводит к ошибке :non-numeric argument to binary operator
. Возможно ли добавитьmtext
объект -object вas.grob
-plot?2. @cmirian Смотрите отредактированный ответ. Я разместил функции
plotCalibration
in, в которые вы можете добавлять все, что вам нравится (например,mtext
иpar
). Возможно, вам потребуется внести незначительные коррективы. Он также используетas_grob
(с подчеркиванием) fromcowplot
для создания grobs. Надеюсь, это полезно.3. Спасибо @Ben, ваши ответы всегда полезны. Я вознагражу вас щедростью, как только это будет возможно.
4. Я не совсем уверен, что вы имеете в виду, но, полагаю, вы чувствуете, что высота графика мала для калибровочных графиков (по крайней мере, по сравнению с другими 2-мя графиками). Если это так, вы можете уменьшить поля… например, чтобы уменьшить верхнюю границу графика калибровки, попробуйте
par(mar=c(5,6,1,2) 0.1...
(«1» вместо «4» будет иметь большое значение). Вы можете поэкспериментировать,mar
а такжеmgp
получить желаемый вид. Часть компромисса здесь заключается в том, что у вас очень большие метки осей и тиков, которые тоже занимают место.5. Или,
mar=c(4,6,1,2)
и уменьшение нижнего поля тоже выглядит неплохо…