我有数据,我想使用ggplot2在y轴上用对数刻度绘制线图。不幸的是,我的一些价值观一直降到零。数据表示依赖于某些参数的特征的相对出现。当在样本中未观察到该特征时,出现零值,这意味着它很少发生,或者实际上从未发生过。这些零值会导致对数图中出现问题。
以下代码说明了简化数据集的问题。实际上,数据集包含更多点,因此曲线看起来更平滑,参数p
的值也更多。
library(ggplot2)
dat <- data.frame(x=rep(c(0, 1, 2, 3), 2),
y=c(1e0, 1e-1, 1e-4, 0,
1e-1, 1e-3, 0, 0),
p=c(rep('a', 4), rep('b', 4)))
qplot(data=dat, x=x, y=y, colour=p, log="y", geom=c("line", "point"))
鉴于上述数据,我们预计有两条线,第一条线应该在对数图上有三个有限点,第二条线应该在对数图上只有两个有限点。
但是,正如您所看到的,这会产生一种非常误导的情节。看起来蓝色和红色线都会收敛到1e-4和1e-3之间的值。原因是log(0)
给出-Inf
,ggplot只是放在下轴上。
使用ggplot2在R中处理此问题的最佳方法是什么? best 我的意思是效率方面,而且是意识形态R(我对R来说还是新手)。
该图应表明这些曲线分别在x = 2(红色)或x = 1(蓝色)之后下降到“非常小”。理想情况下,从最后一个有限点向下垂直线。我的意思如下所示。
在这里,我将描述我的想法。但是,鉴于我对R很新,我怀疑可能有更好的方法。
library(ggplot2)
library(scales)
dat <- data.frame(x=rep(c(0, 1, 2, 3), 2),
y=c(1e0, 1e-1, 1e-4, 0,
1e-1, 1e-3, 0, 0),
p=c(rep('a', 4), rep('b', 4)))
与上述数据相同。
现在,我将浏览每个唯一参数p
,找到最后一个有限点的x坐标,并将其分配给y为零的所有点的x坐标。那是为了实现垂直线。
for (p in unique(dat$p)) {
dat$x[dat$p == p & dat$y == 0] <- dat$x[head(which(dat$p == p & dat$y == 0), 1) - 1]
}
此时情节如下:
垂直线在那里。但是,也有一些观点。这些都是误导性的,因为它们表明那里有一个实际的数据点,这是不正确的。
要删除我复制y数据的点(看起来很浪费),我们称之为yp
,并将{0}替换为NA
。然后我使用新的yp
作为geom_point
的y美学。
dat$yp <- dat$y
dat$yp[dat$y == 0] <- NA
ggplot(dat, aes(x=x, y=y, colour=p)) +
geom_line() +
geom_point(aes(y=dat$yp)) +
scale_y_continuous(trans=log10_trans(),
breaks = trans_breaks("log10", function(x) 10^x),
labels = trans_format("log10", math_format(10^.x)))
我使用ggplot
代替qplot
,以便我可以为geom_line
和geom_point
提供不同的美学。
最后,情节看起来像这样。
正确的方法是什么?
答案 0 :(得分:1)
我使用
+ scale_y_continuous(trans=scales::pseudo_log_trans(base = 10)
答案 1 :(得分:1)
最简单的方法是为每个数字添加一个小值。例子,
df <- mutate(df, log_var = log(var + 0.01))
ggplot(df, aes(x = log_var)) + geom_histogram()
答案 2 :(得分:0)
如果使用的是ggplot,则可以使用scales::pseudo_log_trans()
作为转换对象。这会将您的-inf替换为0。
从文档(https://scales.r-lib.org/reference/pseudo_log_trans.html),
将数字映射到有符号对数刻度的转换,并平滑地过渡到0附近的线性刻度。
pseudo_log_trans(sigma = 1, base = exp(1))
例如,我的比例表达式如下所示:
+ scale_fill_gradient(name = "n occurrences", trans="pseudo_log")