พล็อตตำนานนอกพื้นที่การวางแผนในกราฟิกพื้นฐานหรือไม่?


185

ตามที่ชื่อกล่าวว่า: ฉันจะพล็อตตำนานนอกพื้นที่การวางแผนเมื่อใช้กราฟิกพื้นฐานได้อย่างไร

ฉันคิดถึงเรื่องที่เล่น ๆ ไปด้วยlayoutและสร้างเนื้อเรื่องเปล่า ๆ เพื่อให้มีเพียงตำนาน แต่ฉันสนใจที่จะใช้วิธีการใช้กราฟกราฟพื้นฐานและpar(mar = )เพื่อให้มีพื้นที่ด้านขวาของเนื้อเรื่องสำหรับตำนาน


นี่คือตัวอย่าง:

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))

ผลิต:

ข้อความแสดงแทน

แต่ดังที่กล่าวไว้ฉันต้องการให้ตำนานอยู่นอกพื้นที่การวางแผน (เช่นทางด้านขวาของกราฟ / พล็อต


... นอกจากนี้คุณยังสามารถแฮ็คที่มีตัวจำลองสำหรับตำนานได้ง่ายและสะดวกเป็นครั้งคราว คำถามที่คล้ายกันที่นี่
hhh

3
@hhh ลิงก์ไม่ทำงานอีกต่อไป คุณสามารถอัพเดตหรือโพสต์คำตอบโดยใช้วิธีการนี้ได้หรือไม่?
Henrik

คำตอบ:


111

บางทีสิ่งที่คุณต้องการคือpar(xpd=TRUE)การเปิดใช้งานสิ่งต่าง ๆ ที่จะถูกดึงออกนอกขอบเขตการพล็อต ดังนั้นถ้าคุณทำพล็อตหลักด้วยbty='L'คุณจะมีที่ว่างทางด้านขวาสำหรับตำนาน โดยปกติสิ่งนี้จะถูกเล็มไปยังพื้นที่พล็อต แต่ทำได้par(xpd=TRUE)และด้วยการปรับเล็กน้อยคุณจะได้รับคำอธิบายที่ถูกต้องที่สุด:

 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))

33
โปรดทราบว่าคุณสามารถส่ง xpd ไปยังคำอธิบายโดยตรงเพื่อให้คุณไม่ต้องกังวลเกี่ยวกับการรีเซ็ตพาร์ในภายหลัง ดู grconvertX & Y เพื่อหาวิธีระบุตำแหน่งของคำอธิบายด้วยวิธีที่ไม่ขึ้นอยู่กับขีด จำกัด ของข้อมูลที่คุณกำลังวางแผน
ชาร์ลส์

6
เนื่องจากคำถามและคำตอบนี้ยังคงได้รับความนิยมอย่างpar(xpd=NA)มากมีประสิทธิภาพยิ่งขึ้น (เช่นแปลงไปยังภูมิภาคอื่น ๆ )
Henrik

+1 เราควรพูดถึงว่ามันเหมาะสมที่จะมีการparโทรแยกต่างหากก่อนตำนาน ในพล็อตของฉันฉันใช้par(new=T)หลายครั้งและต้องการเพิ่มxpdพารามิเตอร์ในการโทรเดียวกันซึ่งทำให้เกิดปัญหา
Matt Bannert

146

ไม่มีใครได้กล่าวถึงการใช้ในเชิงลบค่าinset legendนี่คือตัวอย่างโดยที่คำอธิบายแผนภูมิอยู่ทางด้านขวาของพล็อตชิดกับด้านบน (ใช้คำหลัก"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")

ค่าแรกของinset=c(-0.2,0)อาจจำเป็นต้องปรับขึ้นอยู่กับความกว้างของตำนาน

legend_right


14
@Henrik ไม่ทำงานโดย xpd = TRUE โปรดทราบว่าการตั้งค่า xpd = TRUE เป็นอาร์กิวเมนต์ของฟังก์ชัน legend () จะดีกว่า
Stéphane Laurent

