我有许多地理区域的数据,每个地理区域都有相关的描述和时间序列数据。例如:
---in file "data.csv":
ID,Region,Year,Value
9,Manhattan,2010,5
9,Manhattan,2011,6
10,Brooklyn,2010,6
10,Brooklyn,2011,7
11,Bronx,2010,8
11,Bronx,2011,6
12,New Jersey,2010,7
12,New Jersey,2011,5
(此表格是通过重塑每个区域一行的早期表格形成的,但这与此处无关。)我想用ggplot2
绘制此数据,并在图例中包含ID和说明。这是我最好的尝试:
#! /usr/bin/env RSCRIPT
library(data.table)
library(ggplot2)
dt <- fread("data.csv")[,Label:=paste(ID, " (", Region, ")", sep="")]
png("plot.png")
gg <- ggplot(data=dt,aes(x=Year,y=Value,group=ID,colour=Label)) +
geom_line() + geom_label(aes(label=ID))
print(gg)
dev.off()
结果:
我想做两处修改:
通过数字而不是按字母顺序分配颜色 - 使“9(曼哈顿)”变为红色,“10(布朗克斯)”变为黄绿色,依此类推 - 同时保持自动调色板。我想避免使用scale_colour_manual()
之类的手动颜色选择。我的实际数据有不同数量的区域,每个图表最多约20个。
将图例中的彩色图标从小写A更改为区域ID(因此红色9,绿黄色10等)。这样我就可以单独使用Region字段作为图例文本,而不是“ID(Region)”。
答案 0 :(得分:1)
目前的标签是因为9:12
的字母顺序为c("10", "11", "12", "9")
。您可以手动更改它,也可以使用mixedsort
中的gtools
来执行此操作,此处使用dplyr
和magrittr
代替data.table
:
dt %<>%
mutate(Label = paste0(dt$ID, " (", dt$Region, ")") %>%
factor(levels = mixedsort(unique(.))))
更改图例中的标签有点困难,主要是因为它们有两个字符(而不是一个)。如果您的标签都是单个字符,您可以执行以下操作:
ggplot(data=dt,aes(x=Year,y=Value,group=ID,colour=Label)) +
geom_line(show.legend = FALSE) +
geom_point() +
geom_label(aes(label=ID), show.legend = FALSE) +
guides(color = guide_legend(override.aes = list(shape = c("A","B","C","D")
, size = 3)))
但是,你不能(据我所知)在形状中使用多个字符。所以,我诉诸于我的共同后退:将我想要的复杂传奇作为一个单独的情节生成,然后将它们与cowplot
拼接在一起。
首先,存储您想要制作的情节,不带传奇
plotPart <-
ggplot(data=dt,aes(x=Year,y=Value,group=ID,colour=Label)) +
geom_line() +
geom_label(aes(label=ID)) +
theme(legend.position = "none")
然后,修改原始数据以限制每个区域只有一个条目,区域作为因子与标签的顺序相同(此处使用dplyr
但您可以修改为使用data.table
而不是)。将其传递到ggplot
并生成所需的布局。我的左侧区域仍然是,但您可以使用scale_y_discrete(position = "right")
将它们移到右侧。
legendPart <-
dt %>%
select(ID, Region, Label) %>%
filter(!duplicated(.)) %>%
arrange(desc(ID)) %>%
mutate(Region = factor(Region, levels = Region)) %>%
ggplot(
aes(x = 1
, y = Region
, color = Label
, label = ID)) +
geom_label() +
theme(legend.position = "none"
, axis.title = element_blank()
, axis.text.x = element_blank()
, axis.ticks.x = element_blank()
, panel.grid = element_blank()
)
然后,加载cowplot
。请注意,它会重置默认theme
,因此您需要使用cowplot
手动覆盖它(除非您喜欢theme_set
主题):
library(cowplot)
theme_set(theme_minimal())
然后,使用plot_grid
将所有东西拼接在一起。最简单的版本没有参数,但看起来不太好:
plot_grid(plotPart, legendPart)
给出
但是,我们可以使用rel_widths
控制间距(您需要使用它来适应您的实际数据和宽高比):
plot_grid(plotPart
, legendPart
, rel_widths = c(0.9, 0.2)
)
给出
我个人喜欢“挤压”传奇,所以我通常将传奇嵌套在另一个plot_grid
电话中,这里包括一个好的标题:
plot_grid(
plotPart
, plot_grid(
ggdraw()
, ggdraw() + draw_label("Legend")
, legendPart
, ggdraw()
, rel_heights = c(1,1,3,2)
, ncol = 1
)
, rel_widths = c(0.9, 0.2)
)
给出
我相信哪些符合你提问的要求,但你仍然可能想要调整它以匹配你喜欢的风格等。