Chapter 3 Sampling an ecological network

Eva Knop and Vincent Grognuz
session 18/03/2025

Field work

For this exercise session, you will go outside to collect data on species interactions in order to build your own pollination network. You can find instructions on how to collect interaction data in the slides provided. Moreover (weather permitting), we will demonstrate what you should do at the Irchel Park.

An important thing to keep in mind is that you should record the interactions you sample in the file we provide. You can download the file here. This is the file you are expected to use when building your network in R.

Data analysis and report preparation

After having collected your data, you should do the following tasks:

  1. Load the data you collected in the field into R
  2. Convert the data into a network
  3. Visualize your network

We expect you to submit a short report that combines your code, data, and visualisations. To do so, we provide you with a template Rmarkdown file that you can fill in. You can find this file here: /workspace/03-18_sampling_an_ecological_network.

Please keep in mind that the deadline to submit the report for this exercise session is Saturday, April 5th at 1:00 pm. If you have questions, please do not hesitate to contact us.

3.1 Practical demonstration

To walk you through all the steps needed to prepare your report we will work with a mock data set.

Load data

After you recorded your data into the file called species_interactions_protocol.csv, you will need to upload it to the Rstudio Server. To do so, you can click on the Upload button found on the bottom right panel of Rstudio. This will allow you to navigate your file system to find the file you wish to upload and then upload it directly to the server. Once the file is on the server, we can load the relevant packages we will need and read the data into R as follows:

# Load packages
library(igraph)
library(dplyr)
library(bipartite)

# Read data into R
data <- read.csv("~/ecological_networks_2025/downloads/Data/sampling_an_ecological_network/species_interactions_protocol_example.csv")

Note that you will need to change the file path so that it points to the location where your data is stored on the server(!).

Next we can check that the data was imported correctly:

# Take a glimpse at the data
head(data)
##               plant               insect     date  time temperature
## 1 Primula.vulgaris     Bombus.terrestris 22.03.22 14:02          18
## 2 Primula.vulgaris     Bombus.terrestris 22.03.22 14:02          18
## 3 Primula.vulgaris  Episyrphus.balteatus 22.03.22 14:02          18
## 4 Primula.vulgaris       Hymenoptera.sp2 22.03.22 14:15          18
## 5         Salix.sp            Bombus.m1  23.03.22 14:05          18
## 6         Salix.sp            Bombus.m1  23.03.22 14:05          18

3.1.1 Convert data to a bipartite network

Now that you have loaded your data set, you need to convert it into an igraph object, i.e., “something” that is suitable to be visualized and to be analyzed quantitatively as a network. Let’s start by converting our raw data into an edge list:

# convert the raw data into an edge list
my_edge_list <- data |>
  # only select relevant columns
  select(plant, insect) |>
  # group by each unique combination of plant and insect
  group_by(plant, insect) |>
  # summarise the groups by adding a new column which counts the number of 
  # interactions between each unique combination of plant and insect
  summarise(connection_strength = n()) |>
  # ungroup the plants and animals
  ungroup()

Now our data is formatted in such a way that each row summarises the number of interactions between a pair of plant and insect:

# get a glimpse at the data
head(my_edge_list)
## # A tibble: 6 × 3
##   plant                insect                 connection_strength
##   <chr>                <chr>                                <int>
## 1 "Gallanthus.nivalis" "Apis.mellifera"                         1
## 2 "Primula.vulgaris "  "Bombus.terrestris"                      2
## 3 "Primula.vulgaris "  "Episyrphus.balteatus"                   1
## 4 "Primula.vulgaris "  "Hymenoptera.sp1"                        1
## 5 "Primula.vulgaris "  "Hymenoptera.sp2"                        3
## 6 "Salix.sp "          "Bombus.m1 "                             4

Following the procedure we have applied in the session toolkit for network analysis, we can convert our edge list into a network using the igraph package.

# Convert the edge list into network
my_network <- graph_from_data_frame(my_edge_list, directed = FALSE)

