In the R Raster package, when I load a netCDF file into a raster and attempt to mask or crop the raster with a shapefile, I am getting the error:
"*Error in `colnames<-`(`*tmp*`, value = names(object)) :
attempt to set 'colnames' on an object with less than two dimensions*"
Here is example code
library(ncdf4)
library(raster)
nc <- brick("in.netcdf.nc", varname = "diff", values=TRUE )
crs(nc) <- "+proj=utm +zone=17 +ellps=GRS80 +datum=NAD83 +units=m +no_defs"
everShp <- shapefile("EVERareas")
nc.sub <- mask(nc, everShp)
Plotting shows both nc and everShp are 2D and spatially overlap. Thanks for any suggestions with this error.
if I replace
nc <- brick("in.netcdf.nc", varname = "diff", values=TRUE )
with
nc <- raster("in.netcdf.nc", varname = "diff", values=TRUE )
the mask and crop commands work as expected.
Related
I have multiple NetCDF files that contain fire weather data. The files are rotated and also, other R packages (e.g., stars) and programs (e.g., cdo) do not recognize their crs but I can see the crs as WGS84 when I opened them with the raster package.
I'm looking into rotating the data to the common/regular lonlat structure, update the crs, crop the data to the extent of my study area, and writing out each NetCDF file (containing 365/366 layers) just as they were loaded. Example data here: https://www.filemail.com/t/JtIAB1zC
Here's the code that I'm working with:
all_nc = list.files("C:/file_path/",
pattern = ".nc$", recursive = F, full.names = T)
for(i in seq_along(all_nc)){
r = stack(all_nc[i])
r2 = raster::rotate(brick(r))
projectRaster(r2, crs = crs("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))
r2 <- terra::crop(r2, terra::extent(-141.0069, -123.7893, 60, 69.64794))
writeRaster(r, file.path('D:/path/', names(r)),
force_v4 = T, overwrite=TRUE, format="CDF", compression = 7)
}
Error in if (filename == "") { : the condition has length > 1
I can get individual layers with all the changes that I want by tweaking the code but that's not what I'm hoping to achieve. I don't use loops often. So, I suspect that I'm screwing up the indexing somehow.
You can do that like this
fin <- list.files("C:/file_path/", pattern = ".nc$", full.names=TRUE)
fout <- gsub("C:/file_path/", "D:/path/", fin)
library(terra)
e <- ext(-141.0069, -123.7893, 60, 69.64794)
for(i in seq_along(fin)){
r <- rast(fin[i])
crs(r) <- "+proj=longlat +datum=WGS84"
r <- rotate(r)
r <- crop(r, e)
writeCDF(r, filename=fout[i], compression=7)
}
Instead of
r <- crop(r, e)
writeCDF(r, filename=fout[i], compression=7)
writeCDF is a better netCDF writer than writeRaster, but you could also use
r <- crop(r, e, filename=fout[i], gdal=c(COMPRESS="DEFLATE", ZLEVEL="7"))
## or
r <- crop(r, e)
writeRaster(r, filename=fout[i], gdal=c(COMPRESS="DEFLATE", ZLEVEL="7"))
Note that you are mixing up a lot of "raster" and "terra" code. In the above I only use "terra". Also could you point to or share one of the files. I would like to find out why GDAL does not detect the crs.
R Programming Language (New to this)
I am attempting to loop through a number of tiled rasters that have been output by splitRaster. During the loop I want to carry out some processes on each raster.
But the following code throws an error.
library(ForestTools)
library(raster)
library(sp)
library(rgdal)
library(SpaDES)
rm(list = ls())
tmpdir <- file.path(tempdir(), "splitRaster")
lin <- function(x){x * 0.1 + 0.6}
inCHM <- raster("input raster path and name.tif")
split <- splitRaster(inCHM, 5, 5, c(0.05, 0.05), tmpdir)
files <- list.files(path=tmpdir, pattern="*.grd", full.names=FALSE, recursive=FALSE)
file.names <- dir(tmpdir, pattern ="*.grd")
for(file.names in files ){
name <- file.names
ttops <- vwf(name, winFun = lin, minHeight = 5)
writeOGR(ttops, "output folder", name, driver = "ESRI Shapefile")
}
and this is the error
[1] "Xrastername_tile1.grd"
Error in CRS(x) :
PROJ4 argument-value pairs must begin with +: Xrastername_tile1.grd
More to the problem (24/7/2020),
I have removed the loop for trouble shooting instead just choosing one of the splitRasters outputs that would be used in the loop ie files[[3]]
When I run the following code the error is the same;
library(ForestTools)
library(raster)
library(sp)
library(rgdal)
library(SpaDES)
rm(list = ls())
# set temp directory
tmpdir <- "C:\\R-Test\\Temp_Output"
# get raster
r <- raster("C:\\Lidar\\grid_treeheight_max_1m_nofill.tif")
# define projection
projection(r) <- "+proj=utm +zone=50 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
# split raster brick
y <- splitRaster(r, 8, 8, c(0.05, 0.05), tmpdir)
# Get the complete file locations with full.names = T
files <- list.files(path=tmpdir, pattern="*.grd", full.names=FALSE, recursive=FALSE)
tmpfile <- paste(tmpdir, "\\", files[[3]], sep="")
lin <- function(x){x * 0.06 + 0.6}
ttops <- vwf(tmpfile, winFun = lin, minHeight = 5)
This is the error
Error in CRS(x) :
PROJ4 argument-value pairs must begin with +: D:\R-Test\Temp_Output\Xgrid_treeheight_max_1m_nofill_tile11.grd
When I run the following code using one of the splitRaster outputs (files[[3]]) from the above code it runs error free and I am able to plot ttops.
rm(list = ls())
# set temp directory
tmpdir <- "D:\\R-Test\\Temp_Output"
# get raster
r <- raster("D:\\R-Test\\Temp_Output\\Xgrid_treeheight_max_1m_nofill_tile11.grd")
lin <- function(x){x * 0.06 + 0.6}
ttops <- vwf(r, winFun = lin, minHeight = 5)
Why is the PROJ4 error occurring?
This seems to be the error that is causing the loop to fail?
I think the problem is that you are trying to feed the vwf function with the file name instead of a raster object. I would also recommend using lapply instead of for for the loop. Here is a code that should work
library(raster)
library(ForestTools)
library(rgdal)
# Get the complete file locations with full.names = T
files <- list.files(path=tmpdir, pattern="*.grd", full.names=T, recursive=FALSE)
# Loop over each item of the list, i.e., each raster
lapply(files, function(x){
# Load the image as raster
image <- raster(x)
# Calculate vwf (I added a dummy function for winFun)
ttops <- vwf(image, winFun = function(x){x * 0.06 + 0.5}, minHeight = 5)
# Write the file with the name of each raster
writeOGR(ttops, "output_dir", names(x), driver = "ESRI Shapefile")
})
I'am trying to extract the variable "swh_ku" from multiple NetCDF files together with their corresponding latitude and longitude values into csv files using a polygon shapefile or it's extent. I'm working with Jason-1 global altimetry swath data but I only need the data for the domain represented by the shapefile. I just need help with some lines of code that would complete the working code bellow so I can extract only the data for the region I'm interested in.
I've tried several software applications such as QGIS, ESA SNAP, Broadview Radar Altimetry Toolbox (BRAT) with no success unfortunately because I couldn't find a way automate the extraction process for the hundreds of NetCDF files. So I resorted to code with which I'm fairly new but managed to get it working after reading other posts. I've tried opening the files as raster or brick to use the #extract or #mask functions because they seem more straightforward but I couldn't manage to work them out.
Link to data: https://drive.google.com/drive/folders/1d_XVYFe__-ynxbJNUwlyl74SPJi8GybR?usp=sharing
library(ncdf4)
library(rgdal)
library(raster)
my_read_function <- function(ncname) {
setwd("D:/Jason-1/cycle_030")
bs_shp=readOGR("D:/Black_Sea.shp")
e<-extent(bs_shp)
ncfname = ncname
names(ncin[['var']])
dname = "swh_ku"
ncin = nc_open(ncfname)
print(ncin)
vars<-(names(ncin[['var']]))
vars
lon <- ncvar_get(ncin, "lon")
nlon <- dim(lon)
head(lon)
lat <- ncvar_get(ncin, "lat", verbose = F)
nlat <- dim(lat)
head(lat)
print(c(nlon, nlat))
sm_array <- ncvar_get(ncin,dname)
dlname <- ncatt_get(ncin,dname,"long_name")
dunits <- ncatt_get(ncin,dname,"units")
fillvalue <- ncatt_get(ncin,dname,"_FillValue")
dim(sm_array)
ls()
sm.slice <- sm_array[]
sm.vec <- as.vector(sm.slice)
length(sm.vec)
lonlat <- expand.grid(lon, lat)
sm.df01 <- data.frame(cbind(lonlat, sm.vec))
names(sm.df01) <- c("lon", "lat", paste(dname, sep = "_"))
head(na.omit(sm.df01), 20)
csvfile <- paste0(ncname,".csv")
write.table(na.omit(sm.df01), csvfile, row.names = FALSE, sep = ",")
}
my_files <- list.files("D:/Jason-1/cycle_030/")
lapply(my_files, my_read_function)
Looks like your data is not gridded.
library(ncdf4)
library(raster)
bs <- shapefile("Black_Sea.shp")
# simplify so that the data will look better later
bs <- as(bs, "SpatialPolygons")
f <- list.files("cycle_022", pattern="nc$", full=TRUE)
Loop would start here
ncfname = f[1]
dname = "swh_ku"
ncin = nc_open(ncfname)
lon <- ncvar_get(ncin, "lon")
lat <- ncvar_get(ncin, "lat", verbose = F)
sm_array <- ncvar_get(ncin, dname)
xyz <- na.omit(cbind(lon, lat, sm_array))
p <- SpatialPoints(xyz[,1:2], proj4string=crs(bs))
p <- SpatialPointsDataFrame(p, data.frame(xyz))
x <- intersect(p, bs)
x has the points that intersect with the Black Sea
plot(bs)
points(x)
head(x#data)
I'm looking for a way to re-order a set of Formal Class Spatial Polygons using
I'm using US Census data (Limited to Texas) and want to create 33 polygons out of different county combinations.
library(tmap)
library(maptools)
library(ggplot2)
library(rgeos)
library(sp)
library(mapdata)
library(rgdal)
library(raster)
# Download the map of texas and get the LMAs boundaries
# Download shape
f <- tempfile()
download.file("http://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_050_00_20m.zip", destfile = f)
unzip(f, exdir = ".")
US <- read_shape("gz_2010_us_050_00_20m.shp")
# Select only Texas
Texas <- US[(US$STATE %in% c("48")),]
# Load the LMA append data
LMAs = read.table('LMA append data.csv',header=T, sep=',')
# Append LMA data to Texas shape
Texas$FIPS <- paste0(Texas$STATE, Texas$COUNTY)
Texas <- append_data(Texas, LMAs, key.shp = "FIPS", key.data = "FIPS")
Texas <- Texas[order(Texas$LMA),]
# Create shape object with LMAs polygons
Texas_LMA <- unionSpatialPolygons(Texas, IDs=Texas$LMA)
I've tried converting Texas_LMA into a SpatialPolygonsDataFrame with
# Create shape object with LMAs polygons
Texas_LMA <- unionSpatialPolygons(Texas, IDs=Texas$LMA)
spp <- SpatialPolygonsDataFrame(Texas_LMA,data=matrix(1:33,nrow=33,ncol=1))
But that hasn't worked for me.
Your question is not very clear. But I think this is what you are after:
library(raster)
f <- tempfile() download.file("http://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_050_00_20m.zip", destfile = f)
unzip(f, exdir = ".")
US <- shapefile("gz_2010_us_050_00_20m.shp")
Texas <- US[(US$STATE %in% c("48")),]
LMAs = read.csv('LMA append data.csv')
Texas$FIPS <- paste0(Texas$STATE, Texas$COUNTY)
You did not provide the LMA data, so guessing a bit from here:
Texas <- merge(Texas, LMAs, by="FIPS")
Texas_LMA <- aggregate(Texas, by='LMA')
shapefilename[order(shapefilename$column_name),]
I have a NetCDF file of salinity in Indonesia water with 4 dimension (lon, lat, depth and time). I would like to create a map from my data, but it's appear not in appropriate position that not exactly match with the coastline.
download data here: https://onedrive.live.com/redir?resid=6FFDD661570C7D0A%21177
output map here: https://onedrive.live.com/redir?resid=6FFDD661570C7D0A%21176
# This is my script
library (ncdf)
library (raster)
library (sp)
setwd ('D:/work')
bio <- open.ncdf('data.nc')
print (bio)
sal.dat <- get.var.ncdf(bio,"salinity")
sal0 <- brick(sal.dat[,,1,])
extent(sal0) <- c(105,110,-5,0)
projection(sal0) <- CRS("+proj=longlat +datum=WGS84")
#plot image
image (sal0)
# load coastal lines of Indonesia:
con <- url("http://biogeo.ucdavis.edu/data/gadm2/R/IDN_adm0.RData")
load(file = con)
close(con)
# plot coastal lines:
plot(gadm, add = T)
You can use rasterVis package for that purpose:
# load needed librairies
library(rasterVis)
library(rgeos)
# open the data
salinity <- brick("data.nc", varname = "salinity")
# load coastal lines of Indonesia:
con <- url("http://biogeo.ucdavis.edu/data/gadm2/R/IDN_adm0.RData")
load(file = con)
close(con)
# clip the coastline to the study area
CP <- as(extent(salinity), "SpatialPolygons")
proj4string(CP) <- CRS(proj4string(gadm))
gadm <- gIntersection(gadm, CP, byid=TRUE)
# map
levelplot(subset(salinity, 1), margin = FALSE) +
layer(sp.polygons(gadm, fill='transparent', col='black'))