1
บางครั้งxpdต้องตั้งค่าให้TRUEสิ่งที่ใส่เข้าไปทำงาน แต่บางครั้งก็ไม่ ด้วยคำสั่งargs.legend=list(x="bottom", horiz=TRUE, inset=-0.2)ภายในbarplot(...มันไม่จำเป็นที่จะต้อง seemd xpd=TRUEแต่มีเพียงไม่ดูเหมือนจะจำเป็นlegend(x="bottom", horiz=TRUE, inset=-0.2) xpd=TRUEข้อมูลเชิงลึกใด ๆ ฉันแค่สับสนในการผ่านการโต้แย้งของฉัน?
user3386170

28

อีกวิธีหนึ่งที่นอกเหนือจาก ondes ที่กล่าวถึงแล้ว (การใช้layoutหรือpar(xpd=TRUE)) คือการวางโครงเรื่องของคุณด้วยพล็อตที่โปร่งใสบนอุปกรณ์ทั้งหมดแล้วเพิ่มคำอธิบายประกอบลงในนั้น

เคล็ดลับคือการซ้อนกราฟ (ว่าง) บนพื้นที่การวางแผนที่สมบูรณ์และเพิ่มคำอธิบายลงในนั้น เราสามารถใช้par(fig=...)ตัวเลือก ก่อนอื่นเราแนะนำให้ R สร้างพล็อตใหม่ผ่านอุปกรณ์การลงจุดทั้งหมด:

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

การตั้งค่าomaและmarจำเป็นเนื่องจากเราต้องการให้การตกแต่งภายในของพล็อตครอบคลุมอุปกรณ์ทั้งหมด new=TRUEจำเป็นเพื่อป้องกัน R ไม่ให้เริ่มอุปกรณ์ใหม่ จากนั้นเราสามารถเพิ่มพล็อตที่ว่างเปล่า:

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

และเราพร้อมที่จะเพิ่มตำนาน:

legend("bottomright", ...)

จะเพิ่มคำอธิบายประกอบที่ด้านล่างขวาของอุปกรณ์ ในทำนองเดียวกันเราสามารถเพิ่มคำอธิบายแผนภูมิลงบนระยะขอบด้านบนหรือด้านขวา สิ่งเดียวที่เราต้องมั่นใจคือขอบของพล็อตดั้งเดิมนั้นใหญ่พอที่จะรองรับตำนาน

การนำทั้งหมดนี้ไปใช้ในฟังก์ชั่น

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(...)
}

และเป็นตัวอย่าง ขั้นแรกสร้างพล็อตเพื่อให้แน่ใจว่าเรามีพื้นที่ว่างด้านล่างเพื่อเพิ่มคำอธิบาย:

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

จากนั้นเพิ่มคำอธิบาย

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

ที่เกิดขึ้นใน:

ภาพตัวอย่างแสดงคำอธิบายสัญลักษณ์ในระยะขอบบนสุด


2
นอกจากนี้ยอดเยี่ยมในรายการที่นี่ มีคำอธิบายเกี่ยวกับวิธีที่จะทำให้งานนี้มีหลายแปลงในภาพเป็นที่นี่
shiri

ม.ค. มีวิธีเพิ่มขนาดตัวอักษรในคำอธิบายโดยไม่มีการตัดข้อความหรือไม่? ตัวอย่างเช่นฉันมีป้ายกำกับกราฟิก 4 ประเภทที่แตกต่างกัน แต่มีช่องว่างว่างระหว่างพวกเขามาก
ชายแก่ในทะเล

ฉันเขียนคำถามพร้อมรายละเอียดเพิ่มเติมstackoverflow.com/questions/42707308/…
ชายชราคนหนึ่งในทะเล

16

ขออภัยสำหรับการคืนค่าเธรดเก่าอีกครั้ง แต่ฉันมีปัญหาเดียวกันวันนี้ วิธีที่ง่ายที่สุดที่ฉันได้พบคือต่อไปนี้:

# 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)

พบได้ที่นี่: http://www.harding.edu/fmccown/R/


4
ดียิ่งขึ้นคือ oldpar <- par (xpd = T, mar = par () $ mar + c (0,0,0,6)) ... par (oldpar) (ดูความช่วยเหลือของพาร์)
rakensi

การแก้ปัญหานี้ดีกว่าเพราะพื้นที่สำหรับตำนานได้รับการแก้ไขไม่ว่าความยาวของสตริงของตำนาน
Sergio

15

ฉันชอบที่จะทำสิ่งนี้:

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))

ป้อนคำอธิบายรูปภาพที่นี่

การปรับแต่งเพียงอย่างเดียวคือการตั้งค่าระยะขอบด้านขวาให้กว้างพอที่จะรองรับตำนาน

อย่างไรก็ตามสิ่งนี้สามารถเป็นอัตโนมัติได้:

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))

ป้อนคำอธิบายรูปภาพที่นี่


การใช้ xpd = T หรือ xpd = NA ไม่ได้ป้องกัน 'main' (ชื่อเรื่อง) ของฉันจากการถูกเล็มเมื่อยืดเพื่อพยายามใช้พื้นที่ที่เพิ่มด้วยระยะขอบขวากว้าง
Phil Goetz

@PhilGoetz คุณแน่ใจหรือไม่ว่าคุณกำลังวางแผนหลักภายในพื้นที่วางแผน เป็นไปได้หรือไม่ที่คุณไม่มีเส้นขอบที่เพียงพอในการพล็อต
jbaums

10

เมื่อเร็ว ๆ นี้ฉันพบฟังก์ชั่นที่ง่ายและน่าสนใจในการพิมพ์คำอธิบายแผนภูมินอกพื้นที่ที่คุณต้องการ

ทำระยะขอบด้านนอกที่ด้านขวาของพล็อต

