2015-10-19 21 views
6

के साथ अलग-अलग रेखा लंबाई उत्पन्न करता है मैंने इसे जाली के साथ 'भाई' प्रश्न का पालन करने के रूप में पोस्ट किया है (यानी Lattice's `panel.rug` produces different line length with wide plot) लेकिन विभिन्न ग्राफिकल सिस्टम के कारण यह अलग होने का हकदार है।ggplot2 geom_rug() विस्तृत साजिश

जब मार्जिन शामिल है कि geom_rug()ggthemes से, बीहड़ मार्जिन में लाइनों की लंबाई x- अक्ष से y- अक्ष में लंबे समय तक है साथ ggplot2 में एक विस्तृत भूखंड का निर्माण:

library(ggplot2) 
library(ggthemes) 
png(width=800, height=400) 
ggplot(swiss, aes(Education, Fertility)) + geom_point() + geom_rug() 
dev.off() 

enter image description here

मैं उन रग लाइनों को x- और y-axes में एक प्लॉट के आकार के बावजूद समान लंबाई के रूप में रखना चाहूंगा (नोट: अभी रग लाइनें केवल साजिश चौकोर होने पर समान लंबाई होगी) ।

उत्तर

7

यह हैडली के वर्तमान geom_rug कोड इस प्रकार है, लेकिन इसे जोड़ने के लिए (या घटाना) को संशोधित करता है एक उदाहरण के लिए गलीचा-टिक्स की आंतरिक इकाइयों के लिए पूर्ण राशि। यह वास्तव में grid::unit का एक आवेदन है - किसी भी चीज़ से अधिक कार्यक्षमता, क्योंकि यह इस तथ्य का उपयोग करता है कि इकाइयों को अलग-अलग आधारों के साथ जोड़ा और घटाया जा सकता है। यूनिट (0.5, "सेमी") कहें, आप इसे "rug_len" -argument को अपने चयन के डिफ़ॉल्ट के साथ स्वीकार करने के लिए संशोधित कर सकते हैं। एक png मैं बनाने (, समारोह के environment स्थापित करने के लिए याद करने की आवश्यकता है ताकि एक बंद, + ' `' , can call the next closure, ggplot2 :: geom_rug2 ', सही ढंग से।)

geom_rug2 <- function (mapping = NULL, data = NULL, stat = "identity", position = "identity", sides = "bl", ...) { 
    GeomRug2$new(mapping = mapping, data = data, stat = stat, position = position, sides = sides, ...) 
} 

GeomRug2 <- proto(ggplot2:::Geom, { 
    objname <- "rug2" 

    draw <- function(., data, scales, coordinates, sides, ...) { 
    rugs <- list() 
    data <- coord_transform(coordinates, data, scales) 
    if (!is.null(data$x)) { 
     if(grepl("b", sides)) { 
     rugs$x_b <- segmentsGrob(
      x0 = unit(data$x, "native"), x1 = unit(data$x, "native"), 
      y0 = unit(0, "npc"), y1 = unit(0, "npc")+unit(1, "cm"), 
      gp = gpar(col = alpha(data$colour, data$alpha), lty = data$linetype, lwd = data$size * .pt) 
     ) 
     } 

     if(grepl("t", sides)) { 
     rugs$x_t <- segmentsGrob(
      x0 = unit(data$x, "native"), x1 = unit(data$x, "native"), 
      y0 = unit(1, "npc"), y1 = unit(1, "npc")-unit(1, "cm"), 
      gp = gpar(col = alpha(data$colour, data$alpha), lty = data$linetype, lwd = data$size * .pt) 
     ) 
     } 
    } 

    if (!is.null(data$y)) { 
     if(grepl("l", sides)) { 
     rugs$y_l <- segmentsGrob(
      y0 = unit(data$y, "native"), y1 = unit(data$y, "native"), 
      x0 = unit(0, "npc"), x1 = unit(0, "npc")+unit(1, "cm"), 
      gp = gpar(col = alpha(data$colour, data$alpha), lty = data$linetype, lwd = data$size * .pt) 
     ) 
     } 

     if(grepl("r", sides)) { 
     rugs$y_r <- segmentsGrob(
      y0 = unit(data$y, "native"), y1 = unit(data$y, "native"), 
      x0 = unit(1, "npc"), x1 = unit(1, "npc")-unit(1, "cm"), 
      gp = gpar(col = alpha(data$colour, data$alpha), lty = data$linetype, lwd = data$size * .pt) 
     ) 
     } 
    } 

    gTree(children = do.call("gList", rugs)) 
    } 

    default_stat <- function(.) StatIdentity 
    default_aes <- function(.) aes(colour="black", size=0.5, linetype=1, alpha = NA) 
    guide_geom <- function(.) "path" 
}) 
environment(geom_rug2) <- environment(ggplot) 

p <- qplot(x,y) 
p + geom_rug2(size=.1) 
अपने कोड के साथ

:

enter image description here

मैंने बिना किसी सफलता के hadley's current description of how to extend ggplot2 का पालन करने का भी प्रयास किया।

+1

+1 यह दिखाने के लिए कि पुराने पर आधारित एक नया भूगोल कैसे बनाया जाए। उस फ़ंक्शन के लिए एक प्रतीत होता है कि यहां तक ​​कि सरल संपादन 'स्ट्रिंग' 'स्नैप' के साथ 'get (" draw ", ggplot2 ::: geomRug) 'द्वारा दिए गए फ़ंक्शन में' npc "' की सभी घटनाओं को प्रतिस्थापित करना है। –

+0

"spnc" .... अच्छा एक! मैंने पहले कभी 'स्नैप' के बारे में नहीं सुना था। हालांकि मैं 'यूनिट' पृष्ठ को देख रहा था, मैंने इसे बहुत सावधानी से नहीं देखा। मौजूदा "एनपीसी" इकाइयों को छोड़कर एक rug_scale तर्क में डाल सकता है। पेजिंग @ हैडली। –

+0

हाँ, यह अक्सर नहीं आता है। [यहां एकमात्र अन्य स्थान है] (http://stackoverflow.com/questions/13015110/color-a- डिज़ाइन किया गया-area/13015631#13015631) मैंने कभी इसे SO पर डेमो किया है। –

5

मुझे यकीन है कि वहाँ (मैं एक नहीं पा सके) geom_rug में गलीचा खंड की लंबाई को नियंत्रित करने का कोई तरीका है नहीं कर रहा हूँ। हालांकि, आप geom_segment का उपयोग करके अपना खुद का गलीचा बना सकते हैं और सेगमेंट की लंबाई को हार्ड-कोड कर सकते हैं या प्रोग्रामिक रूप से बराबर लंबाई वाली रग लाइनों का उत्पादन करने के लिए कुछ तर्क जोड़ सकते हैं।

# Aspect ratio 
ar = 0.33 

# Distance from lowest value to start of rug segment 
dist = 2 

# Rug length factor 
rlf = 2.5 

ggplot(swiss, aes(Education, Fertility)) + geom_point() + 
    geom_segment(aes(y=Fertility, yend=Fertility, 
        x=min(swiss$Education) - rlf*ar*dist, xend=min(swiss$Education) - ar*dist)) + 
    geom_segment(aes(y=min(swiss$Fertility) - rlf*dist, yend=min(swiss$Fertility) - dist, 
        x=Education, xend=Education)) + 
    coord_fixed(ratio=ar, 
       xlim=c(min(swiss$Education) - rlf*ar*dist, 1.03*max(swiss$Education)), 
       ylim=c(min(swiss$Fertility) - rlf*dist, 1.03*max(swiss$Fertility)))  

enter image description here

या आप केवल कड़ी मेहनत से कोड करना चाहते हैं तो यह:

ggplot(swiss, aes(Education, Fertility)) + geom_point() + 
    geom_segment(aes(y=Fertility, yend=Fertility, 
        x=min(swiss$Education) - 3, xend=min(swiss$Education) - 1.5)) + 
    geom_segment(aes(y=min(swiss$Fertility) - 6, yend=min(swiss$Fertility) - 3, 
        x=Education, xend=Education)) + 
    coord_cartesian(xlim=c(min(swiss$Education) - 3, 1.03*max(swiss$Education)), 
        ylim=c(min(swiss$Fertility) - 6, 1.03*max(swiss$Fertility))) 
+0

क्या पहलू अनुपात को बदलने के बिना ऐसा करने का कोई तरीका है? –

+0

अद्यतन उत्तर देखें। मैंने हार्ड-कोड के लिए एक तरीका जोड़ा है जो पहलू अनुपात निर्धारित नहीं करता है। हालांकि, ध्यान दें कि आपको मूल्यों को ट्विक करना होगा ताकि वे प्लॉट को सहेजते समय आपके द्वारा चुने गए किसी भी अंतर्निहित पहलू अनुपात के साथ काम कर सकें। – eipi10

+0

कोड को देखकर, मैं कहूंगा कि वर्तमान संस्करण में रग टिक लंबाई को नियंत्रित करने का कोई तरीका नहीं है। –

2

ggplot Grob की संरचना में Delving:

माइनर संपादित करें: ggplot2 के लिए 2.2.1

library(ggplot2) 
p = ggplot(swiss, aes(Education, Fertility)) + geom_point() + geom_rug() 

# Get the ggplot grob 
gp = ggplotGrob(p) 

# Set end points of rug segments 
library(grid) 
gp$grobs[[6]]$children[[4]]$children[[1]]$y1 = unit(0.03, "snpc") 
gp$grobs[[6]]$children[[4]]$children[[2]]$x1 = unit(0.03, "snpc") 

png(width=900, height=300) 
grid.draw(gp) 
dev.off() 

enter image description here

1

एक और अंडर-हुड समाधान अद्यतन करने। सबसे पहले, मुझे ggplot grob मिलता है, और फिर मैं पैकेज से editGrob फ़ंक्शन का उपयोग करता हूं। editGrob के साथ, मैं बस संपादित करने के लिए grob नाम; प्रासंगिक मानकों के लिए सभी तरह से ग्रोब की संरचना का पालन करना आसान है। आम तौर पर, editGrob सभी ggplot grobs नहीं देख सकते हैं, लेकिन उन्हें grid.force() के साथ उजागर किया जा सकता है।

library(ggplot2) 
library(grid) 

p = ggplot(swiss, aes(Education, Fertility)) + geom_point() + geom_rug() 

# Get the ggplot grob 
gp = ggplotGrob(p) 

# Get names of relevant grobs. 
# The grid.force function generates the gtable's at-drawing-time contents. 
names.grobs = grid.ls(grid.force(gp))$name # We're interested in the children of rugs.gTree 
segments = names.grobs[which(grepl("GRID.segments", names.grobs))] 

# Check them out 
str(getGrob(grid.force(gp), gPath(segments[1]))) # Note: y1 = 0.03 npc 
str(getGrob(grid.force(gp), gPath(segments[2]))) # Note: x1 = 0.03 npc 

# Set y1 and x1 to 0.03 snpc 
gp = editGrob(grid.force(gp), gPath(segments[1]), y1 = unit(0.03, "snpc")) 
gp = editGrob(grid.force(gp), gPath(segments[2]), x1 = unit(0.03, "snpc")) 

png(width=900, height=300) 
grid.draw(gp) 
dev.off()