2012-07-23 10 views
9

इस प्रश्न को question की खोज करके प्रेरित किया जाता है। स्वीकार किए गए समाधान के साथ समस्या अधिक स्पष्ट हो जाती है जब प्रति पहलू बार की संख्या में अधिक असमानता होती है। कि समाधान का उपयोग इस डेटा पर एक नज़र और उसके एवज में भूखंड लें:ggplot2 + gridExtra: विभिन्न आकार प्लॉट grobs में geom_bar को कैसे सुनिश्चित करें सटीक समान बार चौड़ाई

# create slightly contrived data to better highlight width problems 
data <- data.frame(ID=factor(c(rep(1,9), rep(2,6), rep(3,6), rep(4,3), rep(5,3))), 
        TYPE=factor(rep(1:3,length(ID)/3)), 
        TIME=factor(c(1,1,1,2,2,2,3,3,3,1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,1,1,1)), 
        VAL=runif(27)) 

# implement previously suggested solution 
base.width <- 0.9 
data$w <- base.width 
# facet two has 3 bars compared to facet one's 5 bars 
data$w[data$TIME==2] <- base.width * 3/5 
# facet 3 has 1 bar compared to facet one's 5 bars 
data$w[data$TIME==3] <- base.width * 1/5 
ggplot(data, aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~TIME, ncol=1, scale="free") + 
    geom_bar(position="stack", aes(width = w),stat = "identity") + 
    coord_flip() 

widths all the same but spacing is bad

आप चौड़ाई बिल्कुल सही लग रही है पर ध्यान देंगे, लेकिन पहलू 3 में खाली स्थान के काफी स्पष्ट है। Ggplot2 में इसे ठीक करने का कोई आसान तरीका नहीं है जिसे मैंने अभी तक देखा है (facet_wrap में space विकल्प नहीं है)।

