ggplot2:手动添加图例

时间:2016-01-16 16:30:28

标签: r ggplot2 legend

如何将任何(不相关)的图例映射到现有的ggplot?

免责声明:请不要讨厌我。我知道使用' ggplot2'创建图例的最佳方式。是正确地映射您的数据,我99%的时间都这样做。然而,我要求的东西通常可以给我任何我想要的传奇。

作为一个例子,我有一个看起来有点像这样的情节: enter image description here

从此代码创建:

set.seed(42)
temp1 = cbind.data.frame(begin = rnorm(10, 0, 1), end = rnorm(10, 2, 1), y1 = 1:10, y2 = 1:10, id = as.character(1:10))
temp2 = cbind.data.frame(x = 0:2, y = 1:3*2)
temp3 = cbind.data.frame(x = seq(0.5, 1.5, 0.33))
temp = c()
plot1 = ggplot(data = temp, aes(x = x)) + 
  geom_vline(data = temp3, aes(xintercept = x), color = "red", linetype = "longdash") + 
  geom_segment(data = temp1, aes(y = y1, yend = y2, x = begin, xend = end, color = id)) +
  geom_point(data = temp2, aes(x = x, y = y), shape = 4, size = 4) +
  scale_color_discrete(guide = F) 
plot1

我想添加一个包含以下内容的图例:

  • 一条红色的,垂直的垂直线,名为" l1"
  • 黑色,实心的水平线,称为" l2"
  • 一个名为" l3"
  • 的绿色填充块

理想情况下,我会产生这样的(伪代码):

plot2 = plot1 + guide(elements = list(list(type = "line", color = "red", linetype = "longdash", direction = "vertical", label = "l1"), list(type = "line", label = "l2"), list(type = "rect", fill = "green", label = "l3"))

我最好的猜测如何处理这个问题就是创建一些辅助的伪数据temp,它绘制/映射到某个地方看不见的地方,然后用于创建图例,但我没有成功获得任何东西像这样给我画一个传奇。

再一次,我的想法是如何在现有情节中添加任何不相关的图例,即没有将原始数据巧妙地映射到情节变量?

1 个答案:

答案 0 :(得分:3)

可以从头开始构建图例:使用gtable构建图例元素;然后使用set.seed(42) temp1 = cbind.data.frame(begin = rnorm(10, 0, 1), end = rnorm(10, 2, 1), y1 = 1:10, y2 = 1:10, id = as.character(1:10)) temp2 = cbind.data.frame(x = 0:2, y = 1:3*2) temp3 = cbind.data.frame(x = seq(0.5, 1.5, 0.33)) temp = c() library(ggplot2) library(grid) library(gtable) plot1 = ggplot(data = temp, aes(x = x)) + geom_vline(data = temp3, aes(xintercept = x), color = "red", linetype = "longdash") + geom_segment(data = temp1, aes(y = y1, yend = y2, x = begin, xend = end, color = id)) + geom_point(data = temp2, aes(x = x, y = y), shape = 4, size = 4) + scale_color_discrete(guide = F) # Construct the six grobs - three symbols and three labels L1 = linesGrob(x = unit(c(.5, .5), "npc"), y = unit(c(.25, .75), "npc"), gp = gpar(col = "red", lty = "longdash")) L2 = linesGrob(x = unit(c(.25, .75), "npc"), y = unit(c(.5, .5), "npc")) L3 = rectGrob(height = .5, width = .5, gp = gpar(fill = "green", col = NA)) T1 = textGrob("l1", x = .2, just = "left") T2 = textGrob("l2", x = .2, just = "left") T3 = textGrob("l3", x = .2, just = "left") # Construct a gtable - 2 columns X 4 rows leg = gtable(width = unit(c(1,1), "cm"), height = unit(c(1,1,1,1), "cm")) leg = gtable_add_grob(leg, rectGrob(gp = gpar(fill = NA, col = "black")), t=2,l=1,b=4,r=2) # Place the six grob into the table leg = gtable_add_grob(leg, L1, t=2, l=1) leg = gtable_add_grob(leg, L2, t=3, l=1) leg = gtable_add_grob(leg, L3, t=4, l=1) leg = gtable_add_grob(leg, T1, t=2, l=2) leg = gtable_add_grob(leg, T2, t=3, l=2) leg = gtable_add_grob(leg, T3, t=4, l=2) # Give it a title (if needed) leg = gtable_add_grob(leg, textGrob("Legend"), t=1, l=1, r=2) # Get the ggplot grob for plot1 g = ggplotGrob(plot1) # Get the position of the panel, # add a column to the right of the panel, # put the legend into that column, # and then add another spacing column pos = g$layout[grepl("panel", g$layout$name), c('t', 'l')] g = gtable_add_cols(g, sum(leg$widths), pos$l) g = gtable_add_grob(g, leg, t = pos$t, l = pos$l + 1) g = gtable_add_cols(g, unit(6, "pt"), pos$l) # Draw it grid.newpage() grid.draw(g) 定位图例中的元素和图中的图例。这有点粗糙,但给出了一般的想法。

CREATE TABLE Customer
(    CustomerID INT IDENTITY (1000,1)
    ,FirstName VARCHAR(40)
    ,RegDate DATETIME DEFAULT GETDATE()
    ,Phone VARCHAR(10)
);

CREATE TABLE Expense
(    ExpenseID INT IDENTITY (1000,1)
    ,CustomerID INT NOT NULL
    ,ExpDate DATETIME DEFAULT GETDATE()
    ,Amount MONEY
    ,Comment VARCHAR (100)
);

CREATE TABLE TblLoad
(    LoadID INT IDENTITY (1000,1) --PRIMARY KEY 
    ,CustomerID INT NOT NULL
    ,DepDate DATETIME DEFAULT GETDATE()
    ,Amount MONEY
    ,FromTo VARCHAR (100)
);




select Customer.CustomerID, Customer.FirstName, Expense.Amount As ExpenseAmount from Customer inner join 
Expense on Customer.CustomerID = Expense.CustomerID
WHERE Customer.CustomerID = 1000

select Customer.CustomerID, Customer.FirstName, TblLoad.Amount As LoadAmount from Customer inner join 
TblLoad on Customer.CustomerID = TblLoad.CustomerID
WHERE Customer.CustomerID = 1000

SELECT Customer.CustomerID, Customer.FirstName, e.SE as AmountExp , l.SL as AmountLoad , (l.SL - e.SE) as FinalPay
FROM Customer 
INNER JOIN (SELECT CustomerID, SUM(Amount) AS SE FROM Expense GROUP BY CustomerID) E
ON Customer.CustomerID = e.CustomerID
INNER JOIN (SELECT CustomerID, SUM(Amount) AS SL FROM TblLoad GROUP BY CustomerID) L
ON Customer.CustomerID = l.CustomerID
WHERE Customer.CustomerID = 1000

enter image description here