Wykreślić legendę poza obszarem kreślenia w grafice bazowej?

Jak w tytule jest napisane: Jak mogę wykreślić legendę poza obszarem kreślenia, używając Grafiki bazowej?

Myślałem o grzebaniu w layout i wytworzeniu pustego wykresu, który zawierałby tylko legendę, ale byłbym zainteresowany sposobem wykorzystania tylko podstawowych funkcji wykresu i np. par(mar = ), aby uzyskać trochę miejsca po prawej stronie wykresu dla legendy.


Oto przykład:

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
legend(1,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

Produkuje:

alt text

Ale jak już powiedziałem, chciałbym, aby legenda być poza obszarem kreślenia (np. po prawej stronie wykresu / wykresu.

 144
Author: Henrik, 2010-10-14

10 answers

Być może potrzebujesz par(xpd=TRUE), aby umożliwić rysowanie rzeczy poza obszarem działki. Więc jeśli zrobisz główną fabułę bty='L', będziesz miał trochę miejsca po prawej stronie na legendę. Normalnie byłoby to przycięte do obszaru wykresu, ale zrób par(xpd=TRUE) i przy odrobinie korekty możesz uzyskać legendę tak daleko, jak to tylko możliwe:

 set.seed(1) # just to get the same random numbers
 par(xpd=FALSE) # this is usually the default

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2), bty='L')
 # this legend gets clipped:
 legend(2.8,0,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

 # so turn off clipping:
 par(xpd=TRUE)
 legend(2.8,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))
 92
Author: Spacedman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-12 15:04:18

Nikt nie wspomniał o użyciu ujemnych wartości inset dla legend. Oto przykład, gdzie legenda znajduje się po prawej stronie wykresu, wyrównana do góry (używając słowa kluczowego "topright").

# Random data to plot:
A <- data.frame(x=rnorm(100, 20, 2), y=rnorm(100, 20, 2))
B <- data.frame(x=rnorm(100, 21, 1), y=rnorm(100, 21, 1))

# Add extra space to right of plot area; change clipping to figure
par(mar=c(5.1, 4.1, 4.1, 8.1), xpd=TRUE)

# Plot both groups
plot(y ~ x, A, ylim=range(c(A$y, B$y)), xlim=range(c(A$x, B$x)), pch=1,
               main="Scatter plot of two groups")
points(y ~ x, B, pch=3)

# Add legend to top right, outside plot region
legend("topright", inset=c(-0.2,0), legend=c("A","B"), pch=c(1,3), title="Group")

Pierwsza wartość inset=c(-0.2,0) może wymagać dostosowania na podstawie szerokości legendy.

legend_right

 122
Author: Mike T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-10 05:36:05

Innym rozwiązaniem, poza wspomnianymi już ondami (za pomocą layout lub par(xpd=TRUE)), jest nałożenie wykresu przezroczystym wykresem na całe urządzenie, a następnie dodanie do niego legendy.

Sztuką jest nałożenie (pustego) wykresu na cały obszar kreślenia i dodanie do niego legendy. Możemy użyć opcji par(fig=...). Najpierw instruujemy R, aby stworzył nowy wykres na całym urządzeniu kreślącym:

par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE)

Ustawienie oma i mar jest potrzebne, ponieważ chcemy mieć wnętrze działki obejmują całe urządzenie. new=TRUE jest konieczne, aby zapobiec uruchomieniu nowego urządzenia. Następnie możemy dodać pusty wykres:

plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')

I jesteśmy gotowi dodać legendę:

legend("bottomright", ...)

Doda legendę w prawym dolnym rogu urządzenia. Podobnie możemy dodać legendę do górnego lub prawego marginesu. Jedyne, co musimy zapewnić, to to, że margines oryginalnej fabuły jest wystarczająco duży, aby pomieścić legendę.

Wkładanie tego wszystkiego do function;

add_legend <- function(...) {
  opar <- par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), 
    mar=c(0, 0, 0, 0), new=TRUE)
  on.exit(par(opar))
  plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
  legend(...)
}

I przykład. Najpierw Utwórz fabułę upewniając się, że mamy wystarczająco dużo miejsca na dole, aby dodać legendę: {]}

par(mar = c(5, 4, 1.4, 0.2))
plot(rnorm(50), rnorm(50), col=c("steelblue", "indianred"), pch=20)

Następnie dodaj legendę

add_legend("topright", legend=c("Foo", "Bar"), pch=20, 
   col=c("steelblue", "indianred"),
   horiz=TRUE, bty='n', cex=0.8)

W wyniku:

Przykładowa figura pokazana na górnym marginesie

 21
Author: Jan van der Laan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-14 16:06:31

Przepraszam za wskrzeszenie starego wątku, ale miałem dziś ten sam problem. Najprostszy sposób, który znalazłem jest następujący:

# Expand right side of clipping rect to make room for the legend
par(xpd=T, mar=par()$mar+c(0,0,0,6))

# Plot graph normally
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

# Plot legend where you want
legend(3.2,1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

# Restore default clipping rect
par(mar=c(5, 4, 4, 2) + 0.1)

Znaleziono tutaj: http://www.harding.edu/fmccown/R/

 12
Author: veiga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-24 18:02:43

Lubię to robić tak:

par(oma=c(0, 0, 0, 5))
plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch=2, lty=2, type="o")
legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
       c("group A", "group B"), pch=c(1, 2), lty=c(1,2))

Tutaj wpisz opis obrazka

