2011-07-23 18 views
6

मेरे पास कुछ डेटा है जो 1: 1 रेखा से नीचे है। मैं लाइन के नीचे क्षेत्र में दर्शकों का ध्यान खींचने के लिए लाइन के ऊपर क्षेत्र को हल्के ढंग से छायांकन करके एक साजिश पर प्रदर्शित करना चाहता हूं।ggplot2 - रेखा से ऊपर छाया क्षेत्र

मैं ग्राफ़ उत्पन्न करने के लिए qplot का उपयोग कर रहा हूं। जल्दी, मेरे पास है;

qplot(x,y)+geom_abline(slope=1)

लेकिन मुझे के जीवन के लिए, को समझ नहीं सकता कि कितनी आसानी से एक अलग वस्तु की साजिश रचने के बिना छाया ऊपर क्षेत्र के लिए। क्या इसके लिए कोई आसान फिक्स है?


संपादित

ठीक है, Joran, यहां एक उदाहरण डेटा सेट है:

df=data.frame(x=runif(6,-2,2),y=runif(6,-2,2), 
    var1=rep(c("A","B"),3),var2=rep(c("C","D"),3)) 
df_poly=data.frame(x=c(-Inf, Inf, -Inf),y=c(-Inf, Inf, Inf)) 

और यहाँ कोड है कि मैं इसे साजिश का उपयोग कर रहा है (मैं आपकी सलाह ले लिया और ggplot() देख रहे हैं):

ggplot(df,aes(x,y,color=var1))+ 
facet_wrap(~var2)+ 
geom_abline(slope=1,intercept=0,lwd=0.5)+ 
geom_point(size=3)+ 
scale_color_manual(values=c("red","blue"))+ 
geom_polygon(data=df_poly,aes(x,y),fill="blue",alpha=0.2) 

एरो r kicked back है: "ऑब्जेक्ट 'var1' नहीं मिला" कुछ मुझे बताता है कि मैं गलत तरीके से तर्क लागू कर रहा हूं ...

+0

रंग अंक और भरने बहुभुज दो अलग सौंदर्यशास्त्र द्वारा नियंत्रित (रंग और भरने) और चाहिए नहीं कर रहे हैं संघर्ष, तो मुझे संदेह है कि आप वहां कुछ गलत कर रहे हैं। मुझे कुछ और मदद करने में खुशी होगी, लेकिन मैं उस डेटा के विशिष्ट प्रतिलिपि उदाहरण के बिना नहीं कर सकता जिसे आप साजिश करने की कोशिश कर रहे हैं ... – joran

+0

हो गया। मुझे संदेह है कि यह मेरी अपरिचितता से उत्पन्न होता है कि ggplot2 ऐसी चीजों को कैसे संभालता है। आपकी मदद के लिए फिर से धन्यवाद, मैं इसकी बहुत सराहना करता हूं। – jslefche

+0

'रंग = var1' को' geom_point' पर ले जाएं: 'geom_point (aes (color = var1), ...)'। साथ ही, यदि आप प्रत्येक पहलू में अलग-अलग भरे बहुभुज चाहते हैं, तो सावधान रहें कि आपको प्रत्येक पहलू के लिए एक अलग डेटा फ्रेम बनाना होगा और उन्हें 'var2' कारक समेत एक डेटा फ्रेम में जोड़ना होगा, इसलिए' ggplot' जानता है कि कौन सा प्रत्येक पहलू पर लागू होते हैं। – joran

उत्तर

11

यहाँ @ Andrie के जवाब पर बिल्डिंग एक और अधिक (लेकिन पूरी तरह से नहीं) सामान्य समाधान है कि ऊपर या ज्यादातर मामलों में एक दिया रेखा से नीचे छायांकन संभालती है।

