diff --git a/R/RN_dims.R b/R/RN_dims.R index 4ce856a..46e60e1 100644 --- a/R/RN_dims.R +++ b/R/RN_dims.R @@ -1,17 +1,54 @@ -#' Title +#' Basic network dimensions #' -#' @param int_data -#' @param cover_data -#' @param int_type +#' +#' @description +#' Calculates basic descriptors of the interactions network, such as its size +#' described by the number of nodes and links, and its complexity, which is +#' proportional to network connectance. +#' +#' @inheritParams int_significance #' #' @returns +#' A table with the following information: +#' - *Num nodes*: Number of nodes in the network (*N*). In the case of +#' facilitation and competition the nodes are provided for each guild +#' - *Num. links*: Number of links in the network (*L*). +#' - *Connectance*: Proportion of links observed from all the possible +#' links (*C*). In the case of general recruitment networks, we use the +#' formula $C = L / (N^2 - N)$ since the node "Open" does not act as a recruit +#' (i.e. Open is represented by a row of zeroes in the adjacency matrix). +#' For facilitation and recruitment depressing networks, connectance is +#' calculated as $C = L /(N_c N_r)$, where *N_c* and *N_r* are the number +#' of canopy and recruit species, respectively. +#' +#' int_type**: Indicates the type of plant-plant interaction that will be +#' presented in the output (recruitment patterns, recruitment enhancement +#' (i.e. facilitation) or recruitment depression (i.e. competition)) +#' - *rec*: Estimates the number of nodes, links and connectance of the network +#' based on all plant-plant interactions that contribute to recruitment. "Open" +#' is considered an additional canopy species category. +#'- *fac*: Estimates the number of nodes, links and connectance of the +#' network based on only those pairwise interactions that significantly +#' enhance recruitment. Not every interaction detected in the field has +#' to be present in the matrix. Non-detected interactions are not considered +#' and "Open" is not included as a canopy species category. +#' - *comp*: Estimates the number of nodes, links and connectance of the network +#' based on only those pairwise interactions that depress recruitment. Not every +#' interaction detected in the field has to be present in the matrix. However, +#' in this case non-detected interactions are considered. "Open" is not +#' included as a canopy species category. +#' +#' #' @export #' #' @examples +# +#'RN_dims(Amoladeras_int, Amoladeras_cover, int_type="rec") +#'RN_dims(mysite_com, mysite_cov, int_type="fac") +#'RN_dims(mysite_com, mysite_cov, int_type="comp") +#' +#' #' -#' # RN_dims_UNI() modified to enter the interaction and cover data -#The size of a network can be described by the number of nodes (*N*) and links (*L*), and its complexity is #proportional to network connectance. *C* can be estimated on different ways depending on the type of #network, but it always measures the proportion of links relative to the maximum number of links that could #be possible in the network. In the case of recruitment networks we use the formula $C = L /(N^2-N)$ since #the node "Open" does not act as a recruit (i.e. Open is represented by a row of zeroes in the adjacency #matrix). -#For facilitation and competition that are bipartite networks, the nodes in eahc guild are #provided( nurse/facilitated, Canopy (depressor)/recruit) seprately, and open is not a node #' RN_dims <- function(int_data,cover_data, int_type=c("rec","fac","comp")){ @@ -34,7 +71,8 @@ RN_dims <- function(int_data,cover_data, int_type=c("rec","fac","comp")){ if(int_type=="fac"){ - int_data <-suppressWarnings(RN_to_matrix(int_data,cover_data, int_type="fac",weight="Pcr")) + int_data <-suppressWarnings(RN_to_matrix(int_data,cover_data, + int_type="fac",weight="Pcr")) df <-int_data n_nodes_nurse <-dim(df)[2] @@ -44,7 +82,8 @@ RN_dims <- function(int_data,cover_data, int_type=c("rec","fac","comp")){ out <- data.frame(c(n_nodes_nurse,n_nodes_facilitated, n_links, connectance)) colnames(out) <- c("Value") - rownames(out) <- c("Num. Nurse sp","Num. Facilitated sp", "Num. Links", "Connectance") + rownames(out) <- c("Num. Nurse sp","Num. Facilitated sp", + "Num. Links", "Connectance") return(out) } @@ -52,7 +91,8 @@ RN_dims <- function(int_data,cover_data, int_type=c("rec","fac","comp")){ if(int_type=="comp"){ - int_data <-suppressWarnings(RN_to_matrix(int_data,cover_data, int_type="comp",weight="Pcr")) + int_data <-suppressWarnings(RN_to_matrix(int_data,cover_data, + int_type="comp",weight="Pcr")) df <-int_data n_nodes_canopy_depressing <-dim(df)[2] @@ -60,9 +100,11 @@ RN_dims <- function(int_data,cover_data, int_type=c("rec","fac","comp")){ n_links <- sum(df) connectance <-n_links/(n_nodes_canopy_depressing*n_nodes_recruit_depressed) - out <- data.frame(c(n_nodes_canopy_depressing, n_nodes_recruit_depressed, n_links, connectance)) + out <- data.frame(c(n_nodes_canopy_depressing, n_nodes_recruit_depressed, + n_links, connectance)) colnames(out) <- c("Value") - rownames(out) <- c("Num. Canopy depressing sp","Num. Recruit depressed sp", "Num. Links", "Connectance") + rownames(out) <- c("Num. Canopy depressing sp","Num. Recruit depressed sp", + "Num. Links", "Connectance") return(out) diff --git a/R/int_significance.R b/R/int_significance.R index b8dc7e7..b96d542 100644 --- a/R/int_significance.R +++ b/R/int_significance.R @@ -1,26 +1,126 @@ -#' Title +#' Statistical significance of interactions #' -#' @param int_data -#' @param cover_data -#' @param int_type +#' @description +#' conducts statistical tests for each pairwise interaction, indicating whether +#' the effect of the canopy species on recruitment is enhancing (i.e. positive), +#' depressing (i.e. negative), neutral, or whether it could not be tested due to +#' low sample size. + +#'**IMPORTANT NOTE: Data on recruitment in Open is required for the tests.** + +#' To assess whether recruitment is affected by a given canopy species compared +#' to the "Open" it is used an exact binomial test or a chi square test (if +#' the number of recruits is large enough so that the expected frequencies are +#' larger than 5). The tests address the null hypothesis that recruitment is +#' as frequent under a given canopy species as it is in open interspaces. Thus, +#' we use these tests as a goodness-of-fit tests. The logic is that, if +#' recruitment were neutral regarding the microhabitat, we would observe that +#' the number of recruits under canopy would be exactly proportional to the +#' relative cover of each microhabitat. If the null hypothesis is rejected, +#' we would conclude that recruitment is affected (enhanced or depressed) by +#' the canopy species compared with the prospects of recruitment when seeds +#' are dispersed away from established plants. + +#' When the exact binomial test is applied to canopy-recruit pairs with very +#'low number of recruits, it may be impossible to reject the null hypothesis +#' even if all the recruits occurred in the less likely microhabitat. In such +#' cases, one might conclude that the interaction has a neutral effect when it +#' is actually not possible to reach a conclusion. We classify these cases as +#' "not testable". + +#' +#' @inheritParams check_interactions +#' @inheritParams check_cover +#' +#' @param int_type Indicates the type of plant-plant interaction that will be +#' analyzed: general recruitment, recruitment enhancement (i.e. facilitation) +#' or recruitment depression (i.e. competition). +#' Explanation of its options: +#' +#' - *rec*: All the pairwise interactions observed will be in the output. +#' Focuses on canopy-recruit interactions considering that every recruit +#' growing under the canopy of another plant may occupy that space in the +#' future, thus having a potentially positive effect on the recruit species +#' population. Therefore, even a single observation is considered an +#' interaction. This type of networks considers every species present in the +#' study system, whether as a canopy or as a recruit, as a node in the network. +#' It also includes "Open" as a particular node since some species may recruit +#' away from established plants. Non-detected interactions are also considered +#' since zero frequency can provide evidence of a very negative interaction +#' if the expected frequency under the canopy species is large. +#' - *fac*: Only those pairwise interactions that resulted in recruitment +#' enhancement will be in the output. Focuses on interactions with a +#' significantly higher recruitment density under canopy than in "Open" +#' (i.e. facilitation). Non-detected interactions are not considered and +#' "Open" is not included as a node, although its relative cover is considered +#' as part of the sampling area. +#' - *comp*: Only those pairwise interactions that resulted in a recruitment +#' depression will be in the output. Focuses on interactions with a +#' significantly lower recruitment density under canopy than "Open" +#' (i.e. competition). Non-detected interactions are considered (i.e. expanding +#' with 0 all possible interactions in the study system), as the absence of +#' recruitment of a species under a given canopy can reflect a particularly +#' strong depression of recruitment under that canopy species. "Open" is not +#' included as a node, although its relative cover is considered as part of the +#' sampling area. + #' -#' @returns +#' @returns a data frame with the following information for each recruit-canopy +#' interaction with the following information: + +#'- *Canopy*: Canopy species +#'- *Recruit*: Recruit species +#'- *Fcr*: frequency of recruitment, as the number of recruits found under that +#'canopy species. +#'- *Ac*: Area (in m^2^), (or m when relative cover is measured with transects) +#' occupied by the canopy species in the study site. +#'- *Fro*: frequency of recruitment in open interspaces. +#'- *Ao*: Area (in m^2^), (or m when relative cover is measured with transects) +#' occupied by the open interspaces in the study site. +#'- *testability*: Testability indicates the smallest p-value that a binomial +#' test will estimate based in a given number of recruits. If this p-value is +#' above the reference p-value (typically 0.05), then you have too few cases +#' (number of recruits) to ever reject the null hypothesis, and the interaction +#' is not testable. +#'- *Significance*: p-value of the chi square or binomial test assessing the +#' null hypothesis that Fcr and Fro are equal to the expected frequencies based +#' on the relative cover of each of the two microhabitats: $Ac/(Ac+Ao)$ and +#' $1-(Ac/(Ac+Ao))$ +#' - *Test_type*: Indicates whether, depending on the sample size, a chi square +#' or binomial test has been conducted. +#'- *Effect_int*: Indicates, for each interaction, whether the analysis +#' classifies it as "Enhancing", "Depressing", "Neutral" or "Not Testable". + #' @export #' #' @examples #' -#' # int_significance() Use all functions to consider all interactions (observed and non-observed) (for Recruitment networks) or only observed interactions (for facilitation/completition networks) +#' int_signif_rec <- int_significance(Amoladeras_int, Amoladeras_cover, int_type = "rec") +#' head(int_signif_rec) +#' +#' int_signif_fac <- int_significance(Amoladeras_int, Amoladeras_cover, int_type = "fac") +#' head(int_signif_fac) #' +#' int_signif_comp <- int_significance(Amoladeras_int, Amoladeras_cover, int_type = "comp") +#' head(int_signif_comp) #' int_significance <- function(int_data, cover_data, int_type=c("rec", "fac","comp")){ - if (!"Open" %in% int_data$Canopy) stop("ERROR: tests cannot be conducted because your data does not contain a node named Open or it is spelled differently.") + int_type <- match.arg(int_type) + + if (!"Open" %in% int_data$Canopy) { + stop("tests cannot be conducted because your data does not contain a + node named Open or it is spelled differently.") + } if(int_type=="rec"){ data<-comm_to_RN_UNI(int_data,cover_data) df<-int_significance_UNI(data) - if(length(unique(df$Test_type))>1) message("Different tests were used for different canopy-recruit pairs. Check column Test_type") + if(length(unique(df$Test_type))>1) { + message("Different tests were used for different canopy-recruit pairs. + Check column Test_type") + } } if(int_type=="fac"){ @@ -28,7 +128,9 @@ int_significance <- function(int_data, cover_data, int_type=c("rec", "fac","comp data<-comm_to_RN_BI(int_data,cover_data) df<-int_significance_BI (data) df<-df[df$Effect_int=="Enhancing",] - if(length(unique(df$Test_type))>1) message("Different tests were used for different canopy-recruit pairs. Check column Test_type") + if(length(unique(df$Test_type))>1) + message("Different tests were used for different canopy-recruit pairs. + Check column Test_type") } if(int_type=="comp"){ @@ -36,7 +138,9 @@ int_significance <- function(int_data, cover_data, int_type=c("rec", "fac","comp data<-comm_to_RN_UNI_COMP(int_data,cover_data) df<-int_significance_BI_COMP(data) df<-df[df$Effect_int=="Depressing",] - if(length(unique(df$Test_type))>1) message("Different tests were used for different canopy-recruit pairs. Check column Test_type") + if(length(unique(df$Test_type))>1) + message("Different tests were used for different canopy-recruit pairs. + Check column Test_type") } @@ -44,3 +148,4 @@ int_significance <- function(int_data, cover_data, int_type=c("rec", "fac","comp } + diff --git a/tests/testthat/test-RN_dims.R b/tests/testthat/test-RN_dims.R index b9ba033..4dfe4b4 100644 --- a/tests/testthat/test-RN_dims.R +++ b/tests/testthat/test-RN_dims.R @@ -1,17 +1,12 @@ test_that("RN_dims works for recruitment networks in Amoladeras", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") - out <- RN_dims( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "rec" ) - # estructura del output + # Output structure expect_s3_class(out, "data.frame") expect_equal(rownames(out), c("Num. Nodes", "Num. Links", "Connectance")) @@ -20,19 +15,15 @@ test_that("RN_dims works for recruitment networks in Amoladeras", { #------------------- test_that("RN_dims computes connectance correctly for rec networks", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") out <- RN_dims( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "rec" ) - # reconstrucción manual del cálculo - df <- comm_to_RN_UNI(Amoladeras_com, Amoladeras_cov) + # Manual calculation + df <- comm_to_RN_UNI(Amoladeras_int, Amoladeras_cover) n_nodes <- length(unique(c(df$Canopy, df$Recruit))) n_links <- sum(df$Pcr) connectance_expected <- n_links / (n_nodes^2 - n_nodes) @@ -42,14 +33,10 @@ test_that("RN_dims computes connectance correctly for rec networks", { #--------------------- test_that("RN_dims works for facilitation networks in Amoladeras", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") - out <- RN_dims( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + out <- RN_dims( + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "fac" ) @@ -61,14 +48,11 @@ test_that("RN_dims works for facilitation networks in Amoladeras", { #--------------------- test_that("RN_dims works for competition networks in Amoladeras", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") + out <- RN_dims( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "comp" ) @@ -80,15 +64,11 @@ test_that("RN_dims works for competition networks in Amoladeras", { #----------------------------- test_that("RN_dims connectance for bipartite networks is correctly calculated", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") - fac_dims <- RN_dims(Amoladeras_com, Amoladeras_cov, int_type = "fac") + fac_dims <- RN_dims(Amoladeras_int, Amoladeras_cover, int_type = "fac") - mat <- RN_to_matrix(Amoladeras_com, Amoladeras_cov, + mat <- RN_to_matrix(Amoladeras_int, Amoladeras_cover, int_type = "fac", weight = "Pcr") n_links <- sum(mat) diff --git a/tests/testthat/test-int_significance.R b/tests/testthat/test-int_significance.R index 0fad6b8..bd39a7d 100644 --- a/tests/testthat/test-int_significance.R +++ b/tests/testthat/test-int_significance.R @@ -1,16 +1,9 @@ -library(testthat) - -data(RecruitNet) -data(CanopyCover) - test_that("int_significance works for recruitment network in Amoladeras", { - - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") + out <- int_significance( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "rec" ) @@ -21,16 +14,11 @@ test_that("int_significance works for recruitment network in Amoladeras", { #---------------------- test_that("int_significance works for facilitation network in Amoladeras", { - #data(RecruitNet) - #data(CanopyCover) - - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") out <- int_significance( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "fac" ) @@ -40,13 +28,10 @@ test_that("int_significance works for facilitation network in Amoladeras", { #---------------- test_that("int_significance works for competition network in Amoladeras", { - - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") out <- int_significance( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "comp" ) @@ -57,21 +42,16 @@ test_that("int_significance works for competition network in Amoladeras", { #---------------- test_that("int_significance fails in Amoladeras if 'Open' canopy is missing", { - - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") - int_data <- Amoladeras_com + int_data <- Amoladeras_int int_data$Canopy <- as.character(int_data$Canopy) int_data <- int_data[int_data$Canopy != "Open", ] expect_error( int_significance( int_data = int_data, - cover_data = Amoladeras_cov, + cover_data = Amoladeras_cover, int_type = "rec" ), "ERROR: tests cannot be conducted" @@ -80,16 +60,11 @@ test_that("int_significance fails in Amoladeras if 'Open' canopy is missing", { #-------------------- test_that("int_significance message appears when multiple statistical tests are used (Amoladeras)", { - #data(RecruitNet) - #data(CanopyCover) - Amoladeras_com <- comm_subset(RecruitNet, site = "Amoladeras") - Amoladeras_cov <- comm_subset(CanopyCover, site = "Amoladeras") - expect_message( int_significance( - int_data = Amoladeras_com, - cover_data = Amoladeras_cov, + int_data = Amoladeras_int, + cover_data = Amoladeras_cover, int_type = "rec" ), "Different tests were used",