संयुक्त ggplots के लिए एक आम किंवदंती जोड़ें


138

मेरे पास दो ggplots हैं जिन्हें मैंने क्षैतिज रूप से संरेखित किया है grid.arrange। मैंने बहुत सारे फ़ोरम पोस्टों के माध्यम से देखा है, लेकिन मैं जो कुछ भी कोशिश करता हूं वह कमांड्स लगते हैं जो अब अपडेट किए गए हैं और कुछ और नाम दिए गए हैं।

मेरा डेटा इस तरह दिखता है;

# Data plot 1                                   
        axis1     axis2   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273

# Data plot 2   
        axis1     axis2
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988

#And I run this:
library(ggplot2)
library(gridExtra)


groups=c('group1','group2','group3','group4','group1','group2','group3','group4')

x1=data1[,1]
y1=data1[,2]

x2=data2[,1]
y2=data2[,2]

p1=ggplot(data1, aes(x=x1, y=y1,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

p2=ggplot(data2, aes(x=x2, y=y2,colour=groups)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

#Combine plots
p3=grid.arrange(
p1 + theme(legend.position="none"), p2+ theme(legend.position="none"), nrow=1, widths = unit(c(10.,10), "cm"), heights = unit(rep(8, 1), "cm")))

मैं इनमें से किसी भी भूखंड से किंवदंती कैसे निकालूंगा और इसे संयुक्त भूखंड के नीचे / केंद्र में जोड़ दूंगा?


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

@StephenHenderson यह एक जवाब है। Gfx संपादक के साथ प्रक्रिया या पोस्ट-प्रक्रिया।
ब्रैंडन बर्टेल्सन

जवाबों:


107

अद्यतन 2015-फरवरी

देखें नीचे स्टीवन के जवाब


df1 <- read.table(text="group   x     y   
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.417117 -0.002592
group1 -0.212201  0.358867
group2 -0.279756 -0.126194
group3  0.186860 -0.203273
group4  0.186860 -0.203273",header=TRUE)

df2 <- read.table(text="group   x     y   
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988
group1  0.211826 -0.306214
group2 -0.072626  0.104988
group3 -0.072626  0.104988
group4 -0.072626  0.104988",header=TRUE)


library(ggplot2)
library(gridExtra)

p1 <- ggplot(df1, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8) + theme(legend.position="bottom")

p2 <- ggplot(df2, aes(x=x, y=y,colour=group)) + geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8)

#extract legend
#https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend<-function(a.gplot){
  tmp <- ggplot_gtable(ggplot_build(a.gplot))
  leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
  legend <- tmp$grobs[[leg]]
  return(legend)}

mylegend<-g_legend(p1)

p3 <- grid.arrange(arrangeGrob(p1 + theme(legend.position="none"),
                         p2 + theme(legend.position="none"),
                         nrow=1),
             mylegend, nrow=2,heights=c(10, 1))

यहाँ परिणामी साजिश है: आम किंवदंती के साथ 2 भूखंड


2
दोनों उत्तर एक ही विकी पृष्ठ की ओर इशारा करते हैं जिसे ggplot2 के नए संस्करणों के रूप में अपडेट किया जा सकता है।
बैप्टिस्ट

छह साल से अधिक समय बाद इस जवाब ने मेरी समस्या हल कर दी। धन्यवाद!
SPK.z

यह कुछ / अधिकांश लोगों के लिए सीधा हो सकता है, लेकिन मुझे यह तुरंत नहीं मिला इसलिए मैंने सोचा कि मैं टिप्पणी करूंगा। यदि आप भूखंड के शीर्ष पर (नीचे के बजाय) आम किंवदंती चाहते हैं, तो आपको केवल तर्क करने के लिए स्विच करना होगा। उपरोक्त उदाहरण में, माइलेजेंड पहले जाता है arrangeGrob()। आपको हाइट्स को उल्टा करने की भी आवश्यकता है (अर्थातheights=c(1,10)
ljh2001

113

तुम भी उपयोग कर सकते हैं ggarrange से ggpubr पैकेज और सेट "common.legend सही =":

library(ggpubr)

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data = dsamp, colour = clarity)
p2 <- qplot(cut, price, data = dsamp, colour = clarity)
p3 <- qplot(color, price, data = dsamp, colour = clarity)
p4 <- qplot(depth, price, data = dsamp, colour = clarity) 

ggarrange(p1, p2, p3, p4, ncol=2, nrow=2, common.legend = TRUE, legend="bottom")

यहां छवि विवरण दर्ज करें


1
क्या यह संभव है कि यह रेंडरप्लॉट () के साथ एक चमकदार एप्लिकेशन (या फ्लेक्सडैशबोर्ड) के अंदर काम नहीं करता है? यह सामान्य प्लॉट के साथ एक सामान्य आर स्क्रिप्ट में पूरी तरह से ठीक काम करता है। लेकिन जब मैं अपने flexdashboard में renderPlot () के साथ किए गए भूखंडों के साथ सटीक काम करता हूं, तो कुछ भी प्रकट नहीं होता है।
टिंगोल्फिन

1
इसके लिए धन्यवाद - मुझे लगता है कि यह अब तक का सबसे आसान उपाय था जो मैं देख रहा था
कोमल राठी

यह कमाल का है! धन्यवाद!
Yanes

@ टिंगोल्फिन मुझे कभी-कभी print(ggarrangeobject)अपनी एक ggarrangeवस्तु के चारों ओर लपेटना पड़ता है, जब मुझे इसकी आवश्यकता होती है कि इसे किसी अन्य फ़ंक्शन द्वारा प्लॉट किया जाए, जो आपके समाधान के समान हो सकता है renderPlot()?
ब्रैंडन

common.legend = TRUEमुझे बस इतना ही चाहिए!
आर्यो

62

रोलैंड के जवाब को अपडेट करने की जरूरत है। देखें: https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs

इस विधि को ggplot2 v1.0.0 के लिए अद्यतन किया गया है।

library(ggplot2)
library(gridExtra)
library(grid)


grid_arrange_shared_legend <- function(...) {
    plots <- list(...)
    g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
    legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
    lheight <- sum(legend$height)
    grid.arrange(
        do.call(arrangeGrob, lapply(plots, function(x)
            x + theme(legend.position="none"))),
        legend,
        ncol = 1,
        heights = unit.c(unit(1, "npc") - lheight, lheight))
}

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data=dsamp, colour=clarity)
p2 <- qplot(cut, price, data=dsamp, colour=clarity)
p3 <- qplot(color, price, data=dsamp, colour=clarity)
p4 <- qplot(depth, price, data=dsamp, colour=clarity)
grid_arrange_shared_legend(p1, p2, p3, p4)

की कमी नोट ggplot_gtableऔर ggplot_buildggplotGrobके बजाय प्रयोग किया जाता है। यह उदाहरण उपरोक्त समाधान की तुलना में थोड़ा अधिक जटिल है, लेकिन इसने इसे अभी भी मेरे लिए हल कर दिया है।


10
नमस्ते, मेरे पास 6 भूखंड हैं, और मैं 6 भूखंडों को 2 पंक्ति × 3 कॉल के रूप में व्यवस्थित करना चाहता हूं और शीर्ष पर किंवदंती आकर्षित करना चाहता हूं, इसलिए फ़ंक्शन को कैसे बदलना है grid_arrange_shared_legend? धन्यवाद!
just_rookie

4
@just_rookie क्या आपको एक समाधान मिला कि फ़ंक्शन को कैसे बदलना है ताकि कोई केवल के बजाय विभिन्न ncol और nrow व्यवस्था का उपयोग कर सके ncol = 1?
ग्यूसेप

नमस्ते, मैंने इस समाधान की कोशिश की, यह अच्छा काम करता है, हालांकि इसे प्रिंट करते समय, मुझे केवल 1 के बजाय 2 पीडीएफ पृष्ठ मिले, पहला खाली है जबकि बाद में मेरा प्लॉट शामिल है, मुझे ऐसा व्यवहार क्यों मिला? धन्यवाद,
हन्नीबेल 90

किसी के लिए भी मेरे जैसा ही ईश कैसे मिलता है, यहाँ एक समाधान है: stackoverflow.com/questions/12481267/…
हन्नीबेल 90

1
यहाँ बढ़िया सामान। किसी भी विचार कैसे सभी भूखंडों के लिए एक एकल शीर्षक जोड़ सकते हैं?
पर्टिनैक्स

27

एक नया, आकर्षक समाधान उपयोग करना है patchwork। वाक्यविन्यास बहुत सरल है:

library(ggplot2)
library(patchwork)

p1 <- ggplot(df1, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)
p2 <- ggplot(df2, aes(x = x, y = y, colour = group)) + 
  geom_point(position = position_jitter(w = 0.04, h = 0.02), size = 1.8)

combined <- p1 + p2 & theme(legend.position = "bottom")
combined + plot_layout(guides = "collect")

2019-12-13 को रेप्रेक्स पैकेज (v0.2.1) द्वारा बनाया गया


2
यदि आप आदेशों के क्रम को थोड़ा बदल दें तो आप इसे एक पंक्ति में कर सकते हैं: combined <- p1 + p2 + plot_layout(guides = "collect") & theme(legend.position = "bottom")
mlcyo

17

मेरा सुझाव है कि काउपोट का उपयोग करें। उनके आर विगनेट से :

# load cowplot
library(cowplot)

# down-sampled diamonds data set
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]

