在网格外部绘制点作为箭头指向R中的ggplot2的数据

时间:2015-05-08 19:02:39

标签: r dictionary plot ggplot2 ggmap

我正在使用世界级数据生成地图,然后放大到某些地区。在放大视图中,我想通过将箭头从框的中心指向数据点在外部世界中的位置来显示边界框外还有其他数据点。

注意:我不需要它是一个“大圆”路径,只需要墨卡托投影中的XY矢量,因为我认为这对“普通”图也很有用。

例如,这是显示数据范围的世界地图:

enter image description here

这是放大的视图,手动添加洋红色箭头以显示我想要生成的内容。

close-up

以下是我用来生成这两个基本图的代码和数据。我需要的是一种生成箭头的方法。

- (void)viewDidLoad {
    [super viewDidLoad];

    self.myTableView.delegate=self;
    self.myTableView.dataSource=self;

    UIImageView *myImageView=[[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.myTableView.bounds.size.height, self.view.frame.size.width, 300.0F+self.myTableView.bounds.size.height)];
    [myImageView setClipsToBounds:TRUE];
    [myImageView setImage:[UIImage imageNamed:@"myImage.jpg"]];


    [self.myTableView addSubview:myImageView];

}

2 个答案:

答案 0 :(得分:6)

这是我的尝试。这是我得到的最接近的。我使用gcIntermediate()来计算美国地图中心点与保留在bbox外部的数据点之间的最短距离。因此,箭头位置可能不是你想要的。我希望有人会根据这种尝试提供更好的解决方案。

我首先将你的df(即te)与美国缩放地图中的中心点对齐。然后我选择了不在美国地图的bbox中的数据点。然后,添加两列以指示美国地图的中心点。重命名两列并使用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个数据点来绘制相应的行。我选择了靠近bbox边界的数据点。我特意为每一行寻找两个数据点,以便我以后可以使用geom_segment()。我承认我玩过滤条件了一下。最后,在这种情况下,我没有使用lat子集数据。

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

最后我用箭头画了地图。我希望这能为你提供某种基础。我也希望其他SO用户能提供更好的解决方案。

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

答案 1 :(得分:6)

此解决方案使用sprgeos包处理空间数据,主要关键是相交线和方框多边形以获取箭头的边缘点。然后,如果您绘制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

不确定是否有一个选项可以完全按照你想要的方式绘制箭头!