【问题标题】:Log scale on y axis but data have negative valuesy 轴上的对数刻度,但数据具有负值
【发布时间】:2019-11-20 11:34:46
【问题描述】:

我正在尝试创建一个带有 log y 轴的箱线图,因为我有一些非常小的值,然后是一些更高的值,它们在具有连续 y 轴的箱线图中效果不佳。但是,我有负值,显然不适用于对数刻度。我想知道是否有办法解决这个问题,以便我可以在箱线图上显示我的数据,箱线图仍然很容易解释,但在 y 轴上有更合适的比例。

    p <- ggplot(data = Elstow.monthly.fluxes, aes(x = Month1, y = CH4.Flux)) + stat_boxplot(geom = "errorbar", linetype = 1, width = 0.5) + geom_boxplot() +
xlab(expression("Month")) + ylab(expression(~CH[4]~Flux~(µg~CH[4]~m^{-2}~d^{-1}))) +
scale_y_continuous(breaks = seq(-5000,40000,5000), limits = c(-5000,40000))+
theme(axis.text.x = element_text(colour = "black")) + theme(axis.text.y = element_text(colour = 
"black")) +
theme(panel.background = element_rect("white", "black")) +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
theme(axis.text = element_text(size = 12))+ theme(axis.title = element_text(size = 14))+ 
theme(axis.title.y = element_text(margin = margin(t = 0, r = 15, b = 0, l = 0))) + 
theme(axis.title.x = element_text(margin = margin(t = 15, r = 0, b = 0, l = 0))) +
geom_hline(yintercept = 0, linetype ="dashed", colour = "black") 

【问题讨论】:

  • 删除异常值:只保留abs(Elstow.monthly.fluxes$CH4.Flux) &lt;= X 的所有内容,其中X 可以是4e3
  • 我不愿意删除这些值,因为它们不是传统意义上的异常值可能存在的测量误差,它们是恰好比其他值高很多的有效测量值。是否有解决方案意味着我可以保留这些值?

标签: r ggplot2 scale axis


【解决方案1】:

虽然您确实可以按照志强的建议使用辅助轴来获取您想要的标签,但您也可以使用适合您需要的转换。

考虑以下倾斜的箱线图:

df <- data.frame(
  x = rep(letters[1:2], each = 500),
  y = rlnorm(1000) - 2
)

ggplot(df, aes(x, y)) +
  geom_boxplot()

相反,您可以使用伪对数转换来可视化您的数据:

ggplot(df, aes(x, y)) +
  geom_boxplot() +
  scale_y_continuous(trans = scales::pseudo_log_trans())

或者,您可以进行任何您想要的转换。我个人喜欢反双曲正弦变换,很像伪对数:

asinh_trans <- scales::trans_new(
  "inverse_hyperbolic_sine",
  transform = function(x) {asinh(x)},
  inverse = function(x) {sinh(x)}
  )

ggplot(df, aes(x, y)) +
  geom_boxplot() +
  scale_y_continuous(trans = asinh_trans)

【讨论】:

  • 谢谢,这很有帮助,但是当我尝试使用我的数据运行它时出现错误。 “is.trans(x) 中的错误:找不到对象‘尺度’”。这段代码正确吗? p
  • 你试过两个:吗? IE。 trans = scales::pseudo_log_trans() ?
  • 我认为它有效,但它似乎改变了我数据的所有值,所以箱线图看起来不一样。任何想法为什么会发生这种情况?
  • 箱线图是根据比例转换数据计算的,因此可能会影响离群值截止的位置。
【解决方案2】:

我有一个愚蠢的解决方案:欺骗辅助轴以重新缩放 y 轴。我没有你的数据,只是为了演示的目的编了一些数字。

首先将y 值转换为logy = log(y + 5000)。生成图形时,将值转换回原始比例。我借用第二个轴来显示值。我很确定其他人可能有更优雅的方法来做到这一点。

我很懒,因为没有尝试找到删除主要y 轴刻度标签的正确方法,只是使用了breaks = c(0)

df<-data.frame(y = runif(33, min=-5000, max=40000), 
           x = rep(c("Aug", "Sep", "Oct"),33)) 
library(tidyverse)
df$logy = log(df$y+5000)

p <- ggplot(data = df, aes(x = x, y = logy)) + 
  stat_boxplot(geom = "errorbar", linetype = 1, width = 0.5) + 
  geom_boxplot() +
  xlab(expression("Month")) + 
  ylab(expression(~CH[4]~Flux~(µg~CH[4]~m^{-2}~d^{-1}))) +
  scale_y_continuous(sec.axis = sec_axis(~(exp(.) -5000), 
                                         breaks = c(-4000, 0, 5000, 10000, 20000, 40000)), 
                     breaks = c(0))+ 
  theme(axis.text.x = element_text(colour = "black")) + 
  theme(axis.text.y = element_text(colour = "black")) +
  theme(panel.background = element_rect("white", "black")) +
  theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
  theme(axis.text = element_text(size = 12))+ 
  theme(axis.title = element_text(size = 14))+ 
  theme(axis.title.y = element_text(margin = margin(t = 0, r = 15, b = 0, l = 0))) + 
  theme(axis.title.x = element_text(margin = margin(t = 15, r = 0, b = 0, l = 0))) +
  geom_hline(yintercept = log(5000), linetype ="dashed", colour = "black") 
p

【讨论】:

    【解决方案3】:

    coord_trans() 在计算统计数据后应用(与比例不同)。这可以与pseudo_log_trans 结合使用以应对负面影响。

    library(plotly)
    set.seed(1234)
    dat <- data.frame(cond = factor(rep(c("A","B"), each=200)), rating = c(rnorm(200),rnorm(200, mean=500)))
    
    pseudoLog <- scales::pseudo_log_trans(base = 10)
    p <- ggplot(dat, aes(x=cond, y=rating)) + geom_boxplot() + coord_trans(y=pseudoLog)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多