2016-10-29 8 views
5

मुझे ऐसी स्थिति का सामना करना पड़ा जिसमें मैं एक साजिश बनाना चाहता हूं जिसे तीन समूह चर द्वारा पहचाना गया था। ऐसा करने के लिए, मैं बस facet_grid(f1 ~ f2 + f3) का उपयोग करता हूं, लेकिन यहां मुद्दा यह है कि f2 के लिए लेबल अनावश्यक होंगे, और यह F2 के भीतर f3 के लिए पहलुओं के लिए पहलुओं को फैलाने के लिए बेहतर होगा।ggplot2 स्पैनिंग समूहों में नेस्टेड पहलू

मेगावाट:

library('tibble') 
library('ggplot2') 
df <- tribble(
    ~x, ~y, ~f1, ~f2, ~f3, 
    0.5, 0.5, "a", "a", "a", 
    0.5, 0.5, "b", "a", "a", 
    0.5, 0.5, "a", "b", "a", 
    0.5, 0.5, "b", "b", "a", 
    0.5, 0.5, "a", "a", "b", 
    0.5, 0.5, "b", "a", "b", 
    0.5, 0.5, "a", "b", "b", 
    0.5, 0.5, "b", "b", "b" 
) 


p <- ggplot(df, aes(x = x, y = y)) + 
    geom_point() + 
    facet_grid(f1 ~ f2 + f3) 

MWE of nested facet plot

फिर से, मैं इतना है कि वे इसलिए निरर्थक नहीं हैं f2 के लिए लेबल गठबंधन करने के लिए देख रहा हूँ।

संपादित करें: यह अन्य प्रश्नों से अलग है जिसमें यह पूछता है कि मौजूदा समूह का उपयोग कैसे एक नए को जोड़ने के विपरीत एक पहलू को संशोधित करने के लिए किया जाता है।

उत्तर

9

इसका उत्तर grid और gtable पैकेजों के भीतर है। साजिश में सबकुछ एक विशेष क्रम में रखा गया है और आप पाते हैं कि अगर आप थोड़ा खोदते हैं तो सबकुछ कहां है।

library('gtable') 
library('grid') 
library('magrittr') # for the %>% that I love so well 

# First get the grob 
z <- ggplotGrob(p) 

इस ऑपरेशन का अंतिम लक्ष्य शीर्ष पहलू लेबल ओवरले करने के लिए है, लेकिन चाल है कि इन पहलुओं में से दोनों ग्रिड अंतरिक्ष में एक ही पंक्ति पर मौजूद है। वे एक तालिका के अंदर एक मेज हैं (नाम "पट्टी" के साथ पंक्तियों को देखो, भी zeroGrob को ध्यान में रखना, इन बाद में उपयोगी हो सकता है): आप पहली बार पट्टी करने के लिए ज़ूम तो

z 
## TableGrob (13 x 14) "layout": 34 grobs 
##  z   cells  name         grob 
## 1 0 (1-13, 1-14) background  rect[plot.background..rect.522] 
## 2 1 (7- 7, 4- 4) panel-1-1    gTree[panel-1.gTree.292] 

            ... 

## 20 3 (7- 7,12-12) axis-r-1       zeroGrob[NULL] 
## 21 3 (9- 9,12-12) axis-r-2       zeroGrob[NULL] 
## 22 2 (6- 6, 4- 4) strip-t-1       gtable[strip] 
## 23 2 (6- 6, 6- 6) strip-t-2       gtable[strip] 
## 24 2 (6- 6, 8- 8) strip-t-3       gtable[strip] 
## 25 2 (6- 6,10-10) strip-t-4       gtable[strip] 
## 26 2 (7- 7,11-11) strip-r-1       gtable[strip] 
## 27 2 (9- 9,11-11) strip-r-2       gtable[strip] 

            ... 

## 32 8 (3- 3, 4-10) subtitle zeroGrob[plot.subtitle..zeroGrob.519] 
## 33 9 (2- 2, 4-10)  title  zeroGrob[plot.title..zeroGrob.518] 
## 34 10 (12-12, 4-10) caption zeroGrob[plot.caption..zeroGrob.520] 

, आप आंतरिक संरचना देख सकते हैं:

z$grob[[22]] 
## TableGrob (2 x 1) "strip": 2 grobs 
## z  cells name         grob 
## 1 1 (1-1,1-1) strip absoluteGrob[strip.absoluteGrob.451] 
## 2 2 (2-2,1-1) strip absoluteGrob[strip.absoluteGrob.475] 

