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()
答案 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.