简体   繁体   English

在ggplot2中添加手动图例?

[英]Adding a manual legend in ggplot2?

I'm doing a comparison chart of two different estimates of the same time series data. 我正在对相同时间序列数据的两个不同估计进行比较图表。 I'm filling the area between the two series in green if the original estimate is more than the latest estimate, and red otherwise. 如果原始估计值超过最新估计值,我将以绿色填充两个系列之间的区域,否则为红色。

I've got that part working, but I'd like to add a legend for the fill colors. 我已经完成了该部分的工作,但是我想为填充颜色添加一个图例。 I tried scale_fill_manual towards the bottom of the code, but it doesn't seem to be doing anything? 我尝试将scale_fill_manual放在代码的底部,但它似乎没有做任何事情?

Here's the code: 这是代码:

library(ggplot2)
library(scales)
library(colorspace)

# Return a polygon that only plots between yLower and yUpper when yLower is
# less than yUpper.
getLowerPolygon = function(x, yLower, yUpper) {
    # Create the table of coordinates
    poly = data.frame(
        x = numeric(),
        y = numeric())

    lastReversed = (yUpper[1] < yLower[1])
    for (r in 1:length(x)) {
        reversed = (yUpper[r] < yLower[r])
        if (reversed != lastReversed) {
            # Between points r-1 and r, the series intersected, so we need to
            # change the polygon from visible to invisible or v.v.  In either
            # case, just add the intersection between those two segments to the
            # polygon.  Algorithm from:
            # https://en.wikipedia.org/wiki/Line-line_intersection
            # First line: x1,y1 - x2,y2
            x1 = x[r-1]
            y1 = yLower[r-1]
            x2 = x[r]
            y2 = yLower[r]
            # Second line: x3,y3 - x4,y4
            x3 = x[r-1]
            y3 = yUpper[r-1]
            x4 = x[r]
            y4 = yUpper[r]
            # Calculate determinants
            xy12 = det(matrix(c(x1, y1, x2, y2), ncol = 2))
            xy34 = det(matrix(c(x3, y3, x4, y4), ncol = 2))
            x12  = det(matrix(c(x1,  1, x2,  1), ncol = 2))
            x34  = det(matrix(c(x3,  1, x4,  1), ncol = 2))
            y12  = det(matrix(c(y1,  1, y2,  1), ncol = 2))
            y34  = det(matrix(c(y3,  1, y4,  1), ncol = 2))
            # Calculate fraction pieces
            xn = det(matrix(c(xy12, x12, xy34, x34), ncol = 2))
            yn = det(matrix(c(xy12, y12, xy34, y34), ncol = 2))
            d  = det(matrix(c(x12 , y12,  x34, y34), ncol = 2))
            # Calculate intersection
            xi = xn / d
            yi = yn / d
            # Add the point
            poly[nrow(poly)+1,] = c(xi, yi)
        }
        lastReversed = reversed
        # http://stackoverflow.com/questions/2563824
        poly[nrow(poly)+1,] = c(x[r], min(yLower[r], yUpper[r]))
    }

    poly = rbind(poly, data.frame(
        x = rev(x),
        y = rev(yUpper)))

    return(poly)
}

getComparisonPlot = function(data, title, lower_name, upper_name,
                         x_label, y_label, legend_title = '') {

    lightGreen = '#b0dd8d'
    lightRed   = '#fdba9a'

    darkGray = RGB(.8, .8, .8)
    midGray  = RGB(.5, .5, .5)

    plot = ggplot(data, aes(x = x))

    plot = plot + geom_polygon(
        aes(x = x, y = y),
        data = data.frame(
            x = c(data$x, rev(data$x)),
            y = c(data$yLower, rev(data$yUpper))
        ),
        fill = lightRed)

    coords = getLowerPolygon(data$x, data$yLower, data$yUpper)

    plot = plot + geom_polygon(
        aes(x = x, y = y),
        data = coords,
        fill = lightGreen)

    plot = plot + geom_line(
        aes(y = yUpper, color = 'upper'),
        size = 0.5)

    plot = plot + geom_line(
        aes(y = yLower, color = 'lower'),
        size = 0.5)

    plot = plot +
        ggtitle(paste(title, '\n', sep='')) +
        xlab(x_label) +
        ylab(y_label) +
        scale_y_continuous(labels = comma)

    # http://stackoverflow.com/a/10355844/106302
    plot = plot + scale_color_manual(
        name   = legend_title,
        breaks = c('upper' , 'lower'),
        values = c('gray20', 'gray50'),
        labels = c(upper_name, lower_name))

    plot = plot + scale_fill_manual(
        name   = 'Margin',
        breaks = c('upper', 'lower'),
        values = c(lightGreen, lightRed),
        labels = c('Over', 'Under'))

    return(plot)
}

print(getComparisonPlot(
    data = data.frame(
        x = 1:20,
        yLower = 1:20 %% 5 + 2,
        yUpper = 1:20 %% 7
    ),
    title = 'Comparison Chart',
    lower_name = 'Latest',
    upper_name = 'Original',
    x_label = 'X axis',
    y_label = 'Y axis',
    legend_title = 'Thing'
))

Here's an image of the chart, I think it is a cool technique: 这是图表的图像,我认为这是一种很酷的技巧:

比较表

I'm also open to any other suggestions for improving my ggplot code. 我也对改进我的ggplot代码的任何其他建议持开放态度。

GGplot need you to map polygons fill aesthetic to some variable. GGplot需要您将多边形fillfill到某些变量。 OR, in this case, it need just you to "label" the types of polygons (ie 'upper' and 'lower'). 或者,在这种情况下,只需要“标记”多边形的类型(即“上”和“下”)即可。 You do this by passing a string with the respective label for the fill aesthetic of geom_polygon(). 您可以通过传递一个字符串来执行此操作,该字符串具有geom_polygon()的填充美学的相应标签。 What you are doing is passing a giving colour for each polygon and not mapping to anything that the ggplot will understand. 你正在做的是传递每个多边形的给定颜色,而不是映射到ggplot将理解的任何东西。 It's kind of a "hard coded colour" =P. 它是一种“硬编码颜色”= P.

Well, here are the changes inside getComparisonPlot : 好吧,以下是getComparisonPlot中的更改:

plot = plot + geom_polygon(
    aes(x = x, y = y, fill = "upper"),
    data = coords)

plot = plot + geom_polygon(
    aes(x = x, y = y, fill = "lower"),
    data = data.frame(
      x = c(data$x, rev(data$x)),
      y = c(data$yLower, rev(data$yUpper))
    ))

One more thing. 还有一件事。 Note that the strings passed to fill aesthetic coincides with the breaks passed to the scale_fill_manual. 请注意,传递给fill美学的字符串与传递给scale_fill_manual的中断重合。 It is necessary to make the legend map things right. 有必要使传奇地图正确。

plot = plot + scale_fill_manual(
    name   = 'Margin',
    breaks = c('upper', 'lower'), # <<< corresponds to fill aesthetic labels
    values = c(lightGreen, lightRed),
    labels = c('Over', 'Under'))

Result: 结果:

在此输入图像描述

hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM