Мне нужно построить гистограмму, показывающую количество и линейную диаграмму, показывающую скорость на одном графике, я могу сделать их оба по отдельности, но когда я их соединю, масштаб первого слоя (т. Е. geom_bar
) Перекрывается вторым слой (то есть geom_line
).
Могу ли я переместить ось geom_line
вправо?
ggplot2
реализациюscale_y_*
, вызываемую в данный моментsec.axis
.Ответы:
Иногда клиент хочет двухлетнюю шкалу. Давать им «некорректную» речь часто бессмысленно. Но мне нравится настойчивость ggplot2 делать все правильно. Я уверен, что ggplot на самом деле обучает обычного пользователя правильной технике визуализации.
Может быть, вы можете использовать гранение и масштабирование бесплатно, чтобы сравнить два ряда данных? - например, посмотрите здесь: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
источник
Это невозможно в ggplot2, потому что я считаю, что графики с отдельными y-масштабами (не y-масштабами, которые являются преобразованиями друг друга) в корне ошибочны. Некоторые проблемы:
Не являются обратимыми: учитывая точку на пространстве графика, вы не можете однозначно отобразить ее обратно на точку в пространстве данных.
Их относительно трудно правильно прочитать по сравнению с другими вариантами. Подробности см. В исследовании диаграмм данных двойного масштаба, проведенном Петрой Изенберг, Анастасией Безерианос, Пьером Драгичевичем и Жаном-Даниэлем Фекете.
Их легко манипулировать, чтобы ввести в заблуждение: не существует уникального способа указать относительные масштабы осей, оставляя их открытыми для манипуляций. Два примера из блога Junkcharts: один , два
Они произвольны: почему только 2 шкалы, а не 3, 4 или десять?
Вы также можете прочитать подробное обсуждение Стивена Фью на тему « Двухмасштабные оси в графах». Являются ли они когда-либо лучшим решением? ,
источник
Начиная с ggplot2 2.2.0, вы можете добавить дополнительную ось, подобную этой (взято из объявления ggplot2 2.2.0 ):
источник
Взяв приведенные выше ответы и некоторые настройки (и во что бы то ни стало), вот способ достижения двух шкал с помощью
sec_axis
:Предположим, простой (и чисто вымышленный) набор данных
dt
: в течение пяти дней он отслеживает количество прерываний VS производительности:(диапазоны обоих столбцов отличаются примерно в 5 раз).
Следующий код нарисует обе серии, что они используют всю ось Y:
Вот результат (код выше + подстройка цвета):
sec_axis
Смысл (помимо использования при указании y_scale заключается в умножении каждого значения 2-го ряда данных на 5 при указании ряда. Чтобы получить метки прямо в определении sec_axis, необходимо затем разделить на 5 (и отформатировать). критическая часть в приведенном выше коде действительно находится*5
в geom_line и~./5
sec_axis (формула, делающая текущее значение.
на 5).Для сравнения (я не хочу судить о подходах здесь), вот как выглядят две диаграммы друг над другом:
Вы сами можете судить, какой из них лучше переносить сообщение («Не мешайте людям на работе!»). Думаю, это честный способ решить.
Полный код для обоих изображений (на самом деле это не больше, чем выше, просто завершен и готов к запуску) находится здесь: https://gist.github.com/sebastianrothbucher/de847063f32fdff02c83b75f59c36a7d более подробное объяснение здесь: https: // sebastianrothbucher. github.io/datascience/r/visualization/ggplot/2018/03/24/two-scales-ggplot-r.html
источник
Существуют общие случаи использования дуэльных осей, например, климатограф, показывающий месячную температуру и количество осадков. Вот простое решение, обобщенное на основе решения Мегатрона, позволяющее установить нижний предел переменных на значение, отличное от нуля:
Пример данных:
Установите следующие два значения на значения, близкие к пределам данных (вы можете поиграться с ними, чтобы отрегулировать положения графиков; оси все равно будут правильными):
Следующее делает необходимые вычисления, основанные на этих пределах, и делает сам график:
Если вы хотите убедиться, что красная линия соответствует правой оси Y, вы можете добавить
theme
предложение в код:который окрашивает правую ось:
источник
ylim.prim
иylim.sec
.Вы можете создать коэффициент масштабирования, который применяется ко второму геому и правой оси Y. Это вытекает из решения Себастьяна.
Примечание: использование
ggplot2
v3.0.0источник
Техническая основа для решения этой проблемы была предоставлена Kohske около 3 лет назад [ KOHSKE ]. Тема и технические аспекты ее решения обсуждались в нескольких случаях здесь, на Stackoverflow [ID: 18989001, 29235405, 21026598]. Поэтому я приведу только конкретный вариант и несколько поясняющих пошаговых инструкций, используя вышеуказанные решения.
Предположим, у нас есть некоторые данные y1 в группе G1, с которыми некоторые данные y2 в группе G2 каким-то образом связаны, например, преобразованы диапазон / масштаб или добавлен некоторый шум. Таким образом, каждый хочет построить данные вместе на одном графике с масштабом y1 слева и y2 справа.
Если мы теперь нанесем наши данные вместе с чем-то вроде
это не выравнивается хорошо, поскольку меньший масштаб y1, очевидно, сворачивается большим масштабом y2 .
Хитрость для решения этой проблемы состоит в том, чтобы технически построить оба набора данных по первой шкале y1, но сообщить вторую по вторичной оси с метками, показывающими исходную шкалу y2 .
Поэтому мы создаем первую вспомогательную функцию CalcFudgeAxis, которая вычисляет и собирает элементы новой оси, которая будет показана. Функция может быть изменена в соответствии с предпочтениями ayones (эта просто отображает y2 в диапазон y1 ).
что дает немного:
Теперь я обернул решение Кохске во вторую вспомогательную функцию PlotWithFudgeAxis (в которую мы бросаем объект ggplot и вспомогательный объект новой оси):
Теперь все можно собрать воедино. Ниже приведен код, показывающий, как предлагаемое решение может использоваться в повседневной среде . Вызов plot теперь больше не отображает исходные данные y2 , кроме клонированной версии yf ( хранящейся в предварительно рассчитанном вспомогательном объекте FudgeAxis ), которая работает в масштабе y1 . Затем исходный объект ggplot обрабатывается вспомогательной функцией Кохске PlotWithFudgeAxis, чтобы добавить вторую ось, сохраняющую масштабы y2 . Это также сюжет манипулируемого сюжета.
Теперь график строится по желанию с двумя осями, y1 слева и y2 справа
Вышеупомянутое решение, прямо скажем, ограниченный шаткий взлом. Играя с ядром ggplot, он выдаст несколько предупреждений о том, что мы обмениваемся постфактум масштабами и т. Д. С ним нужно обращаться осторожно, и это может привести к нежелательному поведению в другой ситуации. Также может потребоваться возиться с вспомогательными функциями, чтобы получить макет по желанию. Размещение легенды - такая проблема (она будет помещена между панелью и новой осью; именно поэтому я ее и отбросил). Масштабирование / выравнивание оси 2 также немного сложное: приведенный выше код хорошо работает, когда обе шкалы содержат «0», иначе одна ось сдвигается. Так определенно с некоторыми возможностями для улучшения ...
В случае, если вы хотите сохранить картинку, нужно перевести вызов в устройство «открыть / закрыть»:
источник
Следующая статья помогла мне объединить два графика, сгенерированных ggplot2 в одной строке:
Несколько графиков на одной странице (ggplot2) от Cookbook for R
А вот как может выглядеть код в этом случае:
источник
multiplot
stackoverflow.com/a/51220506Для меня сложнее было выяснить функцию преобразования между двумя осями. Я использовал myCurveFit для этого.
Нахождение функции преобразования
функция преобразования:
f(y1) = 0.025*x + 2.75
функция преобразования:
f(y1) = 40*x - 110
Черчение
Обратите внимание, как функции преобразования используются в
ggplot
вызове для преобразования данных «на лету»Первый
stat_summary
вызов - это тот, который устанавливает основу для первой оси y. Второйstat_summary
вызов вызывается для преобразования данных. Помните, что все данные будут основаны на первой оси Y. Так что данные должны быть нормализованы для первой оси у. Для этого я использую функцию преобразования данных:y=packetOkSinr*40 - 110
Теперь , чтобы превратить вторую ось я использую функцию противоположной внутри
scale_y_continuous
вызова:sec.axis=sec_axis(~.*0.025+2.75, name="y_second")
.источник
coef(lm(c(-70, -110) ~ c(1,0)))
иcoef(lm(c(1,0) ~ c(-70, -110)))
. Вы можете определить вспомогательные функции , такие какequationise <- function(range = c(-70, -110), target = c(1,0)){ c = coef(lm(target ~ range)) as.formula(substitute(~ a*. + b, list(a=c[[2]], b=c[[1]]))) }
Мы , безусловно , могли бы построить сюжет с двумя Y-осях с использованием базового R Funtion
plot
.источник
Вы можете использовать
facet_wrap(~ variable, ncol= )
переменную для создания нового сравнения. Это не на одной оси, но это похоже.источник
Я признаю и согласен с Хэдли (и другими), что отдельные y-шкалы "в корне ошибочны". Сказав это - я часто хотел бы
ggplot2
иметь эту функцию - особенно, когда данные в широкоформатном формате, и я быстро хочу визуализировать или проверить данные (то есть только для личного использования).Хотя
tidyverse
библиотека позволяет довольно легко преобразовать данные в длинный формат (такой, которыйfacet_grid()
будет работать), процесс все еще не тривиален, как показано ниже:источник
sec_axis
.Ответ Хэдли дает интересную ссылку на отчет Стивена Фью « Двойные оси в графах». Являются ли они когда-либо лучшим решением? ,
Я не знаю, что означает OP с «счетами» и «скоростью», но быстрый поиск дает мне « Счет и скорость» , поэтому я получаю некоторые данные об авариях в североамериканском альпинизме 1 :
И затем я попытался сделать график, как предложили несколько на странице 7 вышеупомянутого отчета (и следуя запросу OP, чтобы построить график в виде гистограммы и ставок в виде линейного графика):
И вот результат:
Но мне это не очень нравится, и я не могу легко поставить легенду ...
1 УИЛЬЯМСОН, Джед и др. Аварии в североамериканском альпинизме 2005. Книги альпинистов, 2005.
источник
Казалось бы, это простой вопрос, но он связан с двумя фундаментальными вопросами. A) Как работать с мультискалярными данными при представлении в сравнительной диаграмме, и, во-вторых, B) можно ли это сделать без некоторых практических правил программирования R, таких как i) плавление данных, ii) огранка, iii) добавление другой слой к существующему. Приведенное ниже решение удовлетворяет обоим вышеперечисленным условиям, поскольку оно обрабатывает данные без необходимости их масштабирования, и, во-вторых, упомянутые методы не используются.
Вот результат,
Для тех, кто хочет узнать больше об этом методе, перейдите по ссылке ниже. Как построить 2-осевую диаграмму с столбцами рядом без повторного масштабирования данных
источник
Я обнаружил, что этот ответ помог мне больше всего, но обнаружил, что есть некоторые крайние случаи, которые он, кажется, не обрабатывает правильно, в частности, отрицательные случаи, а также случай, когда мои пределы были на расстоянии 0 (что может случиться, если мы захватываем наши пределы от макс / мин данных). Тестирование, кажется, показывает, что это работает последовательно
Я использую следующий код. Здесь я предполагаю, что у нас есть [x1, x2], который мы хотим преобразовать в [y1, y2]. То, как я справился с этим, состояло в том, чтобы преобразовать [x1, x2] в [0,1] (достаточно простой преобразователь), затем [0,1] в [y1, y2].
Ключевыми частями здесь является то, что мы преобразуем вторичную ось Y с помощью
~((.-ylim.prim[1]) *b + ylim.sec[1])
и затем применяем обратное значение к фактическим значениямy = ylim.prim[1]+(Temp-ylim.sec[1])/b)
. Мы должны также обеспечить этоlimits = ylim.prim
.источник