重新排列多线图的颜色和图例,并更改图例图标

时间:2017-02-15 17:29:29

标签: r ggplot2 data.table

我有许多地理区域的数据,每个地理区域都有相关的描述和时间序列数据。例如:

---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()

结果:

sample plot

我想做两处修改:

  1. 通过数字而不是按字母顺序分配颜色 - 使“9(曼哈顿)”变为红色,“10(布朗克斯)”变为黄绿色,依此类推 - 同时保持自动调色板。我想避免使用scale_colour_manual()之类的手动颜色选择。我的实际数据有不同数量的区域,每个图表最多约20个。

  2. 将图例中的彩色图标从小写A更改为区域ID(因此红色9,绿黄色10等)。这样我就可以单独使用Region字段作为图例文本,而不是“ID(Region)”。

1 个答案:

答案 0 :(得分:1)

目前的标签是因为9:12的字母顺序为c("10", "11", "12", "9")。您可以手动更改它,也可以使用mixedsort中的gtools来执行此操作,此处使用dplyrmagrittr代替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)))

enter image description here

但是,你不能(据我所知)在形状中使用多个字符。所以,我诉诸于我的共同后退:将我想要的复杂传奇作为一个单独的情节生成,然后将它们与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)

给出

enter image description here

但是,我们可以使用rel_widths控制间距(您需要使用它来适应您的实际数据和宽高比):

plot_grid(plotPart
          , legendPart
          , rel_widths = c(0.9, 0.2)
          )

给出

enter image description here

我个人喜欢“挤压”传奇,所以我通常将传奇嵌套在另一个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)
)

给出

enter image description here

我相信哪些符合你提问的要求,但你仍然可能想要调整它以匹配你喜欢的风格等。