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

3

我想使用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

通过沿着y轴(即y = value - baseline)调整美学,我得到了想要展示的图表,这非常好且易于理解。
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个回答

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")

现在,所有设置都完成了,注意比例尺是奇怪的。使用scale_y_reverse来修复它:
ggplot(longdata) + p_aes + p_scale + p_geom + scale_y_reverse(label=yaxis_format)
                 + ylab("Value")

enter image description here


啊,我也正在回答呢。在我看来,留在这里讨论一下美学和潜在的替代方案是可以的(例如,将其变得更加通用而不仅仅是代码)。 - Andy W

4

除了事后更改 y 轴的解决方案之外,另一种解决方法是使用 geom_linerange,然后只需使线宽度足够适合特定的绘图(交叉或误差线的不同形状也可能适用)。

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


谢谢,这是很好的建议,我会考虑使用折线图。 - MRA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接