如何调整地图大小以填满绘图窗口?

4
我开始使用R的map()函数来绘制地图。我注意到当我调整窗口大小时,图像不会按比例缩放以填充窗口。我该如何让地图图像自动调整为更大或更小,取决于我拉伸窗口的大小?
我正在使用MacOS上的R版本3.0.2。
例如,这是一张地图,我已经将绘图窗口拖得更小和更大。请注意,地图图像的大小不会改变。
library(maps)
map("state")

输入图像描述

输入图像描述

输入图像描述

然而,通常的plot()命令会调整图形大小以适应窗口大小。

plot(1:100, 201:300)

enter image description here

enter image description here

enter image description here


1
在画图之前,您可以指定绘图窗口的大小,例如 dev.new(width=3,height=3)。 - user20650
2个回答

7

需要一些工作,但是通过将maps对象转换为SpatialPolygonsDataFrame,然后使用spplot()函数,您可以获得一个动态调整大小的地图。

值得一提的是,我认为这种方法更好的原因是spplot()基于grid(通过lattice),而grid图形系统比R的基础图形系统在处理绘图对象内部的尺寸方面支持更复杂的方式。

library(maps)
library(maptools)  ## For map2SpatialPolygons()

## Convert data from a "maps" object to a "SpatialPolygonsDataFrame" object
mp <- map("state", fill = TRUE, plot = FALSE)
SP <- map2SpatialPolygons(mp, IDs = mp$names, 
                          proj4string = CRS("+proj=longlat +datum=WGS84"))
DATA <- data.frame(seq_len(length(SP)), row.names = names(SP))
SPDF <- SpatialPolygonsDataFrame(SP, data = DATA)

## Plot it
spplot(SPDF, col.regions = "transparent", colorkey = FALSE,
       par.settings = list(axis.line = list(col = "transparent")))

以下是翻译的结果:

以下是一些截图,展示了它是如何工作的:

enter image description here

enter image description here


谢谢。这对于一个如此简单的问题来说似乎是很多工作。 - stackoverflowuser2010
不用客气。虽然有点工作量,但我已经为您完成了大部分;)。如果您将上面的大部分代码封装在一个函数中,调用它可能就像这样简单:plotMap2SPDF(mp) - Josh O'Brien
1
嗯,看起来需要在map()调用中包含fill=T。否则,会出现错误。Error in map2SpatialPolygons(mp, IDs = mp$names, proj4string = CRS("+proj=longlat +datum=WGS84")) : map and IDs differ in length - stackoverflowuser2010
@stackoverflowuser2010 -- 是的,没错。要理解为什么,请参见?mapValue部分的第二段。 - Josh O'Brien

3

我注意到Josh提供了一个可行的解决方案,但了解 为什么 map() 的行为与你描述的一样可能很有用。基本上,这取决于map()在绘图时基于设备的当前尺寸和纵横比(更具体地说是图形区域)设置绘图区域的大小。

因此,一个解决方案是,在你重新调整设备大小后,只需在此之后重新绘制地图,而无需转换为另一种格式,就像Josh演示的那样。你可以根据par("usr")的宽高比做一些计算,然后将设备设置为与该宽高比兼容的宽度,从而避免一些猜测。

可能比@Josh的解决方案更麻烦,但它确实解释了这种行为。下面给出了更详细的问题描述。


绘制的地图没有"填满"设备(直到指定的边距)的原因是map()中的代码设置了绘图区域的大小,以保持正确的宽高比,基于设备的大小等因素。结果的绘图区域大小适合于在设备中适合,但是保留了正确的宽高比,因此可能不能完全填充它。

关键代码部分如下:

        else {
            par(mar = mar)
            p <- par("fin") - as.vector(matrix(c(0, 1, 1, 
              0, 0, 1, 1, 0), nrow = 2) %*% par("mai"))
            par(pin = p)
            p <- par("pin")
            p <- d * min(p/d)
            par(pin = p)
            d <- d * myborder + ((p/min(p/d) - d)/2)/aspect
            usr <- c(xrange, yrange) + rep(c(-1, 1), 2) * 
              rep(d, c(2, 2))
            par(usr = usr)
        }

在稍早之前,d已被定义为:

        d <- c(diff(xrange), diff(yrange)) * (1 + 2 * myborder) * 
            aspect

(针对你给出的示例)else分支的第二行正在以英寸为单位获取图形区域的当前大小。图形区域是设备上包含边距和绘图区域但不包含任何外部边距的区域大小。实际上,如果没有外部边距处于活动状态,则此代码会抓取设备的大小(并进行调整)。然后,将此结果用于设置绘图区域的大小,从而更新该区域。
意图似乎是获取当前图形区域的大小,并使用它来更新绘制地图的区域。从这个意义上讲,绘图区域的大小通过设备的纵横比来控制;如果您从一个宽但短的窗口开始,则计算出的绘图区域不需要使用所有可用的宽度(如果使用了,则宽高比将错误),因此绘图区域设置为比可用空间小的尺寸。
至于为什么当您调整窗口大小时这不会更新,那是因为在绘制时,绘图区域的大小是以英寸为单位绝对设置的。如果您调整设备大小,则绘图区域的大小保持不变,因此如果您缩小设备足够,地图会被裁剪,或者如果您扩大设备,则使用越来越少的设备空间。

我在想,也许设置asp参数可能是解决map()问题的更好方法,但说实话我还没有仔细考虑过 - 我只是很好奇为什么图形没有重新缩放。 - Gavin Simpson
1
但是基础图形中是否有“asp”参数呢?(我有点记得有,但在“?par”中没有看到。) - Josh O'Brien
@JoshO'Brien 请参考?plot.window,很抱歉,它不是一个参数(在?par的意义上),而是一个可设置的参数,类似于其他三个字母参数,我的思维混淆了它们。 - Gavin Simpson
@JoshO'Brien 不,是我记错了 asp 作为 ?par 参数。如果你没有提到它不在 ?par 中,我仍然会认为它是一个参数。 - Gavin Simpson
1
好的,谢谢。我觉得这很有帮助。如果我理解正确,总结起来就是,maps的作者们可以使用asp来绘制具有相应比例的可调整大小的地图,但是在这些映射区域周围绘制的轴的长度将不保持恒定比例。仅供参考,以下是使用grid指定一个遵循纵横比的视口的方法:grid.show.layout(grid.layout(1,1,respect=TRUE, widths=1.3, heights=1)) - Josh O'Brien
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接