Before maptools and rgdal were deprecated, I used this code to import a shapefile, centroids csv and commuting count data, to create a flow map using the code below (I removed the ggplot code for legibility). I am trying to recreate this flow map with recent commuting data to compare changes between both time periods.
I read that read_sf/st_read was used to replace the readOGR function, so I used st_read to import the shapefile.
To join the shapefile to the centroid points, I need to get the polygon ID which is the common field for this join. However, the line soton@data$id = rownames(soton@data) which I'm using to get the polygon IDs that are stored as row names is throwing this error:
Error in soton@data : no applicable method for
@applied to an object of class "sf"
This code worked fine with maptools and rgdal, and I am using the exact same shapefile from before. I'll really appreciate help on tweaking my code to work with the new packages. Thank you.
library(tidyverse)
library(plyr)
library(ggplot2)
library(maptools) -- replaced with library(sf)
library(rgdal) -- removed this and loaded sp package
setwd("your working directory")
soton=st_read(dsn="SouthamptonMSOA",layer="SouthamptonOA")
ODmat=read.csv("ODSouthampton.csv")
centroids=read.csv("CentroidSouthampton.csv")
popdat=read.csv("SouthamptonWZ.csv")
ODmat$frx=0
ODmat$fry=0
ODmat$tox=0
ODmat$toy=0
for (i in 1:dim(ODmat)[1]){
ODmat$frx[i]=centroids$East[which(centroids$Code==ODmat$Origin[i])]
ODmat$fry[i]=centroids$North[which(centroids$Code==ODmat$Origin[i])]
ODmat$tox[i]=centroids$East[which(centroids$Code==ODmat$Destination[i])]
ODmat$toy[i]=centroids$North[which(centroids$Code==ODmat$Destination[i])]}
soton@data$id = rownames(soton@data)
soton.points = fortify(soton, region="id")
soton.df = join(soton.points, soton@data, by="id")
ODmatsub=subset(ODmat,Commuters>50)
figplot = ggplot()+
# ...
UPDATE: In the comments, it was suggested that I convert the centroids data to an sf object before joining to the shapefile. I have done this but now stuck on how to join the shapefile to the centroids data, bearing in mind that I also have to join the origin-destination data (ODSouthampton) to the centroids to create the flow lines.
Here's a sample of the centroids data(csv):
| Code | Name | East | North |
|---|---|---|---|
| E02003549 | Southampton 001 | 442184.28 | 116144.73 |
| E02003550 | Southampton 002 | 439810.63 | 116092.19 |
| E02003551 | Southampton 003 | 443938.17 | 115842.76 |
| E02003552 | Southampton 004 | 439018.21 | 115633.94 |
| E02003553 | Southampton 005 | 443248.97 | 115497.68 |
Sample of the ODSouthampton data (csv):
| Origin | Destination | Commuters |
|---|---|---|
| E02003549 | E02003549 | 22 |
| E02003549 | E02003550 | 25 |
| E02003549 | E02003551 | 13 |
| E02003549 | E02003552 | 12 |
| E02003549 | E02003553 | 24 |
I also have workplace population data which I will display as points on the map, and it's in a csv format. Will I need to convert all 3 csv files to sf objects? Sample of the population data is below:
| MSOA_Code | WZ_Population | POINT_X | POINT_Y |
|---|---|---|---|
| E02003549 | 2149 | 442184.28 | 116144.73 |
| E02003550 | 3227 | 439810.63 | 116092.19 |
| E02003551 | 1998 | 443938.17 | 115842.76 |
| E02003552 | 1596 | 439018.21 | 115633.94 |
| E02003553 | 1772 | 443248.97 | 115497.68 |

Let me explain all steps:
Data preparation, as we don't have access to your SouthamptonMSOA neither csv files:
You can skip above part because you have data on hand.
Let's read in the layer:
Just to show the content:
Let's read in
csvfile and show it's content:Now, we convert
csv(data.frame) tosfobject:Let's use only 2 polygons from our data set, with
admin_level == 6And finally we join them together:
Or opposite way, joining boundaries to points:
Created on 2024-03-05 with reprex v2.1.0