我正在尝试加速R 包的函数,该函数使用 ggplot2 绘制高分辨率地图。该函数basemap使用较大的 shapefile(每个 15 Mb)绘制斯瓦尔巴群岛地图。该地图是使用两个不同的 shapefile 图层(土地和冰川)以及一组“定义”(例如主题、轴比例和网格线)创建的。按照现在编写的代码,绘制地图大约需要 30 秒。
我的想法是,如果我可以打破代码片段中的图层并允许用户不绘制冰川,那么该函数的执行速度将提高两倍。另外,如果我可以将 ggplot2 语法指定为文本字符串并仅评估所需的字符串,那么 R 就不会浪费时间创建函数未使用的 ggplot2 对象。
我知道如何使用if else语句来做到这一点,但我想避免多次编写定义。似乎可以分配scale_x_continuous()给一个对象,但是分配scale_x_continuous() + scale_y_continuous()会产生错误:
scale_x_Continous() + scale_y_Continous() 中的错误:二元运算符的非数字参数
如何将 ggplot2 轴定义分配给文本字符串并将它们与数据层粘贴在一起?
我以iris数据集为例,这样大家就不用下载PlotSvalbard目前又大又乱的包了。请注意,我知道如何将颜色映射到变量。这里的要点只是为了将 shapefile 说明为iris数据集的两个子集:
library(ggplot2)
data(iris)
## Datasets to imitate the shapefile layers
ds1 <- subset(iris, Species == "setosa")
ds2 <- subset(iris, Species == "versicolor")
## Example how the basemap function works at the moment:
ggplot() + geom_point(data = ds1, aes(x = Sepal.Length, y = Sepal.Width), color = "red") +
geom_point(data = ds2, aes(x = Sepal.Length, y = Sepal.Width), color = "blue") +
scale_x_continuous("Longitude", breaks = seq(3, 8, by = 0.5)) +
scale_y_continuous("Latitude", breaks = seq(1,5, by = 1)) + theme_bw()
## Now I would like to plot ds2 only if user defines "keep.glaciers = TRUE"
land <- ggplot() + geom_point(data = ds1, aes(x = Sepal.Length,
y = Sepal.Width), color = "red")
glacier <- geom_point(data = ds2, aes(x = Sepal.Length, y = Sepal.Width),
color = "blue")
def <- scale_x_continuous("Longitude", breaks = seq(3, 8, by = 0.5)) +
scale_y_continuous("Latitude", breaks = seq(1,5, by = 1)) + theme_bw() ## Error!
# Error in +scale_x_continuous("Longitude", breaks = seq(3, 8, by = 0.5)) :
# invalid argument to unary operator
## The ultimate goal:
keep.glaciers = TRUE
if(keep.glaciers) {
land + glacier + def # error, see above
} else {
land + def
}
Run Code Online (Sandbox Code Playgroud)
您可以将图层保留在 a 中list并使用+运算符 with ggplot。
例如,该函数将、和图层plot_glaciers保存在列表中。语句控制层的构造。该函数将返回具有所需层的对象。landdefglacierifglacierggplot
plot_glaciers <- function(keep_glaciers = TRUE) {
layers <- vector('list')
layers$land <- geom_point(data = ds1, aes(x = Sepal.Length, y = Sepal.Width), color = "red")
layers$def <- list(scale_x_continuous("Longitude", breaks = seq(3, 8, by = 0.5)),
scale_y_continuous("Latitude", breaks = seq(1,5, by = 1)),
theme_bw())
if (keep_glaciers) {
layers$glacier <- geom_point(data = ds2, aes(x = Sepal.Length, y = Sepal.Width), color = "blue")
}
ggplot() + layers
}
plot_glaciers(TRUE)
plot_glaciers(FALSE)
Run Code Online (Sandbox Code Playgroud)