One of the element of ecosystem based approach to fisheries is to provide a detailed map of the actual distribution of fishing, in particular the potential destructive bottom trawl fisheries. In the eye of the public bottom trawling has a very negative “image”. This is part because the perception is that the activity occur indiscriminately and uniformly over the ocean floor. This perception is wrong because fishing is in general aggregated in space and bottom trawling occurs mostly on soft substratum. In addition physical energy from currents, tidal forcing and river flow may often exert higher disturbance energy than that coming from anthropogenic activities.
Enough of the preamble, here we will demonstrate one can map fishing effort in space based on vms-data.
library(tidyverse)
library(lubridate)
library(viridis)
library(ggmap)
source("R/get_arcgis.R")
Note that because of confidentiality, the data is not distributed.
An example of some 10 lines out of 254385 records:
vms %>%
filter(Speed > 0) %>%
slice(1000:1010) %>%
select(Date, Longitude, Latitude, Speed, Heading) %>%
knitr::kable()
Date | Longitude | Latitude | Speed | Heading |
---|---|---|---|---|
18/11/2013 05:21:07 | 5434’22.8 W | 618’21.6 N | 12.04 | 52 |
18/11/2013 05:09:16 | 5435’31.2 W | 617’52.8 N | 11.11 | 55 |
18/11/2013 05:00:00 | 5436’25.2 W | 617’31.2 N | 11.11 | 72 |
18/11/2013 04:00:00 | 5442’21.6 W | 615’28.8 N | 12.96 | 73 |
18/11/2013 03:35:47 | 5444’42 W | 614’34.8 N | 12.04 | 90 |
18/11/2013 03:00:00 | 5448’25.2 W | 613’26.4 N | 13.89 | 95 |
18/11/2013 02:00:00 | 5454’54 W | 610’58.8 N | 12.04 | 72 |
18/11/2013 01:31:22 | 5458’15.6 W | 609’57.6 N | 13.89 | 80 |
18/11/2013 01:00:00 | 5501’55.2 W | 608’42 N | 13.89 | 61 |
18/11/2013 00:44:28 | 5503’46.8 W | 608’2.4 N | 13.89 | 86 |
18/11/2013 00:00:00 | 5508’56.4 W | 606’14.4 N | 12.96 | 81 |
The VMS data are in a relatively clean format. However the geographical coordinates are a mixture of numerical and text values (see above). The numerical values are also in the form of degrees, minutes and seconds (and fraction of a second). What we want is that all the data are expressed in degrees and fraction of degrees. For convenience we generate a function which we can later call within the mutate
-function (explanation of the code is provide within the code chunk):
clean_coordinates <- function(x) {
y <-
data_frame(coord = x) %>%
# use the ' character to split the data
separate(coord, c("ddmm", "rest"), sep = "'", remove = FALSE) %>%
# use the " " (space) to separate the seconds from the rest
separate(rest, c("ss", "q"), sep = " ", convert = TRUE) %>%
# Add a zero in front of degrees if the value is less than 10
mutate(ddmm = ifelse(nchar(ddmm) == 3, paste0("0", ddmm), ddmm)) %>%
# split ddmm into two parts, dd (degrees) and mm (minutes)
separate(ddmm, c("dd", "mm"), 2, convert = TRUE) %>%
# generate decimal degrees
mutate(res = dd + mm/60 + ss/(60 * 60),
# if latitude is west or if longitude is south set decimal
# degrees to a negative value
res = ifelse(q == "W" | q == "S", -res, res))
# return only the res(ulting) vector
return(y$res)
}
We use the function above to change the Longitude and Latitude into decimal degrees:
vms <-
vms %>%
mutate(lon = clean_coordinates(Longitude),
lat = clean_coordinates(Latitude)) %>%
ungroup()
An example of what we now have:
Date | lon | lat | Speed |
---|---|---|---|
18/11/2013 05:21:07 | -54.573 | 6.306 | 12.04 |
18/11/2013 05:09:16 | -54.592 | 6.298 | 11.11 |
18/11/2013 05:00:00 | -54.607 | 6.292 | 11.11 |
18/11/2013 04:00:00 | -54.706 | 6.258 | 12.96 |
18/11/2013 03:35:47 | -54.745 | 6.243 | 12.04 |
18/11/2013 03:00:00 | -54.807 | 6.224 | 13.89 |
18/11/2013 02:00:00 | -54.915 | 6.183 | 12.04 |
18/11/2013 01:31:22 | -54.971 | 6.166 | 13.89 |
18/11/2013 01:00:00 | -55.032 | 6.145 | 13.89 |
18/11/2013 00:44:28 | -55.063 | 6.134 | 13.89 |
18/11/2013 00:00:00 | -55.149 | 6.104 | 12.96 |
The next step is to filter the VMS-data so that we only have pings that truly constitute fishing. We can look at the distribution of
vms %>%
filter(Speed > 0) %>%
ggplot(aes(Speed)) +
geom_histogram(binwidth = 1)
We see that there are two peaks in the distribution, one with a narrow hump with a mode around 6 knots and one with a broad hump with mode around 13 knots. The former is associated with fishing, the latter with cruising.
Now what we are interested in is to plot where fishing does occur. We would thus need at minimum to get rid of all the speed that higher than 9 knots. Speeds less that 3 knots are also likely something else than actual trawling activity. And then the fisheries scientist general knowledge is that no fishing takes place south of 6.05 degrees north. Hence we filter the data accordingly:
vms <-
vms %>%
filter(Speed >= 3,
Speed < 9,
lat > 6.05)
We are next interested to generate some kind of “a grid” where we count the number of VMS-pings within some coordinate resolution. Here we opt to just round the coordinates to two decimal numbers, and then group by those rounded values and count the number of pings:
effort <-
vms %>%
mutate(lon = round(lon, 2),
lat = round(lat, 2)) %>%
group_by(lon, lat) %>%
summarise(no.pings = n())
The data have now been “condensed” (we only have 3569 records) and the data look like this:
glimpse(effort)
## Observations: 3,569
## Variables: 3
## $ lon <dbl> -58.18, -58.17, -56.98, -56.97, -56.71, -56.70, -56.6...
## $ lat <dbl> 6.79, 6.80, 6.27, 6.26, 6.18, 6.17, 6.17, 6.14, 6.17,...
## $ no.pings <int> 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4, 1, 1, 3, 14...
The no.pings stands for the number of pings within each of the grid-corrdinates, the higher the value the more recording of fishing effort has occured at the particular coorinate. The distribution of pings among the grid-coordinates is:
effort %>%
ggplot() +
geom_histogram(aes(no.pings), binwidth = 1)
We see that we have a very scewed distribution, with a lot of grid cells with only 1, 2 or 3 pings and then only a few grid cells where the number of pings (read: effort) is higher than, lets say 10. This is a classical distribution of effort, at least of bottom trawling gear. It is highly aggregated. Now, some may argue that in grid cells where pings are fewer than lets say 4 does not constitute actual fishing because the recorded Speed is instantaneous measurement and hence sensitive to boat movements on the rough seas at any one time. We will filter those data further down the line when we plot the data.
Before we do that we need to get some background images. Here we will use the get_arcgismap
-function that was “sourced” in the first code step in this document (see above). You do not need to know the intricacy of what is done, only that you can specify the limits of the map by specifying the boundaries using decimal degrees:
m <- get_arcgismap(bbox = c(left = -56, bottom = 5.5,
right = -54, top = 6.6),
zoom = 9)
What is now left is just to overlay the effort dataframe over the map.
m +
geom_raster(data = effort %>% filter(no.pings > 3), aes(lon, lat, fill = no.pings)) +
scale_fill_viridis(option = "B", trans = "reverse") +
coord_quickmap()
What we observe is: