ggplot2:将图例分成两列,每列都有自己的图案 [英] ggplot2: Divide Legend into Two Columns, Each with Its Own TItle

查看:4041
本文介绍了ggplot2:将图例分成两列,每列都有自己的图案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这些因素

  require(ggplot2)
名称(表格(钻石$ cut))
#[1]FairGoodVery GoodPremiumIdeal

我想在视觉上将它们分成两组(即组名):

First group - >Fair,Good





<第二组> - >非常好,高级,理想 p>

从此图开始

  ggplot(aes,aes(color,fill = cut))+ geom_bar()+ 
guides(fill = guide_legend(ncol = 2))+
theme(legend.position =bottom)



我想要得到




(请注意,非常好在第二列/组中滑落)

解决方案

您可以将Very Good类别移至图例的第二列添加一个虚拟因子水平,并在图例中将其颜色设置为白色,以使其无法看到。在下面的代码中,我们在良好和非常好之间添加了一个空白因子级别,所以现在我们有六个级别。然后,我们使用 scale_fill_manual 将此空白级别的颜色设置为白色。 drop = FALSE 强制 ggplot 来保持图例中的空白级别。可能有一种更优雅的方式来控制 ggplot 放置图例值的位置,但至少可以完成任务。

 钻石$ cut =因子(钻石$ cut,levels = c(Fair,Good,,Very Good,
Premium ,理想))

ggplot(aes(color,fill = cut))+ geom_bar()+
scale_fill_manual(values = c(hcl(seq(15,325,length。 (seq(15,325,length.out = 5),100,65)[3:5]),其中, ,
drop = FALSE)+
guides(fill = guide_legend(ncol = 2))+
theme(legend.position =bottom)



更新:我希望有更好的方式为图例中的每个组添加标题,但是我可以提供的唯一选项现在是度假哼唱,这总是让我头痛。下面的代码是根据这个SO问题的答案进行调整的。它添加了两个文本库,每个标签一个,但标签必须用手定位,这是一个巨大的痛苦。剧情的代码也必须修改,以创造更多的传奇空间。另外,即使我已经关闭所有grob的剪辑,标签仍然被传说grob剪辑。您可以将标签放置在裁剪区域外,但距离图例太远。我希望有人真的知道如何使用grobs可以解决这个问题,并且通常会改进下面的代码(@baptiste,你在那里?)。

  library(gtable)

p = ggplot(diamonds,aes(color,fill = cut)) + geom_bar()+
scale_fill_manual(values = c(hcl(seq(15,325,length.out = 5),100,65)[1:2],
white,
hcl(seq(15,325,length.out = 5),100,65)[3:5]),
drop = FALSE)+
guides(fill = guide_legend(ncol = 2))+
主题(legend.position = c(0.5,-0.26),
plot.margin =单位(c(1,1,7,1),lines))+
labs(填充=)

#添加两个文本grobs
p = p + annotation_custom(
grob = textGrob(label =First \\\ Group,
hjust = 0.5,gp = gpar(cex = 0.7)),
ymin = -2200,ymax = -2200,xmin = 3.45,xmax = 3.45)+
annotation_custom(
grob = textGrob =Second \ Group,
hjust = 0.5,gp = gpar(cex = 0.7)),
ymin = -2200,ymax = -2200,xmin = 4.2,xmax = 4.2)

#覆盖剪切
gt< - ggplot_gtable(ggplot_build(p))
gt $ layout $ clip< - off
grid.draw(gt)

以下是结果:


I have these factors

require(ggplot2)
names(table(diamonds$cut))
# [1] "Fair"      "Good"      "Very Good" "Premium"   "Ideal" 

which I want to visually divide into two groups in the legend (indicating also the group name):

"First group" -> "Fair", "Good"

and

"Second group" -> "Very Good", "Premium", "Ideal"

Starting with this plot

ggplot(diamonds, aes(color, fill=cut)) + geom_bar() + 
  guides(fill=guide_legend(ncol=2)) +
  theme(legend.position="bottom")

I want to get

(note that "Very Good" slipped in the second column/group)

解决方案

You can shift the "Very Good" category to the second column of the legend by adding a dummy factor level and setting its colour to white in the legend, so that it can't be seen. In the code below, we add a blank factor level between "Good" and "Very Good", so now we have six levels. Then, we use scale_fill_manual to set the color of this blank level to "white". drop=FALSE forces ggplot to keep the blank level in the legend. There might be a more elegant way to control where ggplot places the legend values, but at least this will get the job done.

diamonds$cut = factor(diamonds$cut, levels=c("Fair","Good"," ","Very Good",
                                             "Premium","Ideal"))

ggplot(diamonds, aes(color, fill=cut)) + geom_bar() + 
  scale_fill_manual(values=c(hcl(seq(15,325,length.out=5), 100, 65)[1:2], 
                             "white",
                             hcl(seq(15,325,length.out=5), 100, 65)[3:5]),
                    drop=FALSE) +
  guides(fill=guide_legend(ncol=2)) +
  theme(legend.position="bottom")

UPDATE: I'm hoping there's a better way to add titles to each group in the legend, but the only option I can come up with for now is to resort to grobs, which always gives me a headache. The code below is adapted from the answer to this SO question. It adds two text grobs, one for each label, but the labels have to be positioned by hand, which is a huge pain. The code for the plot also has to be modified to create more room for the legend. In addition, even though I've turned off clipping for all grobs, the labels are still clipped by the legend grob. You can position the labels outside of the clipped area, but then they're too far from the legend. I'm hoping someone who really knows how to work with grobs can fix this and more generally improve upon the code below (@baptiste, are you out there?).

library(gtable)

p = ggplot(diamonds, aes(color, fill=cut)) + geom_bar() + 
  scale_fill_manual(values=c(hcl(seq(15,325,length.out=5), 100, 65)[1:2], 
                             "white",
                             hcl(seq(15,325,length.out=5), 100, 65)[3:5]),
                    drop=FALSE) +
  guides(fill=guide_legend(ncol=2)) +
  theme(legend.position=c(0.5,-0.26),  
        plot.margin=unit(c(1,1,7,1),"lines")) +
  labs(fill="") 

# Add two text grobs
p = p + annotation_custom(
    grob = textGrob(label = "First\nGroup", 
                    hjust = 0.5, gp = gpar(cex = 0.7)),
    ymin = -2200, ymax = -2200, xmin = 3.45, xmax = 3.45) +
  annotation_custom(
    grob = textGrob(label = "Second\nGroup",
                    hjust = 0.5, gp = gpar(cex = 0.7)),
    ymin = -2200, ymax = -2200, xmin = 4.2, xmax = 4.2)

# Override clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip <- "off"
grid.draw(gt)

And here's the result:

这篇关于ggplot2:将图例分成两列,每列都有自己的图案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