प्रत्येक Grob के लिए, हम एक उद्देश्य यह है कि जिसमें यह साजिश रची है आदेश (z), ग्रिड में स्थिति (कोशिकाओं), एक लेबल (सूचीबद्ध करता है नाम), और एक ज्यामिति (ग्रोब)।

चूंकि हम gtables के भीतर gtables बना सकते हैं, हम इसका उपयोग हमारी मूल साजिश पर साजिश करने के लिए करेंगे। सबसे पहले, हमें उस साजिश में स्थितियों को ढूंढना होगा जिन्हें प्रतिस्थापित करने की आवश्यकता है।

# Find the location of the strips in the main plot 
locations <- grep("strip-t", z$layout$name) 

# Filter out the strips (trim = FALSE is important here for positions relative to the main plot) 
strip <- gtable_filter(z, "strip-t", trim = FALSE) 

# Gathering our positions for the main plot 
top <- strip$layout$t[1] 
l <- strip$layout$l[c(1, 3)] 
r <- strip$layout$r[c(2, 4)] 

हमारे पास पदों के बाद, हमें एक प्रतिस्थापन तालिका बनाने की आवश्यकता है। हम इसे सूचियों के मैट्रिक्स के साथ कर सकते हैं (हाँ, यह अजीब है। बस इसके साथ रोल करें)। इस मैट्रिक्स के दो पहलुओं और उनके बीच के अंतर की वजह से हमारे मामले में तीन कॉलम और दो पंक्तियां होने की आवश्यकता है। जब से हम सिर्फ बाद में मैट्रिक्स में डेटा को बदलने के लिए जा रहे हैं, हम zeroGrob के साथ एक बनाने के लिए जा रहे हैं:

mat <- matrix(vector("list", length = 6), nrow = 2) 
mat[] <- list(zeroGrob()) 

# The separator for the facets has zero width 
res <- gtable_matrix("toprow", mat, unit(c(1, 0, 1), "null"), unit(c(1, 1), "null")) 

मुखौटा, दो चरणों में बनाई गई है पहले पहलू समूह और फिर दूसरी को कवर। पहले भाग में, हम मूल साजिश से उपयुक्त ग्रोब को पकड़ने के लिए पहले दर्ज किए गए स्थान का उपयोग कर रहे हैं और इसे पूरे प्रतिस्थापन में हमारे प्रतिस्थापन मैट्रिक्स res के शीर्ष पर जोड़ सकते हैं। फिर हम अपनी साजिश के शीर्ष पर उस मैट्रिक्स को जोड़ते हैं।

# Adding the first layer 
zz <- res %>% 
    gtable_add_grob(z$grobs[[locations[1]]]$grobs[[1]], 1, 1, 1, 3) %>% 
    gtable_add_grob(z, ., t = top, l = l[1], b = top, r = r[1], name = c("add-strip")) 

# Adding the second layer (note the indices) 
pp <- gtable_add_grob(res, z$grobs[[locations[3]]]$grobs[[1]], 1, 1, 1, 3) %>% 
    gtable_add_grob(zz, ., t = top, l = l[2], b = top, r = r[2], name = c("add-strip")) 

# Plotting 
grid.newpage() 
print(grid.draw(pp)) 

Nested facet labels

+1

धन्यवाद समाधान के लिए बहुत ज्यादा। मैं साजिश के अधिकार पर होने पर पहलू लेबल को संशोधित करने के लिए इस समाधान को सामान्यीकृत करने के तरीके के बारे में सोचने के लिए संघर्ष कर रहा हूं।क्या आप दिखा सकते हैं कि कोई भी उस मामले को सुइट करने के लिए आपके समाधान को कैसे संशोधित करेगा जहां लेआउट फ़ंक्शन फ़ंक्शन 'ggplot (cbind (df, df), aes (x = x, y = y) पर आधारित था) + geom_point() + facet_grid (एफ 1 + एफ 2 ~ एफ 3) '? मुझे आगे एक मामले में सामान्यीकरण करने की आवश्यकता है जिसमें 12 पहलू पंक्तियों को 4 और 2 के बजाय 6 बाहरी दाएं लेबल तक कम किया गया है (जैसा कि मैंने प्रदान किया गया पुनर्लेखन कार्य किया है)। अगर यह मदद करता है तो एक स्पष्ट उदाहरण प्रदान करने के लिए खुश। बहुत धन्यवाद! – nickb

संबंधित मुद्दे