Jedynym wymaganym ulepszeniem jest ustawienie prawego marginesu, aby był wystarczająco szeroki, aby pomieścić legendę.

Jednak można to również zautomatyzować:

dev.off() # to reset the graphics pars to defaults
par(mar=c(par('mar')[1:3], 0)) # optional, removes extraneous right inner margin space
plot.new()
l <- legend(0, 0, bty='n', c("group A", "group B"), 
            plot=FALSE, pch=c(1, 2), lty=c(1, 2))
# calculate right margin width in ndc
w <- grconvertX(l$rect$w, to='ndc') - grconvertX(0, to='ndc')
par(omd=c(0, 1-w, 0, 1))
plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2, 2))
lines(1:3, rnorm(3), pch=2, lty=2, type="o")
legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
       c("group A", "group B"), pch=c(1, 2), lty=c(1, 2))

Tutaj wpisz opis obrazka

 11
Author: jbaums,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-06 02:49:22

Mogę zaoferować tylko przykład rozwiązania układu już wskazanego.

layout(matrix(c(1,2), nrow = 1), widths = c(0.7, 0.3))
par(mar = c(5, 4, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
par(mar = c(5, 0, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, ylim=c(-2,2), type = "n", axes = FALSE, ann = FALSE)
legend(1, 1, c("group A", "group B"), pch = c(1,2), lty = c(1,2))

brzydkie Zdjęcie: S

 7
Author: Roman Luštrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-14 11:01:00

Ostatnio znalazłem bardzo łatwą i ciekawą funkcję drukowania legendy poza obszarem działki, gdzie chcesz.

Zrób zewnętrzny margines po prawej stronie działki.

par(xpd=T, mar=par()$mar+c(0,0,0,5))

Tworzenie wykresu

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

Dodaj legendę i po prostu użyj funkcji locator (1) Jak Poniżej. Następnie musisz po prostu kliknąć, gdzie chcesz po załadowaniu następującego skryptu.

legend(locator(1),c("group A", "group B"), pch = c(1,2), lty = c(1,2))

Try it

 7
Author: Vandka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-11 02:40:24

Możesz to zrobić za pomocą Plotly R API , z kodem lub z GUI, przeciągając legendę tam, gdzie chcesz.

Oto przykład. Wykres i Kod są również tutaj .

x = c(0,1,2,3,4,5,6,7,8) 
y = c(0,3,6,4,5,2,3,5,4) 
x2 = c(0,1,2,3,4,5,6,7,8) 
y2 = c(0,4,7,8,3,6,3,3,4)

Możesz ustawić legendę poza wykresem, przypisując jedną z wartości x i y 100 lub -100.

legendstyle = list("x"=100, "y"=1)
layoutstyle = list(legend=legendstyle)

Oto inne opcje:

  • list("x" = 100, "y" = 0) Na Zewnątrz prawego dołu
  • list("x" = 100, "y"= 1) Poza Prawym Górnym
  • list("x" = 100, "y" = .5) Poza Prawym Środkiem
  • list("x" = 0, "y" = -100) Pod Lewym
  • list("x" = 0.5, "y" = -100) Under Center
  • list("x" = 1, "y" = -100) Under Right

Następnie odpowiedź.

response = p$plotly(x,y,x2,y2, kwargs=list(layout=layoutstyle));

Plotly zwraca adres URL z wykresem podczas wykonywania połączenia. Możesz uzyskać do niego dostęp szybciej, dzwoniąc browseURL(response$url), aby otworzyć twój wykres w przeglądarce.

url = response$url
filename = response$filename

To daje nam ten wykres. Możesz również przenieść legendę z poziomu GUI, a następnie wykres będzie skalowany odpowiednio. / Align = "left"/

Legenda po stronie wykresu

 3
Author: Mateo Sanchez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-20 21:20:14

Spróbuj layout(), którego używałem do tego w przeszłości, po prostu tworząc pusty wykres poniżej, odpowiednio przeskalowany na około 1/4 i ręcznie umieszczając w nim części legendy.

Jest kilka starszych pytań o legend(), które powinny zacząć.

 1
Author: Dirk Eddelbuettel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-14 10:17:27

Dodanie kolejnej prostej alternatywy, która moim zdaniem jest dość elegancka.

Twoja fabuła:

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

Legenda:

legend("bottomright", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
       inset=c(0,1), xpd=TRUE, horiz=TRUE, bty="n"
       )

Wynik:

obraz z legendą

Tutaj tylko druga linijka legendy została dodana do twojego przykładu. Z kolei:

  • inset=c(0,1) - przesuwa legendę o ułamek obszaru wykresu w kierunkach (x,y). W tym przypadku legenda znajduje się na pozycji "bottomright". Przesuwa się o 0 obszarów kreślenia w kierunku x (więc pozostaje na "prawo") i o 1 kreślenia region w kierunku y (od dołu do góry). I tak się składa, że pojawia się tuż nad fabułą.
  • xpd=TRUE - niech legenda pojawi się poza regionem spisku.
  • horiz=TRUE - nakazuje stworzenie poziomej legendy.
  • bty="n" - detal stylu, aby pozbyć się obwiedni legendy.

To samo dotyczy dodawania legendy do strony:

par(mar=c(5,4,2,6))
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

legend("topleft", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
       inset=c(1,0), xpd=TRUE, bty="n"
       )

Tutaj po prostu dostosowaliśmy pozycje legend i dodaliśmy dodatkowy margines po prawej stronie fabuły. Wynik:

obraz z legendą 2

 0
Author: Karolis Koncevičius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 22:00:05