आर

2015-05-08 6 views
16

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

नोट: मुझे इसे "महान सर्कल" पथ होने की आवश्यकता नहीं है, केवल मर्केटर प्रोजेक्शन में एक्सवाई वैक्टर, क्योंकि मुझे लगता है कि यह "सामान्य" भूखंडों के लिए भी उपयोगी होगा।

enter image description here

और यहाँ देखने से ज़ूम इन, मैन्युअल रूप से दिखाने के लिए मैं तैयार करना चाहते हैं क्या जोड़ा मैजेंटा तीर के साथ:

एक उदाहरण के रूप में, यहाँ डेटा की हद तक दिखा दुनिया के नक्शे है ।

close-up

नीचे कोड और डेटा मैं इन दो बुनियादी भूखंडों उत्पन्न करने के लिए उपयोग कर रहा हूँ है। मुझे तीरहेड उत्पन्न करने का एक तरीका है।

require(ggplot2) 

te = structure(list(lat = c(33.7399, 32.8571, 50.2214, 36.96263, 33.5835, 
33.54557, 47.76147, 48, 59.40289, 35.93411, 32.87962, 38.3241, 
50.03844, 37.44, 50.07774, 50.26668, 36.5944), lng = c(-118.37608, 
-117.25746, -5.3865, -122.00809, -117.86159, -117.79805, -124.45055, 
-126, -146.35157, -122.931472, -117.25285, -123.07331, -5.26339, 
25.4, -5.709894, -3.86828, -121.96201)), .Names = c("lat", "lng" 
), class = "data.frame", row.names = c(NA, -17L)) 

all_states = map_data("world") 

# world version: 
wp = ggplot() + 
     geom_polygon(data = all_states, aes(x = long, y = lat, group = group), colour = "gray", 
        fill = "gray") + 
     coord_cartesian(ylim = c(0, 80), xlim = c(-155, 45)) + 
     geom_point(data = te, aes(x = lng, y = lat), color = "blue", size = 5,alpha = 0.6) 

print(wp) 

#states plot 
sp = ggplot() + 
     geom_polygon(data = all_states, aes(x = long, y = lat, group = group), colour = "gray", fill = "gray") + 
     coord_cartesian(ylim = c(30, 52), xlim = c(-128, -114)) + 
     geom_point(data = te, aes(x = lng, y = lat), color = "blue", size = 5, alpha = 0.6) 

print(sp) 
+0

आप 'geom_segment' परत जोड़ सकते हैं, वे वैकल्पिक तीर सिर प्रदान करते हैं और पर्याप्त छोटी दूरी के साथ यह केवल एकमात्र चीज दिखाई देती है। – baptiste

+0

