Ggplot2 несколько шкал/легенд на эстетический, пересмотренный
У меня есть пример, где я хотел бы выделить несколько свойств выравниваний последовательностей с помощью ggplot. Я использую geom_tile и хочу иметь два набора разноцветных плит для двух свойств оценки. Я могу только визуализировать его.
Я знаю об ограничении одной шкалы за эстетику (и ее логике), но, возможно, у кого-то есть идея, как взломать ее для таких случаев где было бы разумно иметь разные цветовые шкалы в одном "сюжете".
Возможно, с добавлением вручную Grobs, но я не знаю, с чего начать...
дополнительный вопрос: по какой-то причине override.aes=list(shape = "A")
не работает, какие-либо идеи почему?
еще один: любой способ масштабирования текста пропорционально размеру плитки (или наоборот)?
library(ggplot2)
library(grid)
pd = data.frame(
letters = strsplit("AGTGACCGACTATCATAGTGACCCAGAATCATAGTGACCGAGTATGAT", "")[[1]],
species = rep(c("Human", "Armadillo", "Porcupine"), each=16),
x = rep(1:16, 3),
change = c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0),
score1 = c(0,0,0,0,0,0,1,1,2,2,2,3,3,3,4,3,
0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
score2 = c(0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,
0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0)
)
ggplot(pd[pd$score1 != 0,], aes(x=x, y=species)) +
coord_fixed(ratio = 1.5, xlim=c(0.5,16.5), ylim=c(0.5, 3.5)) +
geom_tile(aes(fill=score1)) +
scale_fill_gradient2("Score 1", limits=c(0,4),low="#762A83", mid="white", high="#1B7837", guide=guide_colorbar(title.position="top")) +
geom_text(data=pd, aes(label=letters, color=factor(change)), size=rel(5), family="mono") +
scale_color_manual("Change", values=c("black", "#F2A11F"), labels=c("None", "Some"), guide=guide_legend(direction="vertical", title.position="top", override.aes=list(shape = "A"))) +
theme(panel.background=element_rect(fill="white", colour="white"),
axis.title = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_text(family="mono", size=rel(2)),
axis.text.x = element_text(size=rel(0.7)),
legend.text = element_text(size=rel(0.7)),
legend.key.size = unit(0.7, "lines"),
legend.position = "bottom", legend.box = "horizontal") +
ggtitle("What about Score2?")
![How to add another layer of tiles with different color scale?]()
Ответы
Ответ 1
Мне удалось получить удовлетворительный результат, объединив грифы из двух отдельно созданных графиков. Я уверен, что решение может быть обобщено лучше для размещения разных индексов grob...
library(ggplot2)
library(grid)
pd = data.frame(
letters = strsplit("AGTGACCGACTATCATAGTGACCCAGAATCATAGTGACCGAGTATGAT", "")[[1]],
species = rep(c("Human", "Armadillo", "Porcupine"), each=16),
x = rep(1:16, 3),
change = c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0),
score1 = c(0,0,0,0,0,0,1,1,2,2,2,3,3,3,4,3,
0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
score2 = c(0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,
0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0)
)
p1=ggplot(pd[pd$score1 != 0,], aes(x=x, y=species)) +
coord_fixed(ratio = 1.5, xlim=c(0.5,16.5), ylim=c(0.5, 3.5)) +
geom_tile(aes(fill=score1)) +
scale_fill_gradient2("Score 1", limits=c(0,4),low="#762A83", mid="white", high="#1B7837", guide=guide_colorbar(title.position="top")) +
geom_text(data=pd, aes(label=letters, color=factor(change)), size=rel(5), family="mono") +
scale_color_manual("Change", values=c("black", "#F2A11F"), labels=c("None", "Some"), guide=guide_legend(direction="vertical", title.position="top", override.aes=list(shape = "A"))) +
theme(panel.background=element_rect(fill="white", colour="white"),
axis.title = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_text(family="mono", size=rel(2)),
axis.text.x = element_text(size=rel(0.7)),
legend.text = element_text(size=rel(0.7)),
legend.key.size = unit(0.7, "lines"),
legend.position = "bottom", legend.box = "horizontal") +
ggtitle("Voila, the Score2!")
p2=ggplot(pd[pd$score2 != 0,], aes(x=x, y=species)) +
coord_fixed(ratio = 1.5, xlim=c(0.5,16.5), ylim=c(0.5, 3.5)) +
geom_tile(aes(fill=score2)) +
scale_fill_gradient2("Score 2", limits=c(0,3),low="#1B7837", mid="white", high="#762A83", guide=guide_colorbar(title.position="top")) +
geom_text(data=pd, aes(label=letters, color=factor(change)), size=rel(5), family="mono") +
scale_color_manual("Change", values=c("black", "#F2A11F"), labels=c("None", "Some"), guide=guide_legend(direction="vertical", title.position="top", override.aes=list(shape = "A"))) +
theme(panel.background=element_rect(fill="white", colour="white"),
axis.title = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_text(family="mono", size=rel(2)),
axis.text.x = element_text(size=rel(0.7)),
legend.text = element_text(size=rel(0.7)),
legend.key.size = unit(0.7, "lines"),
legend.position = "bottom", legend.box = "horizontal") +
ggtitle("What about Score2?")
p1g=ggplotGrob(p1)
p2g=ggplotGrob(p2)
combo.grob = p1g
combo.grob$grobs[[8]] = cbind(p1g$grobs[[8]][,1:4],
p2g$grobs[[8]][,3:5],
size="first")
combo.grob$grobs[[4]] = reorderGrob(
addGrob(p1g$grobs[[4]],
getGrob(p2g$grobs[[4]],
"geom_rect.rect",
grep=TRUE)),
c(1,2,5,3,4))
grid.newpage()
grid.draw(combo.grob)
![Two scales in one plot]()
Ответ 2
Я бы использовал размер текста для указания score2:
ggplot(pd[pd$score1 != 0,], aes(x=x, y=species)) +
coord_fixed(ratio = 1.5, xlim=c(0.5,16.5), ylim=c(0.5, 3.5)) +
geom_tile(aes(fill=score1)) +
scale_fill_gradient2("Score 1", limits=c(0,4),low="#762A83", mid="white", high="#1B7837", guide=guide_colorbar(title.position="top")) +
geom_text(data=pd, aes(label=letters, size = score2, color=factor(change)), family="mono") +
scale_size_continuous(range = c(4, 8)) +
scale_color_manual("Change", values=c("black", "#F2A11F"), labels=c("None", "Some"), guide=guide_legend(direction="vertical", title.position="top", override.aes=list(shape = "A"))) +
theme(panel.background=element_rect(fill="white", colour="white"),
axis.title = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_text(family="mono", size=rel(2)),
axis.text.x = element_text(size=rel(0.7)),
legend.text = element_text(size=rel(0.7)),
legend.key.size = unit(0.7, "lines"),
legend.position = "bottom", legend.box = "horizontal") +
ggtitle("What about Score2?")
![enter image description here]()
ОБНОВЛЕНО:
Вот быстрый хак, я не уверен, что это легко проверить визуально, хотя...
library(ggplot2)
library(grid)
library(proto)
GeomTile2 <- proto(ggplot2:::GeomTile, {
reparameterise <- function(., df, params) {
df <- .$.super$reparameterise(df, params)
if (params$ud == "u")
transform(df, ymin = y)
else
transform(df, ymax = (y-ymin)*0.8 + ymin, ymin = (y-ymin)*0.2 + ymin)
}
draw <- function(..., ud) {.$.super$draw(..., ud)}
})
geom_tile2 <- function (mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., ud = "u") {
GeomTile2$new(mapping = mapping, data = data, stat = stat, position = position, ..., ud = ud)
}
ggplot(pd, aes(x=x, y=species)) +
coord_fixed(ratio = 1.5, xlim=c(0.5,16.5), ylim=c(0.5, 3.5)) +
geom_tile2(aes(fill=score1), ud = "u") +
geom_tile2(aes(fill = score2), ud = "d") +
scale_fill_gradient2("Score 1", limits=c(0,4),low="#762A83", mid="white", high="#1B7837", guide=guide_colorbar(title.position="top")) +
geom_text(data=pd, aes(label=letters, color=factor(change)), size=rel(5), family="mono") +
scale_color_manual("Change", values=c("black", "#F2A11F"), labels=c("None", "Some"), guide=guide_legend(direction="vertical", title.position="top", override.aes=list(shape = "A"))) +
theme(panel.background=element_rect(fill="white", colour="white"),
axis.title = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_text(family="mono", size=rel(2)),
axis.text.x = element_text(size=rel(0.7)),
legend.text = element_text(size=rel(0.7)),
legend.key.size = unit(0.7, "lines"),
legend.position = "bottom", legend.box = "horizontal") +
ggtitle("What about Score2?")
![enter image description here]()
Верхняя половина указывает счет 1, а нижний - на счет 2.