使用stat_summary以对数比例绘制数据:汇总范围达到零

时间:2015-06-17 13:12:35

标签: r ggplot2 logarithm

问题:

ggplot手册明确指出scale_y_log10()coord_trans(y="log10")的行为不同。第一个转换数据,第二个转换坐标。因此,如果必须将误差条添加到对数图中,则不能使用前者,因为实际比例不是线性的,并且必须在对数变换之前执行误差计算,而不是之后。

但是,在以对数刻度绘制的某些数据中添加误差线(或其他范围)时,存在某些范围将达到零并且绘图将失败的风险。在这种情况下,绘制的变量不可能低于0,因此这些值可以安全地切割为任意低的数字,因此绘图不会失败。

实施例

获取示例数据框:

url <- "https://copy.com/cfNBrcTLEfjiYXXa/d_dataframe.Rdata?download=1"
download.file(url, "d_dataframe.Rdata", method="curl")
load("d_dataframe.Rdata")
library(ggplot2)
p <- ggplot(d, aes(x=x, y=PDF))

以日志比例查看数据:

p + geom_point(aes(colour=model)) + scale_y_log10()
p + geom_point(aes(colour=model)) + coord_trans(y="log10")

一切都好,数据与coord_trans()和scale_y_log10()看起来相同。但是,如果我添加摘要方法:

p + stat_summary(fun.data = "mean_se", mult = 2) + scale_y_log10()

上述内容并未正确表示实际标准错误,但是:

p + stat_summary(fun.data = "mean_se", mult = 2) + coord_trans(y="log10")

无法绘制,因为其中一个摘要(在本例中我使用的是标准错误)达到0(或更小)并且对数标度因常规而失败:

Error in if (zero_range(range)) { : missing value where TRUE/FALSE needed

设置y限制不起作用,因为只删除了一些点范围:

p + stat_summary(fun.data = "mean_se", mult = 2) + coord_trans(y="log10", limy=c(1e-10, 1.1))

我希望这些行不被删除,而只是到达图表的底部,表示它们低于0。

我知道我可以手动计算错误,将它们过滤为&gt; 0,并用geom_linerange()或类似的方式绘制它们。但是使用stat_summary()的能力非常方便快捷,并且可以快速更改绘制的统计数据。同样的考虑也适用于geom_smooth()

有什么方法可以保留stat_summary() / geom_smooth()的使用,并且仍然以对数标度绘制数据?

编辑:

一个示例解决方案就是沿着这些方向(对于2sd传播):

maxf <- function(dati) {mean(dati) + 2*sd(dati)}
minf <- function(dati) {max(10e-8, mean(dati) - 2*sd(dati))}

然后使用:

stat_summary(fun.y = mean, fun.ymin=minf, fun.ymax=maxf) + coord_trans(y="log10")

但是,每当我改变对摘要错误的想法时(例如,如果我选择标准错误而不是标准差),就必须对此进行调整,并且不可能(?)将此方法用于geom_smooth()

1 个答案:

答案 0 :(得分:1)

A simple and reasonably workable solution is to define maxf and minf as nested function definitions that take functions as their argument.

# Defining minf and maxf to take functions as input
minf <- function(f){function(dati) {max(1e-8, mean(dati) - f(dati))}}
maxf <- function(f){function(dati) {mean(dati) + f(dati)}}

# A plot that works
p + stat_summary(fun.y = mean, fun.ymin=minf(sd), fun.ymax=maxf(sd)) 
  + coord_trans(y="log10")

# If you change your mind and want something besides sd
se <- function(x){sd(x)/sqrt(length(x))}

p + stat_summary(fun.y = mean, fun.ymin=minf(se), fun.ymax=maxf(se)) 
  + coord_trans(y="log10")

There are some limitations on this approach: you still have to redefine minf and maxf if you want error bars that aren't some form of addition/subtraction to the mean, and you have to define your f functions as being able to take single vector inputs to give vector outputs. But I think it's a little nicer than always having to redefine minf and maxf all the time, for everything.