R语言 对数标尺条形图

wsxa1bj1  于 2023-05-04  发布在  其他
关注(0)|答案(2)|浏览(147)

我在使用ggplot缩放时遇到了一个有趣的问题。我有一个数据集,我可以使用默认的线性尺度很好地绘制图形,但当我使用scale_y_log10()时,数字会偏离。下面是一些示例代码和两张图片。请注意,线性标度中的最大值约为700,而对数标度的结果为10^8。我向您展示了整个数据集只有~8000个条目长,所以有些地方不对劲。
我想这个问题与我的数据集的结构和分箱有关,因为我不能在像“钻石”这样的常见数据集上复制这个错误。但是我不确定最好的解决方法。
谢谢Zach CP
编辑:bdamarest可以像这样在diamond数据集上重现规模问题:

example_1 = ggplot(diamonds, aes(x=clarity, fill=cut)) + 
  geom_bar() + scale_y_log10(); print(example_1)
#data.melt is the name of my dataset    
> ggplot(data.melt, aes(name, fill= Library)) + geom_bar()  
> ggplot(data.melt, aes(name, fill= Library)) + geom_bar()  + scale_y_log10()
> length(data.melt$name)
[1] 8003

以下是一些示例数据…我想我看到问题了原始融合数据集可能有~10^8行长。也许行号用于统计数据?

> head(data.melt)
       Library         name               group
221938      AB Arthrofactin        glycopeptide
235087      AB   Putisolvin      cyclic peptide
235090      AB   Putisolvin      cyclic peptide
222125      AB Arthrofactin        glycopeptide
311468      AB     Triostin cyclic depsipeptide
92249       AB          CDA         lipopeptide
test2 <- data.frame(
  Library = rep("AB", 6L),
  name = c(
    "Arthrofactin", "Putisolvin", "Putisolvin", "Arthrofactin",
    "Triostin", "CDA"
  ),
  group = c(
    "glycopeptide", "cyclic peptide", "cyclic peptide", "glycopeptide",
    "cyclic depsipeptide", "lipopeptide"
  ),
  row.names = c(221938L, 235087L, 235090L, 222125L, 311468L, 92249L)
)

更新:
行号不是问题。下面是使用相同的aes x轴和填充颜色绘制的相同数据,缩放比例完全正确:

> ggplot(data.melt, aes(name, fill= name)) + geom_bar()
> ggplot(data.melt, aes(name, fill= name)) + geom_bar() + scale_y_log10()
> length(data.melt$name)
[1] 8003

acruukt9

acruukt91#

geom_barscale_y_log10(或任何对数标度)不能很好地一起工作,并且不能给予预期的结果。
第一个基本问题是条形图会变为0,在对数尺度上,0会转换为负无穷大(这很难绘制)。围绕这一点的婴儿床通常从1而不是0开始(因为$\log(1)=0$),如果计数为0,则不绘制任何内容,并且不必担心失真,因为如果需要对数刻度,您可能不关心偏离1(不一定是真的,但是......)
我使用的是@dbemarest展示的diamonds示例。
一般来说,要做到这一点,需要变换坐标,而不是比例(稍后将详细介绍两者的区别)。

ggplot(diamonds, aes(x=clarity, fill=cut)) +
  geom_bar() +
  coord_trans(ytrans="log10")

但这给出了一个错误

Error in if (length(from) == 1 || abs(from[1] - from[2]) < 1e-06) return(mean(to)) : 
  missing value where TRUE/FALSE needed

这是由负无穷大问题引起的。
使用比例变换时,先将变换应用于数据,然后进行统计和排列,然后在逆变换中(大致)标记比例。你可以通过自己打破计算来看到发生了什么。

DF <- ddply(diamonds, .(clarity, cut), summarise, n=length(clarity))
DF$log10n <- log10(DF$n)

它给出了

> head(DF)
  clarity       cut   n   log10n
1      I1      Fair 210 2.322219
2      I1      Good  96 1.982271
3      I1 Very Good  84 1.924279
4      I1   Premium 205 2.311754
5      I1     Ideal 146 2.164353
6     SI2      Fair 466 2.668386

如果我们以正常的方式绘制它,我们会得到预期的条形图:

ggplot(DF, aes(x=clarity, y=n, fill=cut)) + 
  geom_bar(stat="identity")

并且缩放y轴给出了与使用未预先汇总的数据相同的问题。

ggplot(DF, aes(x=clarity, y=n, fill=cut)) +
  geom_bar(stat="identity") +
  scale_y_log10()

我们可以通过绘制计数的log10()值来了解问题是如何发生的。

ggplot(DF, aes(x=clarity, y=log10n, fill=cut)) +
  geom_bar(stat="identity")

这看起来就像一个与scale_y_log10,但标签是0,5,10,…而不是10^0、10^5、10^10……
因此,使用scale_y_log10进行计数,将其转换为日志,堆叠这些日志,然后以反对数形式显示比例。但是,堆叠日志不是线性变换,因此您要求它做的事情没有任何意义。
底线是,对数尺度上的堆叠条形图没有多大意义,因为它们不能从0开始(条形图的底部应该在那里),比较条形图的部分是不合理的,因为它们的大小取决于它们在堆栈中的位置。而是考虑类似于:

ggplot(diamonds, aes(x=clarity, y=..count.., colour=cut)) + 
  geom_point(stat="bin") +
  scale_y_log10()

或者,如果你真的想要一个叠加条形图通常会给予你的组的总数,你可以这样做:

ggplot(diamonds, aes(x=clarity, y=..count..)) + 
  geom_point(aes(colour=cut), stat="bin") +
  geom_point(stat="bin", colour="black") +
  scale_y_log10()

pw9qyyiw

pw9qyyiw2#

最好的选择是通过使用facet_wrap来摆脱bar堆栈(如@Brian评论的log(sum(x)) != sum(log(x)))。如果需要,还可以添加一个面板来表示Total
例如,对于diamonds数据集(遵循@Brian Diggs的答案),我们可以绘制

diamonds %>%
  bind_rows(                                                  # Adds a
    diamonds %>%                                              # panel to 
    mutate(cut = "Total")                                     # represent
  ) %>%                                                       # the
  mutate(cut = cut %>% fct_relevel("Total", after = Inf)) %>% # Total
  ggplot(aes(x = clarity, fill = clarity)) +
  geom_bar() +
  facet_wrap(~cut) +
  scale_y_log10()

或者,

diamonds %>%
  bind_rows(                                                          # Adds a
    diamonds %>%                                                      # panel to
    mutate(clarity = "Total")                                         # represent
  ) %>%                                                               # the
  mutate(clarity = clarity %>% fct_relevel("Total", after = Inf)) %>% # Total
  ggplot(aes(x = cut, fill = cut)) +
  geom_bar() +
  facet_wrap(~clarity) +
  scale_y_log10()

相关问题