# Electronic supplementary material for # Great cormorants reveal overlooked secondary dispersal of plants and invertebrates by piscivorous birds" # Casper H.A. van Leeuwen, Ádám Lovas-Kiss, Maria Ovegård and Andy J. Green # Biology Letters ## R version 3.3.3 (2017-03-06) ## ####### Visualisation of co-occurrence matrix in a network plot ####### ####### start of script ###### ####### Casper H.A. van Leeuwen ###### ####### for questions contact me ###### ####### www.caspervanleeuwen.info ###### # install and load the following libraries library(Hmisc) library(statnet) setwd(" ... ") # set working directory as appropriate # the script assume a datafile is available containing data on the presence of X species in N samples # (for this manuscript: X propagule- and fish species were present in N pellets of great cormorants) # create a csv file in the working directory named "data.csv", containing data on the presence of X species (columns) in N samples (rows) # The format is as follows: # Pellet sample Species_1 Species_2 Species_3 Species_4 Species_.. Species_X # 1 # 2 # 3 # 4 # 5 # .. # N data <- read.csv("data.csv", header = TRUE) # load your own datafile into the R environment # for this script an example datafile can also be generated instead: sample <- c(1:10) species.1 <- c(0,1,2,4,3,5,0,0,0,0) species.2 <- c(0,5,10,15,15,10,0,5,5,5) species.3 <- c(0,1,0,0,0,0,2,2,0,0) species.4 <- c(0,3,3,3,4,0,0,1,3,1) species.5 <- c(0,2,0,0,0,0,1,1,0,0) species.6 <- c(0,0,0,1,0,0,5,1,0,0) species.7 <- c(0,204,0,0,305,0,20,0,335,0) species.8 <- c(0,2,0,4,0,4,1,4,0,0) data <- data.frame(cbind(sample, species.1, species.2, species.3, species.4, species.5, species.6, species.7, species.8)) # example dataframe # create Spearman rank correlations among all possible combinations of species based on their presence names(data) <- gsub("\\.", " ", names(data)) # substitue points in the species names by spaces for later plotting d <- data[-c(1)] # remove the first column containing the sample number mat1 <- rcorr(as.matrix(d), type = c("spearman")) # create a co-occurence matrix with Spearman Rank correlations for all species mat <- ifelse(mat1$r > 0.3 & mat1$P < 0.05, 1, 0) # this sets the boundaries for which correlations are deemed biologically relevant, and therefore determines the number of species and associations included in the figure. For our study only significant correlations among species at the alpha level of 0.05 and with a rho larger than 0.3 were included. This can here be varied depending on the study. mat2 <- ifelse (mat > 0, mat1$r, 0) # create matrix with only the rho values to use in plotting mat2[lower.tri(mat2)] <- NA # set double values to NA to later remove rhos <- as.vector(mat2) # create vector from matrix rhos <- rhos[ rhos != 0 ] # remove zero rho values rhos <- rhos[!is.na(rhos)] # remove missing values to create a vector with only the rho values in the right order diag(mat) <- 0 # replace all diagonal "NA" values that could not be computed by zeros dim(mat) # informs on the number of species called "nodes" that will be included in the figure sum(mat) # informs on the number of connections called "edges" that will be included in the figure net <- as.network(x = mat, # creates a the network object for use in statnet directed = TRUE, # specify whether the network is directed or not loops = FALSE, # do we allow self ties (should not allow them) matrix.type = "adjacency" # setting the type of input ) network.vertex.names(net) <- colnames(mat) # assigns the species names in the matrix column headings tot the objects in the network object # In our analysis we had three types of species: fish, plants nd invertebrates - each type was given a different colour in the graph for clarity. type <- c("Fish","Plant","Invertebrate", "Fish", "Plant", "Plant", "Plant", "Plant") # create a vector with length dim(mat)[2] describing the type of each species for colouring the graph. set.vertex.attribute ( net, # the name of the network object "Type", # the name we want to reference the variable by in that object type # the vector previously created describing the type for each species ) # color the species (=nodes) based on their "type" using a forloop # if type is Fish, colour becomes orange / if type is Plant, colour becomes lightgreen / if type is else, colour is lightblue num_nodes <- dim(mat)[2] # create an object with the number of nodes in the final graph node_colors <- rep("",num_nodes) # create vector with the length of the number of species for(i in 1:num_nodes){ if(get.node.attr(net,"Type")[i] == "Fish"){ node_colors[i] <- "orange" } else { if(get.node.attr(net,"Type")[i] == "Plant"){ node_colors[i] <- "lightgreen" }else{ node_colors[i] <- "lightblue" } }} # end of for loop # make d a binomial dataframe for plotting using a forloop # if the number is larger than 0 it becomes a 1 for (i in 1:dim(d)[2]) { for (j in 1 : dim(d)[1]) { if (d[j,i] > 0 ) { d[j,i] <- 1 } else {0} }} # end of for loop # make the size of nodes representative of species abundance by using the sums of columns as a measure size <- colSums (d, na.rm = FALSE, dims = 1) # create a vector with the sum of each column (= one value for each species) set.vertex.attribute(net, "Size", size) # add size as a attribute to the network object "net" #Now we can create a blank edgelist with spaces for each edge which we will populate with names we generated above: #num_edges <- dim(d)[2] # invullen uit net object #edgelist <- matrix("",nrow= num_edges,ncol = 2) edge_weights <- rhos set.edge.value(net,"trust",edge_weights*10) # make edge width proportional to rho par(font = 3) # display species names on nodes italic #plot the actual graph plot.network(net, # our network object vertex.col = node_colors, # color nodes by species type vertex.border = 0, # no border needed vertex.cex = log10(size+1)*10, # size nodes by their relative number present displaylabels = TRUE, # display species names label.col = "black", # set colour of species names label.cex = 0.8, # font size of species names label.pos = 5, # display the names directly over nodes usearrows = FALSE, # no directionality edge.lwd = get.edge.value(net,"trust"), # edge width interactive = TRUE, # allows manual dragging of nodes to optimal positions displayisolates = TRUE, # don´t remove single nodes without edges mode = "kamadakawai", # choose the arrangement of the nodes and edges vertices.last = TRUE # draw the nodes after the edges ) # manually drag nodes as desired to optimally position nodes and avoid possible overlap of species names ####### end of script ###### ####### Casper H.A. van Leeuwen ###### ####### for questions contact me ###### ####### www.caspervanleeuwen.info ######