ggplot barplot: как отображать небольшие положительные числа с логарифмической осью Y

Основная проблема: я хочу отображать данные от 0 до 1,0 в виде восходящей полосы (начиная с 0), но не хочу, чтобы интервалы были равномерно распределены, а разделены по логарифмическим интервалам.

Я пытаюсь отобразить столбец с пометкой «среднее» в наборе данных ниже в виде гистограммы в ggplot, но поскольку числа очень малы, я хотел бы показать ось Y в логарифмической шкале, а не логарифмическое преобразование самих данных. Другими словами, я хочу иметь вертикальные полосы с метками оси Y как 0, 1e-8, 1e-6 1e-4 1e-2 и 1e-0 (т. е. от 0 до 1,0, но интервалы логарифмические).

Приведенное ниже решение не работает, так как столбцы перевернуты.

> print(df)
        type         mean           sd           se snp
V7    outer 1.596946e-07 2.967432e-06 1.009740e-08   A
V8    outer 7.472417e-07 6.598652e-06 2.245349e-08   B
V9    outer 1.352327e-07 2.515771e-06 8.560512e-09   C
V10   outer 2.307726e-07 3.235821e-06 1.101065e-08   D
V11   outer 4.598375e-06 1.653457e-05 5.626284e-08   E
V12   outer 5.963164e-07 5.372226e-06 1.828028e-08   F
V71  middle 2.035414e-07 3.246161e-06 1.104584e-08   A
V81  middle 9.000131e-07 7.261463e-06 2.470886e-08   B
V91  middle 1.647716e-07 2.875840e-06 9.785733e-09   C
V101 middle 3.290817e-07 3.886779e-06 1.322569e-08   D
V111 middle 6.371170e-06 1.986268e-05 6.758752e-08   E
V121 middle 8.312429e-07 6.329386e-06 2.153725e-08   F

Приведенный ниже код правильно генерирует сгруппированную гистограмму с планками погрешностей.

ggplot(data=df, aes(x=snp,y=mean,fill=type))+
  geom_bar(stat="identity",position=position_dodge(),width=0.5) + 
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se),width=.3, position=position_dodge(.45)) 

Однако я хочу масштабировать логарифм по оси Y, поэтому добавляю в scale_y_log10() следующее:

 ggplot(data=df, aes(x=snp,y=mean,fill=type))+
  geom_bar(stat="identity",position=position_dodge(),width=0.5) + scale_y_log10() +
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se),width=.3, position=position_dodge(.45)) 

Но странно, что бары падают сверху, а я просто хочу, чтобы они шли вверх (как обычно), и не знаю, что я делаю неправильно.

Спасибо


person Lee Sande    schedule 08.12.2016    source источник
comment
гистограммы определяются с точки зрения нуля. У вас очень маленькие цифры. Логарифм очень маленьких чисел отрицательный. Полоса идет от нуля до ваших отрицательных чисел.   -  person Axeman    schedule 08.12.2016
comment
Я немного смущен, потому что я не преобразовываю данные в журнал, поэтому числа все еще положительные. Более того, если вы нанесете данные на график, вы увидите, что единицы измерения по оси Y по-прежнему от 1e-6 (внизу) увеличиваются до 1e-3, но, как ни странно, столбцы падают сверху вниз, то есть от больших чисел к меньшим числам. . Я просто хочу просматривать данные в логарифмическом масштабе, но не преобразовывать сами данные. Я надеюсь, что я имею смысл   -  person Lee Sande    schedule 08.12.2016
comment
Вы абсолютно логируете преобразование данных. scale_y_log10() log преобразует данные перед их построением.   -  person hrbrmstr    schedule 08.12.2016
comment
Хорошо, в ggplot должна быть ошибка, потому что метки y-tick являются положительными числами (те же значения, которые я вижу, когда я не использую scale_y_log10()).   -  person Lee Sande    schedule 09.12.2016
comment
Нет, он преобразует данные для галочек в обратном порядке. Определенно не ошибка.   -  person hrbrmstr    schedule 09.12.2016
comment
Я также очень обеспокоен тем, что ты это делаешь. Гистограммы абсолютно должны начинаться с 0, но они не могут работать с логарифмической шкалой 10 (log10(0) == -Inf), и большинство людей сделают очень неверные выводы, поскольку они будут линейно сравнивать гистограммы в уме и должны будут постоянно помните, что это логарифмическая шкала, и попытайтесь ее компенсировать. Если проблема заключается в разнице YUGE между E и другими парами стержней, вы можете использовать фасетирование со свободной шкалой Y, чтобы компенсировать это и при этом сделать ее компактной.   -  person hrbrmstr    schedule 09.12.2016
comment
Судя по комментариям, мне было непонятно, поэтому я добавил больше информации и изменил заголовок. Я хочу отображать данные от 0 до 1,0 в виде восходящей полосы (начиная с 0), но не хочу, чтобы интервалы были равноотстоящими, а логарифмическими. Надеюсь, теперь мое объяснение понятно.   -  person Lee Sande    schedule 09.12.2016
comment
Но, как уже указывал @hrbrmstr, log10(0) это -Inf. Итак, вы запрашиваете график, на котором столбцы простираются от отрицательной бесконечности до зарегистрированных значений ваших данных.   -  person eipi10    schedule 09.12.2016
comment
Вы можете найти этот ответ SO полезным.   -  person eipi10    schedule 09.12.2016


