作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R),致力于利用数据科学迅速积累行业经验优势和科学知识发现,涉猎内容包括但不限于信息计量、机器学习、数据可视化、应用统计建模、知识图谱等,著有《R语言高效数据处理指南》(《R语言数据高效处理指南》(黄天元)

本帖子会简单介绍如何读入并处理栅格数据。首先,我们会用到一个矢量数据,数据来自:https://gadm.org/download_country_v3.html,用到的是澳洲的地图。读取方法如下:

# 获得数据的方法之一
# wget --no-check-certificate https://biogeo.ucdavis.edu/data/gadm3.6/gpkg/gadm36_AUS_gpkg.zip

library(pacman)
p_load(sf,raster,tidyverse)

# 查看有哪些图层
st_layers(
  "data/"
)

# 读取特定图层
Ausoutline <- st_read("data/", 
                      layer='gadm36_AUS_0')



可以对这个数据集进行观察:



# 观察
print(Ausoutline)

# 查看proj4坐标系
st_crs(Ausoutline)$proj4string



然后,让我们读入栅格数据,这是一个全球平均气温数据,来源于:Historical climate data(tavg 5m)。



# 读入栅格数据
jan<-raster( "data/")
# have a look at the raster layer jan
jan
plot(jan)



我们可以改变它的坐标系,然后再次绘图:



# set the proj 4 to a new object
newproj<-"+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
# get the jan raster and give it the new proj4
pr1 <- jan %>%
  projectRaster(., crs=newproj)
plot(pr1)



下面,让我们一次性读入所有栅格数据:



# 一次性读入所有栅格数据
dir("data/",full.names = T) %>% 
  stack() -> worldclimtemp
worldclimtemp



让我们为每一个图层命名,它其实是每个月的平均温度,因此可以用月份命名:



month <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", 
           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

names(worldclimtemp) <- month



如果想取出一月份的数据,有两种方法:



worldclimtemp[[1]]
worldclimtemp$Jan



下面,让我们提取特定城市的数据,这是通过经纬度来提取的:



## 提取特定城市的数据
site <- c("Brisbane", "Melbourne", "Perth", "Sydney", "Broome", "Darwin", "Orange", 
          "Bunbury", "Cairns", "Adelaide", "Gold Coast", "Canberra", "Newcastle", 
          "Wollongong", "Logan City" )
lon <- c(153.03, 144.96, 115.86, 151.21, 122.23, 130.84, 149.10, 115.64, 145.77, 
         138.6, 153.43, 149.13, 151.78, 150.89, 153.12)
lat <- c(-27.47, -37.91, -31.95, -33.87, 17.96, -12.46, -33.28, -33.33, -16.92, 
         -34.93, -28, -35.28, -32.93, -34.42, -27.64)
#Put all of this inforamtion into one list 
samples <- data.frame(site, lon, lat, "site")
samples
# Extract the data from the Rasterstack for all points 
AUcitytemp<- raster::extract(worldclimtemp, samples)



提取的变量是一个矩阵,可以稍微进行转化,把城市名称也加上。



AUcitytemp
Aucitytemp2 <- AUcitytemp %>% 
  as_tibble()%>% 
  add_column(Site = site, .before = "Jan")
Aucitytemp2



现在,我们要从世界气温图中取出澳洲的部分,实现如下(利用crop函数):



Austemp <- Ausoutline %>%
  # now crop our temp data to the extent
  crop(worldclimtemp,.)

# plot the output
plot(Austemp)



这个图中还包括了非澳洲的部分,如果只想要澳洲的部分,可以这样操作:



exactAus <- Austemp %>%
  mask(Ausoutline, )
plot(exactAus)



可以尝试对三月份的数据做一个温度分布直方图:



exactAusdf <- exactAus %>%
  ()
# set up the basic histogram
gghist <- ggplot(exactAusdf, 
                 aes(x=Mar)) + 
  geom_histogram(color="black", 
                 fill="white")+
  labs(title="Ggplot2 histogram of Australian March temperatures", 
       x="Temperature", 
       y="Frequency")
# add a vertical line to the hisogram showing mean tempearture
gghist + geom_vline(aes(xintercept=mean(Mar, 
                                        )),
                    color="blue", 
                    linetype="dashed", 
                    size=1)+
  theme(plot.title = element_text(hjust = ))



更多可视化的选择可参考:https://andrewmaclachlan.github.io/CASA0005repo/rasters-descriptive-statistics-and-interpolation.html#histogram-with-ggplot

最后,我们会演示一下空间插值的过程。首先,我们来合并气温的时空分布数据:



samplestemp<-AUcitytemp%>%
  cbind(samples)
samplestemp



而后,让我们把它转换为空间信息数据框,这里需要声明经纬所在列,以及坐标系(这里定义为4326,也就是WGS 84):



samplestemp<-samplestemp%>%
  st_as_sf(.,coords = c("lon", "lat"), 
           crs =4326, 
           agr = "constant")
samplestemp



这里我们可以对澳大利亚轮廓图和城市分布进行可视化:



plot(Ausoutline$geom)
plot(st_geometry(samplestemp), add=TRUE)



插值之前,让我们先统一坐标系,然后转换为SP对象:



samplestemp <- samplestemp %>%
  st_transform(3112)
Ausoutline <- Ausoutline %>%
  st_transform(3112)
samplestempSP <- samplestemp %>%
  as(., 'Spatial')
AusoutlineSP <- Ausoutline %>%
  as(., 'Spatial')



现在意味着,我们要用手头若干个城市的数值,来对整个澳大利亚的气温空间分布进行插值。我们需要创建一个要插值的空间范围:



emptygrd <- (spsample(AusoutlineSP, n=1000, type="regular", cellsize=200000))

names(emptygrd) <- c("X", "Y")

coordinates(emptygrd) <- c("X", "Y")

gridded(emptygrd) <- TRUE  # Create SpatialPixel object
fullgrid(emptygrd) <- TRUE  # Create SpatialGrid object

# Add the projection to the grid
proj4string(emptygrd) <- proj4string(samplestempSP)



然后进行插值:



p_load(gstat)
# Interpolate the grid cells using a power value of 2 
interpolate <- gstat::idw(Jan ~ 1, samplestempSP, newdata=emptygrd, idp=)



这里用的IDW算法来插值,只使用1月份的数据。idp参数越大,则随着距离的增大,数值减少越大。如果idp为0,那么随着距离加大,依然不会有任何数值衰减。关于方法细节,可参考:How inverse distance weighted interpolation works。最后,我们看一下插值之后的结果:



# Convert output to raster object 
ras <- raster(interpolate)
# Clip the raster to Australia outline
rasmask <- mask(ras, Ausoutline)
# Plot the raster
plot(rasmask)