मैंने इस विधि का उपयोग नहीं किया है कि @Andrie ने here का संदर्भ दिया है क्योंकि जब आप किनारों के पास बिंदु जोड़ते हैं तो ggplot की साजिश रेंज को स्वचालित रूप से विस्तारित करने की प्रवृत्ति के साथ समस्याएं आईं। इसके बजाए, यह आवश्यकतानुसार Inf और -Inf का उपयोग करके बहुभुज बिंदु मैन्युअल रूप से बनाता है। कुछ नोट:

  • अंक के बाद से ggplot भूखंडों आदेश अंक दिखाई कि में बहुभुज, डेटा फ्रेम में 'सही' के क्रम में होना है। तो बहुभुज के शिखर प्राप्त करने के लिए पर्याप्त नहीं है, उन्हें आदेश दिया जाना चाहिए (या तो घड़ी की दिशा या विपरीत दिशा में)।

  • यह समाधान मानता है कि जिस लाइन को आप साजिश कर रहे हैं वह प्लॉट रेंज का विस्तार करने के लिए ggplot का कारण नहीं बनता है। आप मेरे उदाहरण में देखेंगे कि मैं डेटा में दो बिंदुओं को यादृच्छिक रूप से चुनकर और उनके माध्यम से रेखा खींचकर आकर्षित करने के लिए एक रेखा चुनता हूं। यदि आप अपने शेष बिंदुओं से बहुत दूर एक रेखा खींचने का प्रयास करते हैं, तो ggplot स्वचालित रूप से साजिश श्रेणियों को बदल देगा, और भविष्यवाणी करना मुश्किल हो जाएगा कि वे क्या होंगे।

सबसे पहले, यहाँ समारोह है कि बहुभुज डेटा फ्रेम बनाता है:

buildPoly <- function(xr, yr, slope = 1, intercept = 0, above = TRUE){ 
    #Assumes ggplot default of expand = c(0.05,0) 
    xrTru <- xr + 0.05*diff(xr)*c(-1,1) 
    yrTru <- yr + 0.05*diff(yr)*c(-1,1) 

    #Find where the line crosses the plot edges 
    yCross <- (yrTru - intercept)/slope 
    xCross <- (slope * xrTru) + intercept 

    #Build polygon by cases 
    if (above & (slope >= 0)){ 
     rs <- data.frame(x=-Inf,y=Inf) 
     if (xCross[1] < yrTru[1]){ 
      rs <- rbind(rs,c(-Inf,-Inf),c(yCross[1],-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(-Inf,xCross[1])) 
     } 
     if (xCross[2] < yrTru[2]){ 
      rs <- rbind(rs,c(Inf,xCross[2]),c(Inf,Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[2],Inf)) 
     } 
    } 
    if (!above & (slope >= 0)){ 
     rs <- data.frame(x= Inf,y= -Inf) 
     if (xCross[1] > yrTru[1]){ 
      rs <- rbind(rs,c(-Inf,-Inf),c(-Inf,xCross[1])) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[1],-Inf)) 
     } 
     if (xCross[2] > yrTru[2]){ 
      rs <- rbind(rs,c(yCross[2],Inf),c(Inf,Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(Inf,xCross[2])) 
     } 
    } 
    if (above & (slope < 0)){ 
     rs <- data.frame(x=Inf,y=Inf) 
     if (xCross[1] < yrTru[2]){ 
      rs <- rbind(rs,c(-Inf,Inf),c(-Inf,xCross[1])) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[2],Inf)) 
     } 
     if (xCross[2] < yrTru[1]){ 
      rs <- rbind(rs,c(yCross[1],-Inf),c(Inf,-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(Inf,xCross[2])) 
     } 
    } 
    if (!above & (slope < 0)){ 
     rs <- data.frame(x= -Inf,y= -Inf) 
     if (xCross[1] > yrTru[2]){ 
      rs <- rbind(rs,c(-Inf,Inf),c(yCross[2],Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(-Inf,xCross[1])) 
     } 
     if (xCross[2] > yrTru[1]){ 
      rs <- rbind(rs,c(Inf,xCross[2]),c(Inf,-Inf)) 
     } 
     else{ 
      rs <- rbind(rs,c(yCross[1],-Inf)) 
     } 
    } 

    return(rs) 
} 