Ответы (1)


Вот небольшая хитрость, чтобы показать, что произойдет, если вы попытаетесь получить столбцы, начинающиеся с нуля на логарифмической шкале. Я использовал geom_segment для иллюстрации, так что я могу создавать «полосы» (фактически широкие сегменты линий), простирающиеся на произвольные диапазоны. Чтобы это работало, мне также пришлось делать все уклонения вручную, поэтому сопоставление x выглядит странно.

В приведенном ниже примере масштаб изменяется от y=1e-20 до y=1. Интервалы по оси Y масштабируются в логарифмическом масштабе, что означает, что физическое расстояние, скажем, от 1e-20 до 1e-19 такое же, как физическое расстояние, скажем, от 1e-8 до 1e-7, даже если величины этих интервалов различаются в триллион раз.

Столбцы, которые уменьшаются до нуля, не могут быть отображены, потому что ноль на логарифмической шкале находится на бесконечном расстоянии ниже нижней части графика. Мы могли бы приблизиться к нулю, например, изменив 1e-20 на 1e-100 в приведенном ниже коде. Но это только сделает и без того небольшие физические расстояния между значениями данных еще меньше и, следовательно, еще труднее их различить.

Столбцы также вводят в заблуждение по другому поводу, потому что, как указал @hrbrmstr, наш мозг воспринимает расстояние вдоль столбца линейно, но величина, представленная каждым приращением расстояния вдоль столбца, изменяется в 10 раз примерно каждые несколько миллиметров в пример ниже. Полосы просто не кодируют значимую информацию о данных.

ggplot(data=df, aes(x=as.numeric(snp) + 0.3*(as.numeric(type) - 1.5), 
                    y=mean, colour=type)) +
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se), width=.3) +
  geom_segment(aes(xend=as.numeric(snp) + 0.3*(as.numeric(type) - 1.5),
                   y=1e-20, yend=mean), size=5) +
  scale_y_log10(limits=c(1e-20, 1), breaks=10^(-100:0), expand=c(0,0)) +
  scale_x_continuous(breaks=1:6, labels=LETTERS[1:6])

введите здесь описание изображения

Если вы хотите придерживаться логарифмической шкалы, возможно, лучшим подходом будет построение точек:

pd = position=position_dodge(.5)
ggplot(data=df, aes(x=snp,y=mean,fill=type))+
  geom_errorbar(aes(ymin=mean-se, ymax=mean+se, colour=type), width=.3, position=pd) +
  geom_point(aes(colour=type), position=pd) +
  scale_y_log10(limits=c(1e-7, 1e-5), breaks=10^(-10:0)) +
  annotation_logticks(sides="l")

введите здесь описание изображения

person eipi10    schedule 09.12.2016