2
$\begingroup$

I'm looking for a solution to perform network analysis among my data set.

My database is shaped like this :

Table 1 :

           Species a  |  Species b  |  Species c  |  Species x  |
Relevé 1|     NA             2            2             4
Relevé 2|     3              NA           1             1
Relevé 3|     1              2            5             NA
Relevé x|     5              1            1             NA

In first column are relevé ID (unique for each plot sampled) and in row cover abundance of species if seen in the plot, or NA if not seen.

From this database I would obtain a table which will allow me to analyse links between each species like:

Species1 | Species2 | Strenth (number of time the link exists)

Example (according to Table 1):

Species a | Species b | 2 
Species a | Species c | 3
Species a | Species x | 1 
Species b | Species a | 2
Species b | Species c | 3
Species b | Species x | 1  
Species c | Species a | 3
Species c | Species b | 3
Species c | Species x | 2
...

The links between species are considered as true if they coexist in at least one relevé.

If someone knows how to do that, it would be helpful!

Thanks,

R.

$\endgroup$
0
$\begingroup$

Would R code suffice? The code is ugly, but the NA handling is easy.

Let's call your data set dat, assume it's a matrix, the relevé ID are the row names and the species names are the column names.

dat <- cbind(
    c(NA, 3, 1, 5),
    c(2, NA, 2, 1),
    c(2, 1, 5, 1),
    c(4, 1, NA, NA)
    )
colnames(dat) <- paste("Species", c(letters[1:3], "x"))
rownames(dat) <- paste("Relevé", c(1:3, "x"))

species_names <- colnames(dat)
n_species <- nrow(dat)
dat_edgelist <- lapply(
    species_names, function(x){
        new_species_names <- species_names[which(species_names != x)]
        small_el <- lapply(
            new_species_names, function(y){
                strength <- sum(!is.na(dat[,x]) & !is.na(dat[,y]))
                new_row <- c(Species1 = x, Species2 = y, Strenth = strength)                    
                return(new_row)
                }             
            ) 
        small_el <- do.call(rbind, small_el)
        }
    )
dat_edgelist <- do.call(rbind, dat_edgelist)
dat_edgelist <- as.data.frame(dat_edgelist)
dat_edgelist$Strenth <- as.integer(dat_edgelist$Strenth)
dat_edgelist <- dat_edgelist[which(dat_edgelist$Strenth > 0),]

Bear in mind that this output recreates the table you're looking for, yet it is memory inefficient, as it contains twice as many links as necessary, given the symmetry of the problem.

EDIT: Here's nicer looking code than the portion following dat.

new_dat <- 1 * !is.na(dat)
new_dat <- t(new_dat) %*% new_dat
diag(new_dat) <- 0
dat_edgelist <- which(new_dat > 0, arr.ind = TRUE)
dat_edgelist <- data.frame(
    Species1 = rownames(new_dat)[dat_edgelist[,1]], 
    Species2 = colnames(new_dat)[dat_edgelist[,2]]
    )
dat_edgelist$Strenth <- apply(dat_edgelist, 1, function(x)
    return(new_dat[x[1], x[2]])
    )
$\endgroup$
  • $\begingroup$ Hi BenjaminLind, it works perfectly and it's very fast! Thanks! $\endgroup$ – user79216 Jun 11 '15 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy