2016-05-17 69 views
8

我想在ggplot2中对色带进行着色。当使用geom_ribbon时,我可以指定ymin和ymax以及填充颜色。它现在做的是着色ymin和ymax之间的所有内容,而不考虑上限或下限。ggplot2:填充geom_ribbon的颜色行为

实施例(从因特网修改):

library("ggplot2") 
# Generate data (level2 == level1) 
huron <- data.frame(year = 1875:1972, level = as.vector(LakeHuron), level2 = as.vector(LakeHuron)) 

# Change Level2 
huron[1:50,2] <- huron[1:50,2]+100 
huron[50:90,2] <- huron[50:90,2]-100 

h <- ggplot(huron, aes(year)) 

h + 
    geom_ribbon(aes(ymin = level, ymax = level2), fill = "grey80") + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) 

将导致图表: enter image description here

我想填充的区域,其中(YMIN> YMAX),用不同的颜色比在哪里(ymin < ymax)。在我的真实数据中,我有导出和导入值。在那里,我想为出口高于进口绿色的区域着色,其中进口大于出口,我希望色带变红。

替代方案:我想geom_ribbon只填充该区域,其中ymax> ymin。

有人知道这是怎么完成的吗?

感谢您的帮助。

回答

7

不需要手动创建另一列的选项将会执行aes(fill =本身内的逻辑;

## fill dependent on level > level2 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = level > level2)) + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) + 
    scale_fill_manual(values=c("red", "green"), name="fill") 

filled conditional on level > level2

或者,如果你只是想基于该条件为真,以填补,

## fill dependent on level > level2, no fill otherwise 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = ifelse(level > level2, TRUE, NA))) + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) + 
    scale_fill_manual(values=c("green"), name="fill") 

filled conditional on level > level2, not otherwise

我认为缺少插值填充的,似乎有什么东西与ggplot2版本有关,因为我收到了@ beetroot的代码

## @beetroot's answer 
huron$id <- 1:nrow(huron) 
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year)) 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) + 
    geom_line(aes(y = level)) + geom_line(aes(y = level2))  

@beetroot's answer

aes(fill =运行没有逻辑的代码时,我得到@马努克的图像输出。

+0

哇,这太好了,非常感谢!它正是我想要的,因为我基本上可以将条件放入'fill ='中。不过,我会将我的更改请求打开,因为它不完美:填充无法完美应用于交点。 (这次对我来说没有问题)另外,我仍然认为ggplot2中的填充逻辑需要改变。 – ManuK

+0

超级有用!有什么方法可以用长格式的数据实现相同的结果?例如,您的数据设置为:Year,Level(1或2),Value。我可以得到:h + geom_line(aes(y = Value,group = Level),但我无法弄清楚如何在这个结构中添加geom_ribbon()图层 –

+1

不容易,我不认为'ggplot2'需要列,所以你需要有一个列作为'ymin'和'ymax'的值。'tidyr :: spread()'将你的长数据转换为所需的格式非常简单。 –

5

您可以将分组变量添加到可用于指定填充颜色的数据。然而,问题在于两条线相交的地方,因为它们需要被包括在两组中以防止任何间隙。

所以先找到该行..

huron[huron$level == huron$level2,] 

> huron[huron$level == huron$level2,] 
    year level level2 
50 1924 577.79 577.79 
... 

并将其添加到数据一次:

huron <- rbind(huron, huron[huron$year == 1924,]) 
huron <- huron[order(huron$year),] 

然后根据行索引添加一个id列,并设置基于组1924年全年的行号:

huron$id <- 1:nrow(huron) 
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year)) 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) + 
    geom_line(aes(y = level)) + geom_line(aes(y = level2)) 

enter image description here

+0

非常感谢你的回答,这个作品。在我的用例中,由于以下问题,它不是非常有用: 1.我想添加多个功能区,所以我需要添加相当多的“解决方法”列。 2.线条相遇的点在数据中并不真正可见,因此我需要计算这些点并将其添加到数据库中(两次)。我希望有一个简单的解决方案,但它似乎比一个简单的条件填充更复杂。 :-) – ManuK

+0

@ManuK是的,特别是2.问题很难解决,据我所知,不幸的是我目前无法帮助你。但也许别人会想出另一个答案?也许[这](https://learnr.wordpress.com/2009/10/22/ggplot2-two-color-xy-area-combo-chart/)博客文章给你一些想法 – beetroot

+0

我提交了作为一个功能的问题请求ggplot2 github。我希望它会在ggplot2的未来版本中实现[请求链接](https://github.com/hadley/ggplot2/issues/1642) – ManuK

1

四处逛逛,我与非插fill的问题,你可以使用两个(或n)色带

h <- ggplot() + 
    geom_ribbon(data = huron[huron$level >= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="green") + 
    geom_ribbon(data = huron[huron$level <= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="red") + 
    geom_line(data = huron, aes(x = year, y = level)) + 
    geom_line(data = huron, aes(x = year, y = level2)) 
h 

Fill is interpolated now

aes(fill =使用任何条件将其强制到因素,所以它似乎只适用于实际数据的地方。我不认为这是一个ggplot2错误,我认为这是预期的行为。