How to convert SpatialPointDataFrame to normal dataframe in r? - r

I could load shp file in r:
setwd("something")
shp = readOGR(dsn = ".", layer = "shp_name")
Now, I want to convert that to a normal dataframe. What should I do?

I found the answer. It's just works like in general:
shp_df = as.data.frame(shp, xy = T)
You don’t always have to complicate things...

Related

Extract values from raster matching csv and raster filenames

I have a folder with many csv files. Each file has several columns as well as lat and long columns. Another folder have many rasters in tif format. The .csv files are named based on Julian date (e.g. 251.csv), and so the rasters (e.g. 251.tif). I would like to be able to add the raster value to the csv with matching name and save to a new csv in R. What I want to achieve is this:
raster<-raster("c:/temp/TIFF/2001/273.tif")
points<-read.csv("c:/temp/csv/2001/273.csv")
coordinates(points)=~long+lat
rasValue=extract(raster,points)
combinePointValue <- cbind(points,rasValue)
head(combinePointValue)
library(spdplyr)
combinePointValue <- combinePointValue %>%
rename(chloro = 10)
write.table(combinePointValue,file="c:/temp/2001/chloro/273_chloro.csv",append=FALSE,
sep=",",row.names=FALSE, col.names=TRUE)
Considering the many csv and many tif files, I would prefer avoiding having to type this over and over. Anyone able to help?
Many thanks in advance!
Ilaria
It is better to provide a minimal reproducible example since your code can not run without your specific data. However, if I understand well, you can try something like this. Since csv and tif files have the same name, you can sort them and loop through the file index. You can use the original path of csv files to save a new file just by pasting the suffix "_chloro:
library(spdplyr)
csv <- sort(list.files("c:/temp/csv/2001/",full.names = T))
tif <- sort(list.files("c:/temp/TIFF/2001/",full.names = T))
lapply(1:length(csv),function(i){
raster<-raster(tif[i])
points<-read.csv(csv[i])
coordinates(points)=~long+lat
rasValue=extract(raster,points)
combinePointValue <- cbind(points,rasValue)
head(combinePointValue)
combinePointValue <- combinePointValue %>%
rename(chloro = 10)
write.table(combinePointValue,file=paste0(tools::file_path_sans_ext(csv[i]),"_chloro.csv"),append=FALSE,
sep=",",row.names=FALSE, col.names=TRUE)
})
SInce the R spatial "ecosystem" is undergoing dramatic changes over the past few years, and package like sp and raster will be deprecated, you might consider a solution based on the terra package.
It would go something like:
# Not tested!
library(terra)
csv_path = "c:/temp/csv/2001/"
tif_path = "c:/temp/TIFF/2001/"
tif_list = list.files(file.path(tif_path, pattern = "*.tif", full.names = FALSE)
result_list = lapply(1:length(tif_list), function(i) {
tif_file = file.path(tif_path, tif_list[i])
# Do not assume that the list of files are exactly equivalent.
# Instead create CSV file name from tif file
csv_name = gsub("tif", "csv", tif_file)
csv_file = file.path(csv_path, csv_name)
r = rast(tif_file)
csv_df = read.csv(csv_file)
# Assume csv long/lat are the same CRS as the tif files
pts = vect(csv_df, geom=c("long", "lat"), crs=st_crs(tif))
result = extract(r, pts, xy = TRUE)
new_csv = paste0(tools::file_path_sans_ext(csv_file),"_chloro.csv")
write.csv(result, file.path(csv_path, new_csv))
return(result)
})

How to create a subset of a shp file, with all its properties

I am new to programming in R and with .shp files.
I am trying to take a subsample / subset of a .shp file that is so big, you can download this file from here: https://www.ine.es/ss/Satellite?L=es_ES&c=Page&cid=1259952026632&p=1259952026632&pagename=ProductosYServicios%2FPYSLayout (select the year 2021 and then go ahead).
I have tried several things but none of them work, neither is it worth passing it to sf because it would simply add one more column called geometry with the coordinates listed and that is not enough for me to put it later in the leaflet package.
I have tried this here but it doesn't work for me:
myspdf = readOGR(getwd(), layer = "SECC_CE_20210101") #It works
PV2 = myspdf[myspdf#data$NCA == 'País Vasco', ] #Dont work
PV2 = myspdf[,myspdf#data$NCA == 'País Vasco'] #Dont work
What I intend is to create a sample of myspdf (with data, polygons, plotorder, bbox and proj4string) but I don't want it from all the NCA values ​​(myspdf#data$NCA), I only want those in which data$NCA are 'País Vasco'
In short, I would like to have a sample for each value of the different NCA column.
Is that possible? someone can help me on this? thank you very much.
I have tried this too but the same thing as before appears to me, all 18 variables appear and all are empty:
Pais_V = subset(myspdf, NCA == 'País Vasco')
dim(Pais_V)
Here's one approach:
library(rgdal)
dlshape=function(shploc, shpfile) {
temp=tempfile()
download.file(shploc, temp)
unzip(temp)
shp.data <- sapply(".", function(f) {
fp <- file.path(temp, f)
return(readOGR(dsn=".",shpfile))
})
}
setwd("C:/temp")
x = dlshape(shploc="https://www2.census.gov/geo/tiger/GENZ2020/shp/cb_2020_us_aitsn_500k.zip", "cb_2020_us_aitsn_500k")
x<-x$. # extract the shapefile
mycats<-c("00","T2","T3","28")
x2<-subset(x, x$LSAD %in% mycats) # subset using the list `mycats`
mypal=colorFactor("Dark2",domain=x2$LSAD)
library(leaflet)
leaflet(x2) %>% addPolygons(weight=.2, color=mypal(x2$LSAD))
dlshape function courtesy of #yokota
Here's another option. This uses the package sf.
myspdf <- st_read("./_data/España_Seccionado2021/SECC_CE_20210101.shp",
as_tibble = T)
Now you can filter this data any way that you filter a data frame. It will still work as spatial data, as well.
Using tidyverse (well, technically dplyr):
myspdf %>% filter(NCA == "País Vasco")
This takes it from 36,334 observations to 1714 observations.
The base R method you tried to use with readOGR will work, as well.
myspdf[myspdf$NCA == "País Vasco",]

convert streamstats() object into sf() object

I would like to create a sf() object from the streamstats function delineateWatershed() without first needing to save as shapefiles of jsons. I can delineate the polygon, then save as a shape, and finally import back in as a shapefile. This leaves me with a version of the shape file in a nested folder, which will quickly take up space. Once I have my sf() polygons I plan to merge multiple together and save them as a single shapefile. In the end I will have two copies of the polygons. How can I skip the writeShapefile() then st_read step?
setwd('~/R/GIS/data/') #I need to define the working directory for writeShapefile()
ws <- delineateWatershed(xlocation = -123.9637, ylocation = 40.06269, crs = 4326)
##writeShapefile(watershed = ws, layer = "name of shape file", "name of folder in dir", what='boundary')
writeShapefile(watershed = ws, layer = "shed", "data", what = 'boundary')
ws_sf <- st_read("~/R/GIS/data/shed.shp")
After some some guess and check I came up with a solution, but I would love to see a more elegant one without a loop. I found the list of coords for the polygon. Made a data frame from the list, then used st_polygon. Props to #Gilles for the last part
ws1 <- ws$featurecollection[[2]]$feature$features[[1]]$geometry$coordinates[[1]]
length(ws1)
for (i in 1:length(ws1)){
ws2[i,] <- data.frame(ws1[[i]])
}
ws3 <- st_sf(st_sfc(st_polygon(list(as.matrix(ws2)))), crs = 4326)
mapview(ws3)

Write CSV with coordinates using R package sf

I'm wondering if there is an easy way to write a CSV of a point sf object (sf R package) that includes the coordinates.
You can use st_write(input, "output.csv") and it will write a CSV without coordinates. My hack for writing a file with coordinates is:
coords <- st_coordinates(input)
input_dat <- input %>% st_set_geometry(., NULL)
input_dat <- cbind(input_dat, coords)
But it seems there must be a simpler way.
As requested, here is the setup for the code above:
input <- data.frame(ID = 1:10, longitude = rnorm(10), latitude = rnorm(10))
input <- st_as_sf(input, coords = c("longitude", "latitude"))
I was sent to the solution by Jakub Nowosad. He pointed me to this github issue which was solved by Etienne B. Racine.
Apparently GDAL has a flag that allows you to include the coordinates. So:
st_write(input, "output.csv", layer_options = "GEOMETRY=AS_XY")
You want a different treatment for POINT simple feature geometries from all other geometry types for something as basic as as.data.frame; I consider that feature creep. I think
cbind(as.data.frame(input), st_coordinates(input))
is easy enough, for this particular case.
st_write is meant to be your portal to all GDAL drivers and nothing more, it will do nothing with the data first, or manipulate GDAL settings by itself.
There should be an easier way, I agree. The as.data.frame() method for sp objects appends the coordinates and I feel like there should be one for sf objects too. But for now, how about:
input %>%
cbind(., st_coordinates(.)) %>%
st_set_geometry(NULL)

R : How to write an XYZ file from a SpatialPointsDataFrame?

I have a SpatialPointsDataFrame which has one attribute (let's call it z for convenience) as well as lat/long coordinates.
I want to write this out to an XYZ file (i.e. an ASCII file with three columns).
Initially I tried
write.table(spdf, filename, row.names=FALSE)
but this wrote the z value first, followed by the coordinates, on each row. So it was ZXY format rather than XYZ. Not a big deal, perhaps, but annoying for other people who have to use the file.
At present I am using what feels like a really horrible bodge to do this (given below), but my question is: is there a good and straightforward way to write a SPDF out as XYZ, with the columns in the right order? It seems as though it ought to be easy!
Thanks for any advice.
Bodge:
dfOutput <- data.frame(x = coordinates(spdf)[,1], y = coordinates(spdf)[,2])
dfOutput$z <- data.frame(spdf)[,1]
write.table(dfOutput, filename, row.names=FALSE)
Why not just
library(sp)
spdf <- SpatialPointsDataFrame(coords=matrix(rnorm(30), ncol = 2),
data=data.frame(z = rnorm(15)))
write.csv(cbind(coordinates(spdf), spdf#data), file = "example.csv",
row.names = FALSE)
You can write to a .shp file using writeOGR from rgdal package. Alternatively, you could fortify (from ggplot2) your data and write that as a csv file.
Following up on Noah's comment about a method like coordinates but for data values: The raster package has the getValues() method for returning the values of a SpatialPointsDataFrame.
library(raster)
spdf <- raster('raster.sdat')
write.table(
cbind(coordinates(spdf), getValues(spdf)),
file = output_file,
col.names = c("X", "Y", "ZVALUE"),
row.names = FALSE,
quote = FALSE
)

Resources