# Check network 
my_network
## IGRAPH 2780125 UN-- 11 9 -- 
## + attr: name (v/c), connection_strength (e/n)
## + edges from 2780125 (vertex names):
## [1] Gallanthus.nivalis   --Apis.mellifera      
## [2] Primula.vulgaris     --Bombus.terrestris   
## [3] Primula.vulgaris     --Episyrphus.balteatus
## [4] Primula.vulgaris     --Hymenoptera.sp1     
## [5] Primula.vulgaris     --Hymenoptera.sp2     
## [6] Salix.sp             --Bombus.m1           
## [7] Salix.sp             --Episyrphus.balteatus
## [8] Taraxacum.officinalis--Episyrphus.balteatus
## + ... omitted several edges

Now we need to make our network bipartite. To do so, we can use the bipartite_mapping function to automatically assign plants and insects to separate groups:

# Assign groups to insects and plants
bipartite_mapping_output <- bipartite_mapping(my_network)

# Set these groups to the nodes of the network
V(my_network)$type <- bipartite_mapping_output$type

# Confirm that network is now bipartite
is_bipartite(my_network)
## [1] TRUE

3.1.2 Plot the network

We can plot the network using either the igraph or bipartite package. Remember, however, that each one requires our network to be represented in different formats. igraph requires a network object while bipartite requires an incidence matrix.

Let’s first plot our network using igraph:

# Set the layout for our plot
LO = layout_as_bipartite(my_network)

# Visualize our network
plot(my_network, # define the network we want to plot 
     vertex.label=V(my_network)$Name, # define the node labels
     vertex.size=8, # define node size
     vertex.label.dist=9, # define position of node labels
     layout=LO[,2:1], # tweak layout 
     vertex.label.degree = pi*V(my_network)$type, # tweak position of labels
     vertex.label.cex=0.8, # define label size
     vertex.color = rgb(0.8,0.4,0.3,0.8), # define colour of nodes
     vertex.label.family="Times", # define typography
     vertex.label.color="black", # define colour of border
     edge.color="black", # define colour of links
     main = "My Network") # define title

If we want to plot our network using the bipartite package, we first need to convert our network into an incidence matrix:

# Convert the igraph object into incidence matrix 
my_incidence_matrix <- as_incidence_matrix(
  my_network,
  attr = "connection_strength",
  names = TRUE,
  sparse = FALSE
)

# Check matrix
my_incidence_matrix
##                       Apis.mellifera Bombus.terrestris Episyrphus.balteatus
## Gallanthus.nivalis                 1                 0                    0
## Primula.vulgaris                   0                 2                    1
## Salix.sp                           0                 0                    1
## Taraxacum.officinalis              0                 0                    1
## Yellow.flower .m1                  0                 0                    0
##                       Hymenoptera.sp1 Hymenoptera.sp2 Bombus.m1 
## Gallanthus.nivalis                  0               0          0
## Primula.vulgaris                    1               3          0
## Salix.sp                            0               0          4
## Taraxacum.officinalis               0               0          0
## Yellow.flower .m1                   0               0          1

Now we can plot our network:

# Plot the network 
# (you can tweak the arguments to change the look of your network)

plotweb(my_incidence_matrix, # define the matrix
        text.rot=90, # rotate the text
        bor.col.interaction="gray40", # define colour of links
        col.high="blue", # define colour of top level
        col.low="darkgreen", # define colour of lower level
        y.lim=c(-1,3)) # tweak y axis so that network is visible in RMARKDOWN

3.2 Your task

We expect you to repeat the analysis shown above with the data set you collected during the block course. We ask you to upload the raw data you collected as a .csv file onto the server filling the template provided by us.

Please store your data set in the folder workspace/03-18_sampling_an_ecological_network/. Later you can use the 03-18_sampling_an_ecological_network.Rmd script therein to produce your report in html format. Once you are done, please download the whole folder and upload it on OLAT.

If you encounter technical troubles, please ask Fernando to help you.