यह आपके डेटा के x और y पर्वतमाला (range() के रूप में) की उम्मीद है, ढाल, और अवरोधन लाइन की आप साजिश जा रहे हैं, और क्या आप लाइन के ऊपर या नीचे छाया करना चाहते हैं। यहां दिए गए कोड का उपयोग निम्नलिखित चार उदाहरणों को उत्पन्न करने के लिए किया गया है:

#Generate some data 
dat <- data.frame(x=runif(10),y=runif(10)) 

#Select two of the points to define the line 
pts <- dat[sample(1:nrow(dat),size=2,replace=FALSE),] 

#Slope and intercept of line through those points 
sl <- diff(pts$y)/diff(pts$x) 
int <- pts$y[1] - (sl*pts$x[1]) 

#Build the polygon 
datPoly <- buildPoly(range(dat$x),range(dat$y), 
      slope=sl,intercept=int,above=FALSE) 

#Make the plot 
p <- ggplot(dat,aes(x=x,y=y)) + 
     geom_point() + 
     geom_abline(slope=sl,intercept = int) + 
     geom_polygon(data=datPoly,aes(x=x,y=y),alpha=0.2,fill="blue") 
print(p)  

और यहां परिणामों के कुछ उदाहरण दिए गए हैं। आप किसी भी कीड़े मिल जाए, जाहिर है, मुझे इतना पता है कि मैं इस उत्तर को अपडेट कर सकते हैं ...

shade_above1

shade_above2

shade_below1

shade_below2

संपादित

अपडेट किया गया ओपी के उदाहरण डेटा का उपयोग कर समाधान चित्रण करते हैं:

set.seed(1) 
dat <- data.frame(x=runif(6,-2,2),y=runif(6,-2,2), 
     var1=rep(c("A","B"),3),var2=rep(c("C","D"),3)) 
#Create polygon data frame 
df_poly <- buildPoly(range(dat$x),range(dat$y)) 

ggplot(data=dat,aes(x,y)) + 
    facet_wrap(~var2) + 
    geom_abline(slope=1,intercept=0,lwd=0.5)+ 
    geom_point(aes(colour=var1),size=3) + 
    scale_color_manual(values=c("red","blue"))+ 
    geom_polygon(data=df_poly,aes(x,y),fill="blue",alpha=0.2) 

और इस निम्नलिखित उत्पादन का उत्पादन:

enter image description here

+0

+1 अच्छा एक .... – Andrie

+0

मेरी टिप्पणियों के लिए ऊपर देखें! – jslefche

5

जहां तक ​​मुझे पता है कि अल्फा-मिश्रित के साथ बहुभुज बनाने के अलावा कोई अन्य तरीका नहीं है भरें। उदाहरण के लिए:

df <- data.frame(x=1, y=1) 
df_poly <- data.frame(
    x=c(-Inf, Inf, -Inf), 
    y=c(-Inf, Inf, Inf) 
) 

ggplot(df, aes(x, y)) + 
    geom_blank() + 
    geom_abline(slope=1, intercept=0) + 
    geom_polygon(data=df_poly, aes(x, y), fill="blue", alpha=0.2) + 

enter image description here

+0

यदि लाइन कोने से कोने तक नहीं चलती है, तो चीजें अधिक जटिल हो जाती हैं, यदि ऐसा होता है तो यदि लाइन किसी अन्य डेटा सेट के शीर्ष पर प्लॉट की जाती है तो ऐसा होने की संभावना है। मैं थोड़ी देर के लिए tinkered लेकिन एक सामान्य समाधान के साथ नहीं आ सकता था। – joran

+0

सामान्य समाधान लाइनों के साथ होना चाहिए जैसा कि http://stackoverflow.com/questions/6786982/shaded-area-under-two-curves-using-r/6787479#6787479 – Andrie

+0

में आपके समाधान के लिए धन्यवाद! मैंने एंड्री की कोशिश की, लेकिन मैंने यह निर्दिष्ट किया है कि अंक तीसरे चर 'qplot (x, y, color = z)' द्वारा रंगीन होते हैं, जो 'geom_polygon()' कथन के साथ अच्छा नहीं खेलता है। रेखा उत्पत्ति से भी कम है, जिसे मैं समझ नहीं सकता। कोई विचार? – jslefche