ตำแหน่งป้ายชื่อจุดอัจฉริยะใน R


102

1) มี R ไลบรารี / ฟังก์ชันใดบ้างที่จะใช้การจัดวางป้ายกำกับอัจฉริยะใน R plot ฉันลองใช้บ้าง แต่ก็มีปัญหาทั้งหมด - ป้ายกำกับจำนวนมากซ้อนทับกันหรือจุดอื่น ๆ (หรือวัตถุอื่น ๆ ในพล็อต แต่ฉันเห็นว่ามันยากกว่ามากที่จะจัดการ)

2) หากไม่เป็นเช่นนั้นมีวิธีใดบ้างที่จะช่วยให้อัลกอริทึมสะดวกสบายในการจัดวางฉลากสำหรับจุดที่มีปัญหา ต้องการโซลูชันที่สะดวกสบายและมีประสิทธิภาพที่สุด

คุณสามารถเล่นและทดสอบความเป็นไปได้อื่น ๆ ด้วยตัวอย่างที่ทำซ้ำได้ของฉันและดูว่าคุณสามารถบรรลุผลลัพธ์ที่ดีกว่าที่ฉันมีได้หรือไม่:

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")

# basic plot
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

สำหรับการติดฉลากฉันลองใช้ความเป็นไปได้เหล่านี้แล้วไม่มีใครดีจริงๆ:

1) อันนี้แย่มาก:

text(x, y, labels = ShortSci, cex= 0.7, offset = 10)

2) อันนี้ดีถ้าคุณไม่ต้องการวางป้ายกำกับสำหรับทุกจุด แต่สำหรับค่าผิดปกติ แต่ถึงกระนั้นป้ายกำกับมักจะวางผิด:

identify(x, y, labels = ShortSci, cex = 0.7)

3) อันนี้ดูน่าสนใจ แต่มีปัญหาเรื่องฉลากอยู่ใกล้กับจุดมากเกินไป ฉันต้องเว้นวรรค แต่มันไม่ได้ช่วยอะไรมาก:

require(maptools)
pointLabel(x, y, labels = paste("  ", ShortSci, "  ", sep=""), cex=0.7)

4)

require(plotrix)
thigmophobe.labels(x, y, labels = ShortSci, cex=0.7, offset=0.5)

5)

require(calibrate)
textxy(x, y, labs=ShortSci, cx=0.7)

ขอบคุณล่วงหน้า!

แก้ไข:สิ่งที่ต้องทำ: ลองlabcurve {}


2
คำตอบสำหรับคำถาม R ดูเหมือนจะแบ่งเท่า ๆ กันระหว่าง StackOverflow และ CrossValidated ในกรณีนี้คำถามซ้ำกับคำถามเมื่อ4 วันก่อนตรงนั้น
Ed Staub

3
ฉันพบปัญหาที่คล้ายกันและเขียนแพ็คเกจพื้นฐานที่ใช้การจำลองสนามพลังเพื่อปรับตำแหน่งวัตถุ แม้ว่าจะสามารถปรับปรุงได้มากรวมถึงการผสานรวมกับ ggplot ฯลฯ ดูเหมือนว่าจะทำให้งานสำเร็จ ต่อไปนี้แสดงให้เห็นถึงการทำงาน หากมีคนพบปัญหาและค้นหาคำตอบหวังว่านี่จะช่วยได้บ้าง:install.packages("FField") library(FField) FFieldPtRepDemo()
gregk

ฉันขอให้คุณลองggrepel ได้ไหม
Kamil Slowikowski

ที่รัก @Joran โปรดใส่ความคิดเห็นของคุณ "6) สำหรับกราฟ ggplot2 มีตัวเลือกใหม่ที่เรียกว่า ggrepel ซึ่งหลายคนดูเหมือนจะชอบ" ในความคิดเห็นหรือคำตอบ นี่ฉันรวมเฉพาะรายการของตัวเลือกฉันพยายาม แต่ไม่ได้เป็นที่น่าพอใจ หากเป็นสิ่งที่ใช้งานได้ดีก็ควรเป็นคำตอบ
TMS

คำตอบ:


49

ขั้นแรกนี่คือผลลัพธ์ของการแก้ปัญหาของฉันสำหรับปัญหานี้:

ใส่คำอธิบายภาพที่นี่