[इस ब्लॉग पोस्ट] को देखें (http://editerna.free.fr/wp/?p=76), यह आपको कुछ विचार दे सकता है। – shekeine

+0

टिप्पणियों के लिए धन्यवाद। यह उस तीर को उत्पन्न नहीं कर रहा है जिसके बारे में मुझे चिंता है, लेकिन यह पता लगाना कि उन्हें सही स्थान और अभिविन्यास में कैसे प्लॉट करना है। सबसे बुरी स्थिति परिदृश्य मुझे एक ऐसा फ़ंक्शन बनाना होगा जो बाउंडिंग बॉक्स के बाहर के बिंदुओं की जांच करता है, फिर उनके लिए वैक्टर की गणना करता है, x.y के लिए हल करता है, जहां वह रेखा बॉक्स के किनारे को छेड़छाड़ करती है, और फिर उन बिंदुओं पर घुमावदार त्रिकोणों को साजिश करती है। लेकिन मैं उम्मीद कर रहा था कि एक पुस्तकालय या सुविधा थी जो पहले से ही ऐसा कर सकती है ..! – beroe

उत्तर

6

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

इस समारोह की गणना करता है लाइन बॉक्स चौराहों:

boxint <- function(xlim, ylim, xp, yp){ 
    ## build box as SpatialPolygons 
    box = cbind(xlim[c(1,2,2,1,1)], 
     ylim[c(1,1,2,2,1)]) 
    box <- sp::SpatialPolygons(list(sp::Polygons(list(sp::Polygon(box)),ID=1))) 

    ## get centre of box 
    x0=mean(xlim) 
    y0=mean(ylim) 

    ## construct line segments to points 
    sl = sp::SpatialLines(
     lapply(1:length(xp), 
       function(i){ 
        sp::Lines(list(sp::Line(cbind(c(x0,xp[i]),c(y0,yp[i])))),ID=i) 
       } 
       ) 
     ) 
    ## intersect lines segments with boxes to make points 
    pts = rgeos::gIntersection(sl, as(box, "SpatialLines")) 
    as.data.frame(sp::coordinates(pts), row.names=1:length(xp)) 
} 

और यह तीर के साथ geom रिटर्न:

wherelse <- function(xlim, ylim, points){ 
    ## get points outside bounding box 
    outsides = points[!(
     points$lng>=xlim[1] & 
      points$lng <= xlim[2] & 
       points$lat >= ylim[1] & 
        points$lat <= ylim[2]),] 
    npts = nrow(outsides) 
    ## get centre point of box 
    x = rep(mean(xlim),npts) 
    y = rep(mean(ylim),npts) 

    ## compute box-point intersections 
    pts = boxint(xlim, ylim, outsides$lng, outsides$lat) 
    pts$x0=x 
    pts$y0=y 
    ## create arrow segments as invisible lines with visible arrowheads 
    ggplot2::geom_segment(data=pts, aes(x=x0,y=y0,xend=x,yend=y), 
     lwd=0, arrow=grid::arrow(length=unit(0.5,"cm"), 
     type="closed"),col="magenta") 
} 

तो अपने उदाहरण, मूल कथानक है:

sp = ggplot() + 
    geom_polygon(
    data=all_states, 
    aes(x=long, y=lat, group = group),colour="gray",fill="gray") + 
    coord_cartesian(ylim=c(30, 52), xlim=c(-128,-114)) + 
    geom_point(data=te,aes(x=lng,y=lat),color="blue",size=5,alpha=0.6) 

और उसके बाद तीर जोड़ें:

sp + wherelse(c(-128,-114), c(30,52), te) 

enter image description here

सुनिश्चित नहीं हैं कि वहाँ तीर आकर्षित करने के लिए वास्तव में की तरह आप उन्हें हालांकि चाहते हैं एक विकल्प है कि अगर!

6

मेरा प्रयास यहां है। यह मुझे सबसे नज़दीक मिला है। मैंने आपके यूएस मानचित्र के केंद्र बिंदु और डेटा बिंदुओं के बीच सबसे छोटी दूरी की गणना के लिए gcIntermediate() का उपयोग किया जो कि बॉक्स के बाहर रहने वाले डेटा बिंदुओं के बीच था। इसलिए, तीर की स्थिति कुछ ऐसी चीज नहीं हो सकती है जो आप चाहते हैं। मेरी आशा है कि कोई और इस प्रयास के आधार पर एक बेहतर समाधान प्रदान करेगा।

मैंने पहली बार यूएस ज़ूम किए गए मानचित्र में केंद्र बिंदु के साथ अपना डीएफ (यानी, ते) व्यवस्थित किया था। मैंने फिर डेटा पॉइंट्स चुना जो यूएस मानचित्र के बॉक्स में नहीं हैं। फिर, यूएस मानचित्र के केंद्र बिंदु को इंगित करने के लिए दो कॉलम जोड़ें। दो कॉलम का नाम बदलें और gcIntermediate के साथ सबसे छोटी दूरी की गणना करें।

library(dplyr) 
library(ggplot2) 
library(geosphere) 

filter(te, !between(lng, -128, -114) | !between(lat, 30, 52)) %>% 
mutate(start_long = (-128 - 114)/2, 
     start_lat = (30 + 52)/2) %>% 
rename(end_lat = lat, end_long = lng) %>% 
do(fortify(as(gcIntermediate(.[,c("start_long", "start_lat")], 
          .[,c("end_long", "end_lat")], 
          100, 
          breakAtDateLine = FALSE, 
          addStartEnd = TRUE, 
          sp = TRUE), "SpatialLinesDataFrame"))) -> foo 

foo में संबंधित रेखा खींचने के लिए 100 डेटा पॉइंट शामिल हैं। मैंने डेटा पॉइंट्स चुना जो बबॉक्स सीमा के करीब रहते हैं। मैं विशेष रूप से प्रत्येक पंक्ति के लिए दो डेटा पॉइंट ढूंढ रहा था ताकि मैं बाद में geom_segment() का उपयोग कर सकूं। मैं मानता हूं कि मैंने फिल्टर स्थिति के साथ थोड़ा सा खेला। अंत में, मैंने इस मामले में लेट का उपयोग कर डेटा को सबसेट नहीं किया।

filter(foo, between(long, -128, -126.5) | between(long, -115.5, -114)) %>% 
group_by(group) %>% 
slice(c(1,n())) -> mydf 

अगले चरण में, मैं पर this link

mutate(mydf, end_long = lag(long), end_lat = lag(lat)) %>% 
slice(n()) -> mydf2 

आधारित डेटा फ्रेम पुन: व्यवस्थित अंत में मैं तीर के साथ नक्शा आकर्षित किया। मुझे उम्मीद है कि यह आपके लिए कुछ प्रकार का आधार प्रदान करेगा। मुझे उम्मीद है कि अन्य एसओ उपयोगकर्ता बेहतर समाधान प्रदान करेंगे।

ggplot() + 
geom_polygon(data = all_states, aes(x = long, y = lat, group = group), 
      colour = "gray", fill = "gray") + 
coord_cartesian(ylim = c(30, 52), xlim = c(-128,-114)) + 
geom_point(data = te, aes(x = lng,y = lat), color = "blue", size = 5,alpha = 0.6) + 
geom_segment(data = mydf2, aes(x = end_long, xend = long, 
           y = end_lat, yend = lat, group = group), 
           arrow = arrow(length = unit(0.2, "cm"), ends = "last")) 

enter image description here

+0

धन्यवाद जैज़ूरो। मुझे आपके समाधान के पहलुओं को पसंद है और केवल यह चाहता है कि उसने सीमा के साथ चौराहे के बिंदु की गणना की, 100 अंकों में से सबसे नज़दीक का उपयोग करने के बजाय। – beroe

+0

@beroe आपकी टिप्पणी के लिए धन्यवाद। मैं उन चीजों के साथ आपकी मदद करना चाहता था जो मुझे पता है। अंत में आपको एक बहुत ही उपयोगी उत्तर मिला। मैं तुम्हारे लिए बहुत खुश हूँ! – jazzurro