You're right ... it is pretty easy! The "raster" package has some pretty straightforward ways of dealing with creating and manipulating rasters.
library(maptools)
library(raster)
# Load your point shapefile (with IP values in an IP field):
pts <- readShapePoints("pts.shp")
# Create a raster, give it the same extent as the points
# and define rows and columns:
rast <- raster()
extent(rast) <- extent(pts) # this might be unnecessary
ncol(rast) <- 20 # this is one way of assigning cell size / resolution
nrow(rast) <- 20
# And then ... rasterize it! This creates a grid version
# of your points using the cells of rast, values from the IP field:
rast2 <- rasterize(pts, rast, pts$IP, fun=mean)
You can assign grid size and resolution in a number of ways - have a good look at the raster package documentation.
The values of the raster cells from rasterize can be calculated with a function - 'mean' in the example above. Make sure you put this in: otherwise it just uses the value of IP from the last point it comes across!
From a CSV:
pts <- read.csv("IP.csv")
coordinates(pts) <- ~lon+lat
rast <- raster(ncol = 10, nrow = 10)
extent(rast) <- extent(pts)
rasterize(pts, rast, pts$IP, fun = mean)
Here is a tidyverse
method of doing it, starting with your table from before converting to sf
. The approach is to create a long-form table where each row is a start or end point, but include a lineid
so that you can group_by
on it and summarise
to union the right points together, and then st_cast
to LINESTRING
.
library(tidyverse)
library(sf)
#> Linking to GEOS 3.6.1, GDAL 2.2.3, proj.4 4.9.3
table <- structure(list(NOMBRE = c("AL011900", "AL011900", "AL011900", "AL011900", "AL021900", "AL021900", "AL021900", "AL041905", "AL041905", "AL041905", "AL041905"), LAT = c(15, 15.2, 15.3, 15.4, 19, 19.5, 20, 36.3, 37.9, 39.6, 41), LONG = c(-42.1, -43.4, -44.7, -45.6, -59.3, -60, -60.6, -48.6, -47.9, -47.1, -46), INT = c(18.0054, 18.0054, 18.0054, 18.0054, 33.4386, 36.0108, 38.583, 46.2996, 43.7274, 41.1552, 41.1552)), row.names = c(NA, -11L), class = c("tbl_df", "tbl", "data.frame"), spec = structure(list(cols = list(NOMBRE = structure(list(), class = c("collector_character", "collector")), LAT = structure(list(), class = c("collector_double", "collector")), LONG = structure(list(), class = c("collector_double", "collector")), FECHA = structure(list(format = ""), class = c("collector_datetime", "collector")), INT = structure(list(), class = c("collector_double", "collector"))), default = structure(list(), class = c("collector_guess", "collector"))), class = "col_spec"))
table_sf <- table %>%
group_by(NOMBRE) %>%
mutate(
lineid = row_number(), # create a lineid
LONG_end = lead(LONG), # create the end point coords for each start point
LAT_end = lead(LAT)
) %>%
unite(start, LONG, LAT) %>% # collect coords into one column for reshaping
unite(end, LONG_end, LAT_end) %>%
filter(end != "NA_NA") %>% # remove nas (last points in a NOMBRE group don't start lines)
gather(start_end, coords, start, end) %>% # reshape to long
separate(coords, c("LONG", "LAT"), sep = "_") %>% # convert our text coordinates back to individual numeric columns
mutate_at(vars(LONG, LAT), as.numeric) %>%
st_as_sf(coords = c("LONG", "LAT")) %>% # create points
group_by(NOMBRE, INT, lineid) %>%
summarise() %>% # union points into lines using our created lineid
st_cast("LINESTRING")
plot(table_sf[, 1:2])
You can see in the plot that each line between two points has its own INT
as requested.
Best Answer
You need to
summarise
after yourgroup_by
statement then your approach works perfectly fine. Directly from POINTS --> POLYGON, and keeping the crs (if there is one).If you want the outer polygon you can add
st_convex_hull()