ฉันทำสิ่งนี้ด้วยมือใน Preview (โปรแกรมดู PDF / รูปภาพพื้นฐานบน OS X) ในเวลาเพียงไม่กี่นาที ( แก้ไข:ขั้นตอนการทำงานเป็นสิ่งที่คุณคาดหวัง: ฉันบันทึกพล็อตเป็น PDF จาก R เปิดใน Preview และสร้างกล่องข้อความพร้อมป้ายกำกับที่ต้องการ (9pt Helvetica) จากนั้นลากเมาส์ไปรอบ ๆ จนกว่าพวกเขาจะดู ดีจากนั้นฉันส่งออกเป็น PNG เพื่ออัปโหลดไปยัง SO)

ตอนนี้ก่อนที่คุณจะยอมจำนนต่อแรงกระตุ้นที่รุนแรงในการลงคะแนนสิ่งนี้เป็นการให้อภัยและแสดงความคิดเห็นที่น่ารังเกียจเกี่ยวกับประเด็นที่จะทำให้กระบวนการนี้เป็นไปโดยอัตโนมัติฟังฉันออก!

การมองหาโซลูชันอัลกอริทึมนั้นใช้ได้ดีและ (IMHO) น่าสนใจจริงๆ แต่สำหรับฉันแล้วสถานการณ์การติดฉลากแบบชี้แบ่งออกเป็นสามประเภท:

  1. คุณมีคะแนนเพียงเล็กน้อยไม่มีจุดใดที่อยู่ใกล้กันมาก ในกรณีนี้หนึ่งในวิธีแก้ปัญหาที่คุณระบุไว้ในคำถามนั้นน่าจะใช้ได้ผลกับการปรับแต่งที่ค่อนข้างน้อย
  2. คุณมีจำนวนเล็ก ๆ ของจุดบางส่วนที่จะถูกบรรจุอย่างใกล้ชิดเกินไปสำหรับการแก้ปัญหาขั้นตอนโดยทั่วไปจะให้ผลลัพธ์ที่ดี ในกรณีนี้เนื่องจากคุณเพียง แต่มีขนาดเล็กจำนวนจุดติดฉลากพวกเขาด้วยมือ (ทั้งที่มีโปรแกรมแก้ไขภาพหรือปรับจูนเรียกร้องให้text) ไม่ได้ว่าใช้ความพยายามมาก
  3. คุณมีจำนวนที่ค่อนข้างใหญ่ของจุด ในกรณีนี้คุณไม่ควรติดป้ายกำกับเนื่องจากเป็นการยากที่จะประมวลผลฉลากจำนวนมากด้วยสายตา

: ปีนขึ้นไปบนสบู่:

เนื่องจากคนอย่างเราชอบระบบอัตโนมัติฉันคิดว่าเรามักจะตกอยู่ในกับดักของการคิดว่าเกือบทุกแง่มุมของการสร้างกราฟิกทางสถิติที่ดีควรเป็นแบบอัตโนมัติ ฉันขอแสดงความนับถือ (นอบน้อม!)

ไม่มีสภาพแวดล้อมการพล็อตเชิงสถิติทั่วไปที่สมบูรณ์แบบที่สร้างภาพที่คุณมีอยู่ในหัวโดยอัตโนมัติ สิ่งที่ชอบ R, ggplot2 ตาข่าย ฯลฯ ทำมากที่สุดของการทำงาน; แต่การปรับแต่งเพิ่มเติมเล็กน้อยเพิ่มเส้นตรงนี้ปรับระยะขอบตรงนั้นน่าจะเหมาะกับเครื่องมืออื่นมากกว่า

: ปีนลงมาจากสบู่:

ฉันจะสังเกตด้วยว่าฉันคิดว่าเราทุกคนสามารถสร้าง scatterplots ที่มี <10-15 จุดซึ่งแทบจะเป็นไปไม่ได้เลยที่จะติดฉลากอย่างหมดจดแม้จะทำด้วยมือก็ตามและสิ่งเหล่านี้อาจทำให้โซลูชันอัตโนมัติที่ใครบางคนคิด

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

เหตุผลที่ฉันโพสต์คำตอบนี้ก็คือฉันคิดว่าคำถามนี้ควรเป็นคำถาม "การติดฉลากจุดใน R" ที่ยอมรับได้สำหรับการทำซ้ำในอนาคตและฉันคิดว่าโซลูชันที่เกี่ยวข้องกับการติดฉลากด้วยมือควรได้รับที่นั่งที่โต๊ะนั่นคือทั้งหมดที่


