4

我正在创建类似于下面第一个示例图像的图,并且需要类似于下面第二个示例的图。

library(ggplot2)
library(scales)

# some data
data.2015 = data.frame(score = c(-50,20,15,-40,-10,60),
                       area = c("first","second","third","first","second","third"),
                       group = c("Findings","Findings","Findings","Benchmark","Benchmark","Benchmark"))

data.2014 = data.frame(score = c(-30,40,-15),
                       area = c("first","second","third"),
                       group = c("Findings","Findings","Findings"))

# breaks and limits
breaks.major = c(-60,-40,-22.5,-10, 0,10, 22.5, 40, 60)
breaks.minor = c(-50,-30,-15,-5,0, 5, 15,30,50) 
limits =c(-70,70)

# plot 2015 data
ggplot(data.2015, aes(x = area, y = score, fill = group)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
  coord_flip() +
  scale_y_continuous(limit = limits, oob = squish, minor_breaks = breaks.minor, breaks = breaks.major)

样本图

data.2014 只有“发现”组的值。我想在图上显示那些 2014 年的调查结果值,在适当的/对应的 data.2015$area 上,其中有 2014 年的数据可用。

为了仅在“发现”(红色条)数据上显示去年的数据,我想使用从相关 data.2015 条的值产生的单边误差条/晶须,并在 data.2014 终止值,例如:

理想情节

我想通过使用图层和绘制误差线来做到这一点,以便 2015 年的数据可以重叠,但是当 2014 年的结果 abs() 小于 2015 年的结果并因此被遮挡时,这不起作用。

注意事项:

  • 我希望误差条/晶须与条的宽度相同,甚至可能是带有实心帽的虚线。
  • 值减少时红线加分,值增加时绿线加分
  • 我在一个循环中生成了很多这样的图,有时有很多组,每个图中的区域数量不同。2014年的数据(在这个阶段)总是只显示一个组,每个区域都有一些数据(除了只有一个NA案例,但需要为那个场景准备)

编辑

所以我已经添加到下面的解决方案中,我使用了那个确切的代码,而是使用了geom_linerange这样它会添加没有大写的行,然后我也使用了geom_errorbar,但是将 ymin 和 ymax 设置为相同的值,所以结果是一个单边误差线ggplot geom_bar!谢谢您的帮助。

4

2 回答 2

1

我相信你可以通过一点点数据操作来获得大部分你想要的东西。对两个数据集进行外部连接可以让您添加带有适当闪避的误差线。

alldat = merge(data.2015, data.2014, all = TRUE, by = c("area", "group"), 
            suffixes = c(".2015", ".2014"))

要使误差线偏向一边,您需要与组ymin相同yNA取决于组。创建一个我称之为 的新变量似乎最容易plotscore实现这一点。

alldat$plotscore = with(alldat, ifelse(is.na(score.2014), NA, score.2015))

我做的最后一件事是为direction2015 年的分数与 2014 年相比何时下降与上升做一个变量。我将第三类Benchmark作为填充物,因为在没有它的情况下我遇到了一些躲避问题。

alldat$direction = with(alldat, ifelse(score.2015 < score.2014, "dec", "inc"))
alldat$direction[is.na(alldat$score.2014)] = "absent"

用于绘图的数据集如下所示:

    area     group score.2015 score.2014 plotscore direction
1  first Benchmark        -40         NA        NA    absent
2  first  Findings        -50        -30       -50       dec
3 second Benchmark        -10         NA        NA    absent
4 second  Findings         20         40        20       dec
5  third Benchmark         60         NA        NA    absent
6  third  Findings         15        -15        15       inc

我使用的最终代码如下所示:

ggplot(alldat, aes(x = area, y = score.2015, fill = group)) +
    geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
    geom_errorbar(aes(ymin = plotscore, ymax = score.2014, color = direction), 
                position = position_dodge(width = .9), lwd = 1.5, show.legend = FALSE) +
    coord_flip() +
    scale_y_continuous(limit = limits, oob = squish, minor_breaks = breaks.minor, breaks = breaks.major) +
    scale_color_manual(values = c(NA, "red", "green"))

在此处输入图像描述

我正在使用 ggplot2 的开发版本ggplot2_1.0.1.9002show_guide现在不推荐使用,show.legend而支持geom_errorbar.

我显然没有将误差线的线型更改为带有实心帽的虚线,也没有移除底部的胡须,因为我不知道做这些事情的简单方法。

于 2015-08-18T16:58:45.257 回答
0

作为对建议我添加完整解决方案作为答案的评论的回应:

    library(ggplot2)
    library(scales)

    # some data
    data.2015 = data.frame(score = c(-50,20,15,-40,-10,60),
                           area = c("first","second","third","first","second","third"),
                           group = c("Findings","Findings","Findings","Benchmark","Benchmark","Benchmark"))

    data.2014 = data.frame(score = c(-30,40,-15),
                           area = c("first","second","third"),
                           group = c("Findings","Findings","Findings"))

    # breaks and limits
    breaks.major = c(-60,-40,-22.5,-10, 0,10, 22.5, 40, 60)
    breaks.minor = c(-50,-30,-15,-5,0, 5, 15,30,50) 
    limits =c(-70,70)

    # reconfigure data to create values for the additional errorbar/linerange
    alldat = merge(data.2015, data.2014, all = TRUE, by = c("area", "group"), 
                suffixes = c(".2015", ".2014"))
    alldat$plotscore = with(alldat, ifelse(is.na(score.2014), NA, score.2015))
    alldat$direction = with(alldat, ifelse(score.2015 < score.2014, "dec", "inc"))
    alldat$direction[is.na(alldat$score.2014)] = "absent"

    ggplot(alldat, aes(x = area, y = score.2015, fill = group)) +
    geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +

    # set the data min and max as the same to have a single 'cap' with no line
    geom_errorbar(aes(ymin = score.2014, ymax = score.2014, color = direction), 
                    position = position_dodge(width = .9), lwd = 1.5, show.legend = FALSE) +
    #then add the line
    geom_linerange(aes(ymin = score.2015, ymax = score.2014, color = direction), 
                    position = position_dodge(width = .9), lwd = 1.5, show.legend = FALSE) +
    coord_flip() +
    scale_y_continuous(limit = limits, oob = squish, minor_breaks = breaks.minor, breaks = breaks.major) +
    scale_color_manual(values = c(NA, "red", "green"))
于 2015-08-21T02:03:21.483 回答