对于正负号的重尾数据,我有时喜欢在没有隐藏单位区间结构的情况下查看绘图上的所有数据。
在 Python 中使用 Matplotlib 绘图时,我可以通过选择symlog scale来实现这一点,它在某个区间外使用对数变换,并在其中进行线性绘图。
以前在 RI 中通过一次性使用arcsinh转换数据来构建类似的行为。然而,刻度标签等是非常棘手的(见下文)。
现在,我面临着一堆数据,其中lattice或ggplot中的子集非常方便。由于子集,我不想使用 Matplotlib,但我肯定缺少symlog!
编辑:
我看到ggplot 使用了一个名为 scales 的包,它解决了很多这个问题(如果它有效的话)。不过,自动选择刻度线和标签放置看起来仍然很难做得很好。log_breaks
和的某种组合cbreaks
?
编辑2:
下面的代码还不错
sinh.scaled <- function(x,scale=1){ sinh(x)*scale }
asinh.scaled <- function(x,scale=1) { asinh(x/scale) }
asinh_breaks <- function (n = 5, scale = 1, base=10)
{
function(x) {
log_breaks.callable <- log_breaks(n=n,base=base)
rng <- rng <- range(x, na.rm = TRUE)
minx <- floor(rng[1])
maxx <- ceiling(rng[2])
if (maxx == minx)
return(sinh.scaled(minx, scale=scale))
big.vals <- 0
if (minx < (-scale)) {
big.vals = big.vals + 1
}
if (maxx>scale) {
big.vals = big.vals + 1
}
brk <- c()
if (minx < (-scale)) {
rbrk <- log_breaks.callable( c(-min(maxx,-scale), -minx ) )
rbrk <- -rev(rbrk)
brk <- c(brk,rbrk)
}
if ( !(minx>scale | maxx<(-scale)) ) {
rng <- c(max(minx,-scale), min(maxx,scale))
minc <- floor(rng[1])
maxc <- ceiling(rng[2])
by <- floor((maxc - minc)/(n-big.vals)) + 1
cb <- seq(minc, maxc, by = by)
brk <- c(brk,cb)
}
if (maxx>scale) {
brk <- c(brk,log_breaks.callable( c(max(minx,scale), maxx )))
}
brk
}
}
asinh_trans <- function(scale = 1) {
trans <- function(x) asinh.scaled(x, scale)
inv <- function(x) sinh.scaled(x, scale)
trans_new(paste0("asinh-", format(scale)), trans, inv,
asinh_breaks(scale = scale),
domain = c(-Inf, Inf))
}