10
อีกวิธีด้วยตนเองคือบันทึกพล็อตเป็น SVG และแก้ไขโดยใช้ Inkscape จากนั้นสร้าง PDF จากนั้น
Spacedman

สวัสดี joran ขอบคุณสำหรับคำตอบของคุณ ตกลงฉันยอมรับวิธีแก้ปัญหานี้แม้ว่าฉันคิดว่าคอมพิวเตอร์ควรทำสิ่งนี้ให้ดีที่สุดก่อนและจากนั้นขอการแทรกแซงด้วยตนเอง ฉันกำลังมองหาวิธีแก้ปัญหาที่สะดวกสบายและรวดเร็วที่สุด คุณช่วยอธิบายวิธีการสร้างพล็อตทีละขั้นตอนได้ไหม สิ่งที่คุณสร้างใน R การส่งออกการย้ายป้ายกำกับในการแสดงตัวอย่าง ฯลฯ ?
TMS

1
@ โทมัสที. อ้อเข้าใจแล้ว. ในกรณีนั้นฉัน "โกง" ชนิดของ. ฉันสร้าง pdf หนึ่งชุดพร้อมป้ายกำกับโดยใช้วิธีใดวิธีหนึ่งของคุณด้านบนและอีกวิธีหนึ่งโดยไม่ใช้และใช้แบบที่มีป้ายกำกับเป็นแนวทาง
joran

1
+1 นี่คือคำตอบที่ดี คำอธิบายบางประการเกี่ยวกับสาเหตุที่ปรากฏในmeta-CV : ดูความคิดเห็นที่นั่น
whuber

1
การย้ายป้ายกำกับเล็ก ๆ ด้วยมือดูเหมือนจะสมเหตุสมผล แต่คุณอาจสร้างโดยอัตโนมัติก่อนจากนั้นจึงย้าย วิธีนี้ช่วยให้คุณประหยัดงานได้มากและยังลดโอกาสในการติดฉลากผิดอีกด้วย ...
naught101

42

ggrepelดูมีแนวโน้มเมื่อนำไปใช้กับggplot2scatterplots

# data
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
0.9717, 0.9357)
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
"SaxRub", "TurMer", "TurPil", "TurPhi")


df <- data.frame(x = x, y = y, z = ShortSci)
library(ggplot2)
library(ggrepel)

ggplot(data = df, aes(x = x, y = y)) + theme_bw() + 

    geom_text_repel(aes(label = z), 
       box.padding = unit(0.45, "lines")) +

    geom_point(colour = "green", size = 3)

ใส่คำอธิบายภาพที่นี่


10

คุณได้ลองใช้แพ็คเกจป้ายกำกับโดยตรงหรือไม่?

และ BTW อาร์กิวเมนต์ pos และ offset สามารถใช้เวกเตอร์เพื่อให้คุณได้รับในตำแหน่งที่เหมาะสมเมื่อมีจำนวนจุดที่เหมาะสมในการพล็อตเพียงไม่กี่รัน


แพ็คเกจ directlabels สามารถใช้กับplot()พล็อตปกติได้หรือไม่? ฉันพยายามไม่สำเร็จ ... ขอบคุณ! PS: @SpacedMan & Ben ฉันทำความสะอาดความคิดเห็นของฉันเกี่ยวกับการอัปเดต R เนื่องจากไม่น่าสนใจมากนักคุณสามารถทำเช่นเดียวกันได้
TMS

6

ฉันพบทางออกแล้ว! มันไม่ใช่สิ่งที่ดีที่สุดและเป็นเรื่องที่น่าเสียดาย แต่เป็นสิ่งที่ดีที่สุดสำหรับฉันในตอนนี้ มันเป็นครึ่ง algoritmic ครึ่งคู่มือดังนั้นจึงประหยัดเวลาเมื่อเทียบกับโซลูชันแบบแมนนวลที่วาดโดย joran

ฉันมองข้ามส่วนที่สำคัญมากในการ?identifyช่วยเหลือ!

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

ดังนั้นหากคุณใช้identify()วิธีแก้ปัญหาตามที่ฉันเขียนไว้ในคำถามของฉันคุณสามารถส่งผลต่อตำแหน่งของป้ายกำกับได้โดยไม่คลิกที่จุดนั้นโดยตรง แต่คลิกถัดจากจุดนั้นไปในทิศทางที่ต้องการ !!! ใช้งานได้ดีเยี่ยม!