# create each of the three plots, don't worry about legend for now 
p1 <- ggplot(data[data$TIME==1,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 
p2 <- ggplot(data[data$TIME==2,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 
p3 <- ggplot(data[data$TIME==3,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 

# use similar arithmetic to try and get layout correct 
require(gridExtra) 
heights <- c(5, 3, 1)/sum(5, 3, 1) 
print(arrangeGrob(p1 ,p2, p3, ncol=1, 
      heights=heights)) 

widths wrong

आप मैं एक ही गणित पहले से सुझाव पर आधारित पहलू प्रति बार की संख्या का इस्तेमाल किया पर ध्यान देंगे, लेकिन इस में:

अगला चरण इस gridExtra का उपयोग कर हल करने का प्रयास करने के लिए है अगर यह बहुत गलत हो जाता है। ऐसा लगता है क्योंकि अतिरिक्त "निरंतर ऊंचाई" तत्व हैं जिन्हें मुझे गणित में विचार करने की आवश्यकता है।

एक और जटिलता (मुझे विश्वास है) यह है कि अंतिम आउटपुट (और चौड़ाई मैच चाहे या नहीं) यह भी चौड़ाई और ऊंचाई पर निर्भर करेगा जहां मैं अंतिम ग्रोब आउटपुट कर रहा हूं, चाहे वह आर/आरस्टूडियो में हो पर्यावरण, या एक पीएनजी फ़ाइल के लिए।

मैं यह कैसे पूरा कर सकते हैं?

+1

साथ 'ggplot_build' आप सीधे अपने पहले समाधान में प्रत्येक पैनल की ऊंचाई को संशोधित कर सकता है। कोहस्के ने यहां उदाहरण पोस्ट किए हैं – baptiste

+0

@baptiste धन्यवाद, जल्द ही एक नज़र डालें और अपडेट करें –

उत्तर

2

gtable बदलने में मदद नहीं करता है, दुर्भाग्य से, के रूप में बार चौड़ाई रिश्तेदार इकाइयों में है,

g = ggplot_gtable(ggplot_build(p)) 
panels = which(sapply(g$heights, attr, "unit") == "null") 
g$heights[[panels[1]]] <- unit(5, "null") 
g$heights[[panels[2]]] <- unit(3, "null") 
g$heights[[panels[3]]] <- unit(1, "null") 
grid.draw(g) 

enter image description here

+0

तो फिर ग्रिडएक्स्ट्रा के माध्यम से अलग-अलग पहलुओं की व्यवस्था करने के लिए? –

5

कुछ इस तरह काम करने के लिए दिखाई देते हैं, लेकिन यह नहीं है - पूरी तरह से नहीं । इसमें काम करने की उपस्थिति है क्योंकि आईडी कारक के स्तर अनुक्रमिक हैं। कुछ और, और scale = "free" विफल रहता है। लेकिन आगे विकसित करना संभव हो सकता है। विधि facet_grid का उपयोग करती है, और इस प्रकार space = "free" का उपयोग किया जा सकता है। विधि एक दूसरे के शीर्ष पर अलग-अलग रंगीन आयतों को परत पर geom_rect का उपयोग करती है। इसकी गणना करने के लिए संचयी रकम की आवश्यकता होती है ताकि प्रत्येक आयताकार के दाएं किनारे पर रखा जा सके।

data <- data.frame(ID=factor(c(rep(1,9), rep(2,6), rep(3,6), rep(4,3), rep(5,3))), 
        TYPE=factor(rep(1:3,3)), 
        TIME=factor(c(1,1,1,2,2,2,3,3,3,1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,1,1,1)), 
        VAL=runif(27)) 

library(ggplot2) 
library(plyr) 

# Get the cumulative sums 
data = ddply(data, .(ID, TIME), mutate, CUMSUMVAL = cumsum(VAL)) 

ggplot(data, aes(x=VAL, y = as.numeric(ID), fill=TYPE)) + 
    geom_rect(data = subset(data, TYPE == 3), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    geom_rect(data = subset(data, TYPE == 2), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    geom_rect(data = subset(data, TYPE == 1), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    facet_grid(TIME~., space = "free", scale="free") + 
    scale_y_continuous(breaks = c(1:5), expand = c(0, 0.2)) 

enter image description here

संपादित करें: या वास्तव में मोटी लाइनों काम थोड़ा बेहतर (मुझे लगता है कि)

ggplot(data, aes(x=VAL, y = ID, colour=TYPE)) + 
     geom_segment(data = subset(data, TYPE == 3), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     geom_segment(data = subset(data, TYPE == 2), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     geom_segment(data = subset(data, TYPE == 1), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     facet_grid(TIME~., space = "free", scale="free") 

enter image description here

अतिरिक्त संपादित अपने earleir से डेटा ले रहा है पोस्ट करें, और इसे थोड़ा संशोधित करें।
अपडेट किया गयाopts बहिष्कृत है; इसके बजाय theme का उपयोग कर।

df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 
5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L), .Label = c("a", 
"b", "c", "d", "e", "f", "g"), class = "factor"), TYPE = structure(c(1L, 
2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 
1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 
5L, 6L, 1L, 2L, 3L), .Label = c("1", "2", "3", "4", "5", "6", 
"7", "8"), class = "factor"), TIME = structure(c(2L, 2L, 2L, 
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 
1L, 1L, 1L), .Label = c("One", "Five", "Fifteen"), class = "factor"), VAL = c(0.937377670081332, 
0.522220720537007, 0.278690102742985, 0.967633064137772, 0.116124767344445, 
0.0544306698720902, 0.470229141646996, 0.62017166428268, 0.195459847105667, 
0.732876230962574, 0.996336271753535, 0.983087373664603, 0.666449476964772, 
0.291554537601769, 0.167933790013194, 0.860138458199799, 0.172361251665279, 
0.833266809117049, 0.620465772924945, 0.786503327777609, 0.761877260869369, 
0.425386636285111, 0.612077651312575, 0.178726130630821, 0.528709076810628, 
0.492527724476531, 0.472576208412647, 0.0702785139437765, 0.696220921119675, 
0.230852259788662, 0.359884874196723, 0.518227979075164, 0.259466265095398, 
0.149970305617899, 0.00682218233123422, 0.463400925742462, 0.924704828299582, 
0.229068386601284)), .Names = c("ID", "TYPE", "TIME", "VAL"), row.names = c(NA, 
-38L), class = "data.frame") 

library(ggplot2) 
library(plyr) 

data = ddply(df, .(ID, TIME), mutate, CUMSUMVAL = cumsum(VAL)) 

ggplot(data, aes(x=VAL, y = ID, colour=TYPE)) + 
      geom_segment(data = subset(data, TYPE == 6), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 5), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 4), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 3), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 2), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 1), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      facet_grid(TIME~., space = "free", scale="free") + 
      theme(strip.text.y = element_text(angle = 0)) 

enter image description here

+0

चालाक! यह काम करेगा, पहलू लेबल को दाएं तरफ के साथ-साथ मेरे वास्तविक डेटा में भी मेरा आईडी कॉलम वास्तव में एक कारक है और कभी-कभी एक विशेष आईडी, टाइम कॉम्बो में एक प्रकार गुम हो जाएगा। यह देखने के लिए अब यह जांच कर रहा है कि यह मेरे वास्तविक डेटा के साथ कितनी अच्छी तरह से काम करता है। –

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