par(xpd=T, mar=par()$mar+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")

เพิ่มคำอธิบายแผนภูมิและเพียงใช้ตัวระบุตำแหน่ง (1) ฟังก์ชั่นเช่นเดียวกับด้านล่าง จากนั้นคุณต้องคลิกที่ที่คุณต้องการหลังจากโหลดสคริปต์ต่อไปนี้

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

ลองมัน


9

ฉันสามารถเสนอตัวอย่างของโซลูชันเลย์เอาต์ที่ชี้ไปแล้วเท่านั้น

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))

ภาพที่น่าเกลียด:


9

การเพิ่มอีกทางเลือกง่าย ๆ ที่ค่อนข้างหรูหราในความคิดของฉัน

พล็อตของคุณ:

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("bottomright", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
       inset=c(0,1), xpd=TRUE, horiz=TRUE, bty="n"
       )

ผลลัพธ์:

ภาพที่มีตำนาน

ที่นี่มีเพียงตำนานสองบรรทัดเท่านั้นที่ถูกเพิ่มเข้าไปในตัวอย่างของคุณ ในทางกลับกัน:

  • inset=c(0,1)- ย้ายคำอธิบายแผนภูมิตามส่วนของพื้นที่พล็อตในทิศทาง (x, y) ในกรณีนี้ตำนานอยู่ใน"bottomright"ตำแหน่ง มันถูกย้ายโดย 0 พื้นที่การวางแผนในทิศทาง x (ดังนั้นอยู่ที่ "ขวา") และโดย 1 พื้นที่การวางแผนในทิศทาง y (จากล่างขึ้นบน) และมันเกิดขึ้นเมื่อมันปรากฏขึ้นเหนือพล็อต
  • xpd=TRUE - ให้ตำนานปรากฏขึ้นนอกขอบเขตการวางแผน
  • horiz=TRUE - สั่งให้สร้างตำนานแนวนอน
  • bty="n" - รายละเอียดสไตล์การกำจัดกล่องคำอธิบายแผนภูมิ

เช่นเดียวกันเมื่อเพิ่มคำอธิบายลงในด้าน:

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"
       )

ที่นี่เราปรับตำแหน่งคำอธิบายภาพและเพิ่มพื้นที่มาร์จิ้นเพิ่มเติมทางด้านขวาของพล็อต ผลลัพธ์:

ภาพที่มีตำนาน 2


4

คุณสามารถทำได้ด้วยPlotly R APIด้วยโค้ดหรือจาก GUI โดยการลากคำอธิบายที่คุณต้องการ

นี่คือตัวอย่าง กราฟและรหัสอยู่ที่นี่ด้วย

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)

คุณสามารถวางตำแหน่งคำอธิบายแผนภูมิภายนอกกราฟโดยกำหนดค่า x และ y หนึ่งค่าให้กับ 100 หรือ -100

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

นี่คือตัวเลือกอื่น ๆ :

  • list("x" = 100, "y" = 0) สำหรับภายนอกขวาล่าง
  • list("x" = 100, "y"= 1) ด้านนอกขวาด้านบน
  • list("x" = 100, "y" = .5) ด้านนอกขวาตรงกลาง
  • list("x" = 0, "y" = -100) ใต้ซ้าย
  • list("x" = 0.5, "y" = -100) ภายใต้ศูนย์
  • list("x" = 1, "y" = -100) ภายใต้ขวา

จากนั้นตอบสนอง

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

โปรดส่งคืน URL ด้วยกราฟของคุณเมื่อคุณโทรออก คุณสามารถเข้าถึงได้เร็วขึ้นโดยการโทรbrowseURL(response$url)เพื่อที่จะเปิดกราฟในเบราว์เซอร์ของคุณ

url = response$url
filename = response$filename

นั่นทำให้เรากราฟนี้ นอกจากนี้คุณยังสามารถย้ายคำอธิบายภาพได้จากใน GUI จากนั้นกราฟจะปรับขนาดตามความเหมาะสม การเปิดเผยแบบเต็ม: ฉันอยู่ในทีม Plotly

ตำนานด้านกราฟ


2

ลองใช้layout()สิ่งที่ฉันเคยทำในอดีตโดยเพียงแค่สร้างพล็อตที่ว่างเปล่าด้านล่างปรับขนาดอย่างถูกต้องที่ประมาณ 1/4 หรือประมาณนั้นและวางชิ้นส่วนตำนานไว้ด้วยตนเอง

มีคำถามเก่า ๆ อยู่ที่นี่เกี่ยวกับlegend()สิ่งที่ควรให้คุณเริ่มต้น


อย่างที่พูดไปแล้วในคำถามนี่คือสิ่งที่ฉันคิดด้วย แต่มันจะเหมาะถ้ามีอีกวิธี ยังไงก็เถอะฉันคิดว่าไม่มี
Henrik
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.