使用条形图可视化与目标值的差异

时间:2014-12-04 10:52:52

标签: r data-visualization ggplot2

我正在尝试使用R的gglot2包中的条形图来显示时间序列与其基线值的偏移量。例如,采用以下合成数据:

baseline = 400
steps <- sample(0:10,50,replace=TRUE) - sample(0:10,50,replace=TRUE)
value <- cumsum(steps) + baseline
time = 1:50
data <- data.frame(time,value)

print(value)
 [1] 400 400 397 397 393 400 394 395 389 389 385 395 400 399 405 403 399 401 399 401
[21] 401 401 398 397 395 395 401 402 393 400 399 398 406 412 417 413 410 401 400 399
[41] 394 401 406 406 401 404 411 413 404 402

我可以按照原始尺度绘制图表,但这并不能提供真正的信息:

longdata <- ddply( data, "value", transform, posneg=sign(value-baseline) )
longdata[longdata$posneg == 0,'posneg'] <- 1
p_aes <- aes( time, value, fill=factor(posneg))
p_scale <- scale_fill_brewer( palette='Set1', guide=FALSE )
p_geom <- geom_bar( stat='identity', position='identity' )
ggplot(longdata) + p_aes + p_scale + p_geom

enter image description here

通过沿y轴移动美学(即,y =值 - 基线),我获得了我想要展示的图表,这很好,很容易。

longdata <- ddply( data, "value", transform, posneg=sign(value-baseline) )
longdata[longdata$posneg == 0,'posneg'] <- 1
p_aes <- aes( time, value-baseline, fill=factor(posneg))
p_scale <- scale_fill_brewer( palette='Set1', guide=FALSE )
p_geom <- geom_bar( stat='identity', position='identity' )
ggplot(longdata) + p_aes + p_scale + p_geom

enter image description here

不幸的是,y轴的比例现在变为偏离基线的偏移,即“值 - 基线”。但是,我确实希望y轴保持原始值(380到420之间的值)。

有没有办法保留第二张图表的原始y轴刻度?您是否有任何其他建议可视化与目标值的差异?

2 个答案:

答案 0 :(得分:5)

添加功能:

yaxis_format <- function(x){
lab <- 400-x
}

然后使用scale_y_continuous(label = yaxis_format)处理标签:

ggplot(longdata) + p_aes + p_scale + p_geom + scale_y_continuous(label=yaxis_format)

最终的代码和图表应如下所示:

library(ggplot2)
library(plyr)

set.seed(201)

baseline = 400
steps <- sample(0:10,50,replace=TRUE) - sample(0:10,50,replace=TRUE)
value <- cumsum(steps) + baseline
time = 1:50
data <- data.frame(time,value)

yaxis_format <- function(x){
lab <- 400-x
}

longdata <- ddply( data, "value", transform, posneg=sign(value-baseline) )
longdata[longdata$posneg == 0,'posneg'] <- 1
p_aes <- aes( time, value-baseline, fill=factor(posneg))
p_scale <- scale_fill_brewer( palette='Set1', guide=FALSE )
p_geom <- geom_bar( stat='identity', position='identity' )
ggplot(longdata) + p_aes + p_scale + p_geom + scale_y_continuous(label=yaxis_format)
                 + ylab("Value")

enter image description here

现在,有了这一切,请注意比例是奇数。请使用scale_y_reverse来修复它:

ggplot(longdata) + p_aes + p_scale + p_geom + scale_y_reverse(label=yaxis_format)
                 + ylab("Value")

enter image description here

答案 1 :(得分:4)

另一个解决方案而不是事后更改y轴的解决方案是使用geom_linerange,然后只需使线条足够宽以用于特定的绘图(交叉或误差条的不同geom也可能是合适的)。

p <- ggplot(data=longdata, aes(x = time, color = factor(posneg))) +
     geom_linerange(aes(ymax = value, ymin = baseline), size = 3) +
     scale_color_brewer( palette='Set1', guide=FALSE )

p

enter image description here

这是一个完全合理的情节,因为您通过缩小并在零规则处使用基线来显示您错过了所有变化。但是,条形图具有如此强烈的约定,基线应该为零,它可能会被误读。此外,基线值处的条形图根本不会出现在图表中,这使它们看起来像缺少数据。

带有表示基线的水平条的折线图足以显示相同的信息,实际上不需要颜色。

p2 <- ggplot(data=longdata, aes(x = time, y = value)) + 
      geom_line() + geom_point() + geom_hline(yintercept=baseline)

p2

enter image description here