Установите поля для размещения большой легенды

Я пытаюсь найти способ рассчитать высоту легенды для графика до установки полей графика. Я намерен разместить легенду под графиком под метками оси X и заголовком.

Поскольку это часть функции, которая отображает ряд вещей, легенда может увеличиваться и уменьшаться в размерах, чтобы обслуживать 2 элемента, до 15 или более, поэтому мне нужно выяснить, как я могу сделать это динамически, а не жестко кодировать . Итак, в конце концов мне нужно динамически установить поля и некоторые другие кусочки.

Ключевая проблема состоит в том, чтобы определить высоту легенды, которую нужно ввести в par(mar), до рисования графика, но после анализа базовых кодов для легенды, однако, кажется невозможным получить точную оценку значения высоты, если график не нарисован на самом деле. (курица и яйцо кто-нибудь?)

Вот что я уже пробовал:

  1. получить высоту, используя вывод legend$rect$h из функции базовой легенды (которая, кажется, дает неверное значение высоты, если только график не нарисован)

  2. подсчитайте количество строк в легенде (легко) и умножьте это на высоту строки (чтобы сделать это, кажется, вам нужно перевести в дюймы (код базовой легенды использует yinch, и я также пробовал grconvertY, но ни этих произведений, если не был нарисован сюжет).

Еще одна проблема заключается в том, чтобы определить правильное значение y для размещения легенды — я полагаю, что как только я решу первую задачу, вторая будет легкой.

ИЗМЕНИТЬ:

После дня мучений над тем, как это (не) работает. У меня есть пара идей и пара вопросов. Для ясности, это то, что по существу делает моя функция:

шаг 1) установить поля

шаг 2) создайте гистограмму на левой оси

шаг 3) переустановите координаты usr - это необходимо для обеспечения выравнивания правой оси, в противном случае он будет отображаться по шкале оси x. Нехорошо, когда они заметно отличаются.

шаг 4) создайте правую ось

шаг 5) создайте серию линейных диаграмм на правой оси

шаг 6) сделайте некоторую маркировку двух осей и оси x

шаг 7) добавить легенду

Вот вопросы

Q1) В каких единицах сообщается о вещах? Меня интересуют границы полей и координаты (пользовательские координаты), дюймы говорят сами за себя. - Я могу сделать некоторые преобразования, используя grconvertY(), но я не уверен, на что я смотрю и во что я должен преобразовываться - документация не так хороша.

Q2) Мне нужно установить поле на шаге 1, чтобы в нижней части диаграммы было достаточно места для легенды. Я думаю, что правильно понял, однако мне нужно установить легенду после того, как правая ось и линейные диаграммы установлены, что означает, что пользовательские координаты (и значение пикселя в дюйме) изменились. Из-за Q1 выше I' Я не знаю, как перевести одну систему в другую. Буду признателен за любые идеи на этот счет.


person Timmwardion    schedule 13.05.2014    source источник
comment
вы можете сгенерировать легенду и присвоить ее переменной, а не строить ее — используйте опцию plot=FALSE   -  person user20650    schedule 13.05.2014
comment
Спасибо пользователю 20650. Я пробовал это, и я получаю неправильные результаты, если я вызываю его до создания сюжета. Вот как я получил доступ к $rect$h, это результат использования plot=FALSE с функцией легенды.   -  person Timmwardion    schedule 13.05.2014


Ответы (1)


После еще одного дня пота над этим вот что решило это в основном для меня.

Я разобрал код основной функции легенды и скомпилировал это:

#calculate legend buffer
cin <- par("cin")
Cex <- par("cex")
yc <- Cex * cin[2L] #cin(inches) * maginfication
yextra <- 0
ymax <- yc * max(1, strheight("Example", units = "inches", cex = Cex)/yc)
ychar <- yextra + ymax #coordinates
legendHeight <- (legendLines * ychar) + yc # in

По сути, это имитирует способ, которым базовая функция вычисляет высоту легенды, но возвращает высоту в дюймах, а не в пользовательских координатах. legendLines — количество строк в легенде.

После этого несложно разобраться, как разместить легенду и правильно установить нижнее поле. Я использую:

#calculate inches per margin line
inchesPerMarLine<-par("mai")[1]/par("mar")[1]

Чтобы рассчитать количество дюймов на линию поля, а затем установить буферы (для подписей оси и заголовка, а также нижней части диаграммы) и поля графика.

#set buffers
bottomBuffer = 1
buffer=2

#calculate legend buffer
legBuffer <- legendHeight/inchesPerMarLine

#start the new plot
plot.new()

# set margin
bottomMargin <- buffer + legBuffer + bottomBuffer
par(mar=c(bottomMargin,8,3,5))

Сюжет сделан

barplot(data, width=1, col=barCol, names.arg=names,  ylab="", las=1 ,axes=F, ylim=c(0,maxL), axis.lty=1)

А потом легенда помещается. Я использовал другой метод для извлечения ширины легенды, который имеет некоторые проблемы, когда есть легенда с 1 точкой, однако на данный момент он работает нормально. Помещение легенды в переменную позволяет вам получить доступ к ширине поля, например l$rect$w. trace=TRUE и plot=FALSE пока останавливают запись легенды на график.

ycoord <- -1*(yinch(inchesPerMarLine*buffer)*1.8)
l<-legend(x=par("usr")[1], y=ycoord, inset=c(0,-0.25), legendText, fill=legendColour, horiz=FALSE, bty = "n", ncol=3, trace=TRUE,plot=FALSE)
lx <- mean(par("usr")[1:2]-(l$rect$w/2))
legend(x=lx, y=ycoord, legendText, fill=legendColour, horiz=FALSE, bty = "n", ncol=3)

Для полноты, вот как я вычисляю количество строк в легенде. Примечание. Количество столбцов в легенде равно 3. labelSeries — список меток легенды.

legendLines <- ceiling(nrow(labelSeries)/3)
person Timmwardion    schedule 16.05.2014