ข้อเสียคือมีเพียง 4 ตำแหน่ง (บนซ้ายล่างขวา) แต่ฉันจะขอบคุณอีก 4 ตำแหน่ง (บนซ้ายบนขวาล่างซ้ายล่างขวา) ... ดังนั้นฉัน ใช้สิ่งนี้เพื่อป้ายกำกับจุดที่ไม่รบกวนฉันและส่วนที่เหลือฉันติดป้ายกำกับโดยตรงในงานนำเสนอ Powerpoint ของฉันตามที่ joran เสนอ :-)

PS: ฉันยังไม่ได้ลองใช้โซลูชัน directlabels lattice / ggplot ฉันยังคงชอบใช้ไลบรารีพล็อตพื้นฐาน


4

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

http://blog.fellstat.com/?cat=11


3

ผมเคยเขียนฟังก์ชั่นที่เรียกว่า R ภายในแพคเกจaddTextLabels() plotteRสามารถติดตั้งแพ็คเกจลงในไลบรารี R ของคุณได้โดยตรงโดยใช้รหัสต่อไปนี้:

install.packages("devtools")
library("devtools")
install_github("JosephCrispell/basicPlotteR")

สำหรับตัวอย่างที่ให้มาฉันใช้รหัสต่อไปนี้เพื่อสร้างรูปตัวอย่างที่เชื่อมโยงด้านล่าง

# Load the plotteR library
library(plotteR)

# Create vectors storing the X and Y coordinates
x = c(0.8846, 1.1554, 0.9317, 0.9703, 0.9053, 0.9454, 1.0146, 0.9012, 
      0.9055, 1.3307)
y = c(0.9828, 1.0329, 0.931, 1.3794, 0.9273, 0.9605, 1.0259, 0.9542, 
      0.9717, 0.9357)

# Store the labels to be plotted in a vector
ShortSci = c("MotAlb", "PruMod", "EriRub", "LusMeg", "PhoOch", "PhoPho", 
             "SaxRub", "TurMer", "TurPil", "TurPhi")

# Plot the X and Y coordinates without labels
plot(x, y, asp=1)
abline(h = 1, col = "green")
abline(v = 1, col = "green")

# Add non-overlapping text labels
addTextLabels(x, y, ShortSci, cex=0.9, col.background=rgb(0,0,0, 0.75), 
              col.label="white")

ทำงานโดยการเลือกตำแหน่งอื่นโดยอัตโนมัติจากตารางจุดที่ละเอียด จุดที่ใกล้ที่สุดบนเส้นตารางจะเข้าชมก่อนและเลือกหากไม่ทับซ้อนกับจุดหรือป้ายกำกับใด ๆ ลองดูที่แหล่งที่มารหัสถ้าคุณกำลังสนใจ

ตัวอย่างรูป


2

ไม่ใช่คำตอบ แต่ยาวเกินไปสำหรับความคิดเห็น วิธีการที่ง่ายมากที่สามารถใช้ได้กับกรณีง่าย ๆ ซึ่งอยู่ระหว่างขั้นตอนหลังการประมวลผลของ joran และอัลกอริทึมที่ซับซ้อนกว่าที่ได้นำเสนอคือการin-placeแปลงดาต้าเฟรมอย่างง่าย

ฉันอธิบายสิ่งนี้ด้วยggplot2เพราะฉันคุ้นเคยกับไวยากรณ์นั้นมากกว่าพล็อตฐาน R

df <- data.frame(x = x, y = y, z = ShortSci)
library("ggplot2")
ggplot(data = df, aes(x = x, y = y, label = z)) + theme_bw() + 
    geom_point(shape = 1, colour = "green", size = 5) + 
    geom_text(data = within(df, c(y <- y+.01, x <- x-.01)), hjust = 0, vjust = 0)

อย่างที่คุณเห็นในกรณีนี้ผลลัพธ์ไม่เหมาะ แต่อาจดีพอสำหรับวัตถุประสงค์บางอย่าง และมันค่อนข้างง่ายโดยทั่วไปแล้วสิ่งนี้ก็เพียงพอแล้วwithin(df, y <- y+.01)

ใส่คำอธิบายภาพที่นี่


2
แทนที่จะปรับเปลี่ยนการdfใช้withinงานฉันมักจะทำสิ่งนี้โดยปรับความสวยงาม: geom_text(aes(x = x - .01, y = y + .01), hjust = 0, vjust = 0)ดูเหมือนสะอาดกว่า
Gregor Thomas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.