# Make three plots.
# We set left and right margins to 0 to remove unnecessary spacing in the
# final plot arrangement.
p1 <- qplot(carat, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt"))
p2 <- qplot(depth, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")
p3 <- qplot(color, price, data=dsamp, colour=clarity) +
   theme(plot.margin = unit(c(6,0,6,0), "pt")) + ylab("")

# arrange the three plots in a single row
prow <- plot_grid( p1 + theme(legend.position="none"),
           p2 + theme(legend.position="none"),
           p3 + theme(legend.position="none"),
           align = 'vh',
           labels = c("A", "B", "C"),
           hjust = -1,
           nrow = 1
           )

# extract the legend from one of the plots
# (clearly the whole thing only makes sense if all plots
# have the same legend, so we can arbitrarily pick one.)
legend_b <- get_legend(p1 + theme(legend.position="bottom"))

# add the legend underneath the row we made earlier. Give it 10% of the height
# of one plot (via rel_heights).
p <- plot_grid( prow, legend_b, ncol = 1, rel_heights = c(1, .2))
p

तल पर किंवदंती के साथ संयुक्त भूखंड


यह केवल एक तरीका था, जिसने एक कथा_ब () का उपयोग करके अपने प्लॉट में एक मैनुअल किंवदंती लगाने के लिए annotate_figure(ggarrange())एक कब्जे को जन्म दिया। बहुत बहुत धन्यवाद, भगवान आपका भला करे!
जीन कार्लोस

12

@Giuseppe, आप प्लॉट्स व्यवस्था के लचीले विनिर्देशन के लिए इस पर विचार कर सकते हैं ( यहाँ से संशोधित ):

library(ggplot2)
library(gridExtra)
library(grid)

grid_arrange_shared_legend <- function(..., nrow = 1, ncol = length(list(...)), position = c("bottom", "right")) {

  plots <- list(...)
  position <- match.arg(position)
  g <- ggplotGrob(plots[[1]] + theme(legend.position = position))$grobs
  legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
  lheight <- sum(legend$height)
  lwidth <- sum(legend$width)
  gl <- lapply(plots, function(x) x + theme(legend.position = "none"))
  gl <- c(gl, nrow = nrow, ncol = ncol)

  combined <- switch(position,
                     "bottom" = arrangeGrob(do.call(arrangeGrob, gl),
                                            legend,
                                            ncol = 1,
                                            heights = unit.c(unit(1, "npc") - lheight, lheight)),
                     "right" = arrangeGrob(do.call(arrangeGrob, gl),
                                           legend,
                                           ncol = 2,
                                           widths = unit.c(unit(1, "npc") - lwidth, lwidth)))
  grid.newpage()
  grid.draw(combined)

}

अतिरिक्त तर्क nrowऔर ncolव्यवस्थित भूखंडों के लेआउट को नियंत्रित करें:

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
p1 <- qplot(carat, price, data = dsamp, colour = clarity)
p2 <- qplot(cut, price, data = dsamp, colour = clarity)
p3 <- qplot(color, price, data = dsamp, colour = clarity)
p4 <- qplot(depth, price, data = dsamp, colour = clarity)
grid_arrange_shared_legend(p1, p2, p3, p4, nrow = 1, ncol = 4)
grid_arrange_shared_legend(p1, p2, p3, p4, nrow = 2, ncol = 2)

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें


अन्य समाधान के लिए भी, मैंने इसे आज़माया, यह अच्छा काम करता है, हालांकि इसे प्रिंट करते समय, मुझे केवल 1 के बजाय 2 pdf पृष्ठ मिले, पहला खाली है जबकि बाद में मेरा प्लॉट शामिल है, मुझे ऐसा व्यवहार क्यों मिला? धन्यवाद,
हन्नीबेल

किसी के लिए भी मेरे जैसा ही इस्से कैसे मिलता है, यहाँ एक समाधान है: stackoverflow.com/questions/12481267/…
हन्नीबेल 90

क्या कोई मुझे इसका समाधान बता सकता है? कैसे लीया नीचे के बजाय शीर्ष पर किंवदंती को रख सकती है? धन्यवाद
HanniBaL90

8

यदि आप दोनों प्लॉट में एक ही वैरिएबल की साजिश रच रहे हैं, तो सबसे आसान तरीका यह होगा कि आप डेटा फ्रेम को एक में मिलाएं, फिर facet_wrap का उपयोग करें।

अपने उदाहरण के लिए:

big_df <- rbind(df1,df2)

big_df <- data.frame(big_df,Df = rep(c("df1","df2"),
times=c(nrow(df1),nrow(df2))))

ggplot(big_df,aes(x=x, y=y,colour=group)) 
+ geom_point(position=position_jitter(w=0.04,h=0.02),size=1.8) 
+ facet_wrap(~Df)

प्लॉट 1

हीरे के डेटा सेट का उपयोग कर एक और उदाहरण। इससे पता चलता है कि आप इसे काम भी कर सकते हैं यदि आपके पास अपने भूखंडों के बीच केवल एक चर आम है।

diamonds_reshaped <- data.frame(price = diamonds$price,
independent.variable = c(diamonds$carat,diamonds$cut,diamonds$color,diamonds$depth),
Clarity = rep(diamonds$clarity,times=4),
Variable.name = rep(c("Carat","Cut","Color","Depth"),each=nrow(diamonds)))

ggplot(diamonds_reshaped,aes(independent.variable,price,colour=Clarity)) + 
geom_point(size=2) + facet_wrap(~Variable.name,scales="free_x") + 
xlab("")

प्लॉट २

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


1

@Guiseppe:

मुझे ग्रोब आदि के बारे में कुछ भी पता नहीं है, लेकिन मैंने एक साथ दो भूखंडों के लिए एक समाधान हैक कर लिया, मनमाने ढंग से संख्या बढ़ाने के लिए संभव होना चाहिए, लेकिन एक सेक्सी फ़ंक्शन में नहीं:

plots <- list(p1, p2)
g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
tmp <- arrangeGrob(p1 + theme(legend.position = "none"), p2 + theme(legend.position = "none"), layout_matrix = matrix(c(1, 2), nrow = 1))
grid.arrange(tmp, legend, ncol = 1, heights = unit.c(unit(1, "npc") - lheight, lheight))

1

यदि किंवदंती दोनों भूखंडों के लिए समान है, तो उपयोग करके एक सरल समाधान है grid.arrange(यह मानते हुए कि आप चाहते हैं कि आपकी किंवदंती दोनों भूखंडों के साथ लंबवत या क्षैतिज रूप से संरेखित हो)। बस दूसरे के लिए किंवदंती को छोड़ते हुए नीचे-सबसे या दाएं-सबसे भूखंड के लिए किंवदंती रखें। सिर्फ एक कथानक में एक किंवदंती जोड़ना, हालांकि, एक भूखंड के आकार को दूसरे के सापेक्ष बदल देता है। इससे बचने के लिए heightsकमांड को मैन्युअल रूप से समायोजित करने और उन्हें समान आकार रखने के लिए उपयोग करें । तुम भी grid.arrangeआम अक्ष खिताब बनाने के लिए उपयोग कर सकते हैं। ध्यान दें कि library(grid)इसके अलावा इसकी आवश्यकता होगी library(gridExtra)। ऊर्ध्वाधर भूखंडों के लिए:

y_title <- expression(paste(italic("E. coli"), " (CFU/100mL)"))

grid.arrange(arrangeGrob(p1, theme(legend.position="none"), ncol=1), arrangeGrob(p2, theme(legend.position="bottom"), ncol=1), heights=c(1,1.2), left=textGrob(y_title, rot=90, gp=gpar(fontsize=20)))

यहाँ एक परियोजना के लिए समान ग्राफ के लिए परिणाम है जिस पर मैं काम कर रहा था: यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.