Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change 'tails' argument to take 'right' and 'both' #49

Merged
merged 4 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions R/3-shared-getAdjacency.R
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
#' Get Adjacency Matrix as indicated by permutation tests
#' Get Adjacency Matrix as indicated by permutation tests.
#'
#' This function gets the significant pairs according to the permutation tests. Then it fills
#' the adjacency matrix with 1 if pair is significant, otherwise 0. The significance is determined
#' by the cutoff value for which the false discovery rate (FDR) is less or equal than the given
#' value 'fdr'. The significant pairs are those that have a value greater/less or equal than the
#' cutoff, depending on the metric.
#'
#' This function gets the significant pairs, according to the permutation tests.
#' Then it fills the adjacency matrix with 1 if pair is significant, otherwise 0.
#' @param object A \code{propd} or \code{propr} object.
#' @param fdr A float value for the false discovery rate. Default is 0.05.
#' @param window_size An integer. Default is 1. When it is greater than 1, the FDR
#' values would be smoothed out by a moving average of the given window size.
#' @param tails 1 for one-sided on the right, and 2 for two-sided. When NULL, use default
#' test for the given metric. This is only relevant for \code{propr} objects.
#' @param tails 'right' or 'both'. 'right' is for one-sided on the right. 'both' is to
#' combine one-sided on the right (positive values) and left (negative values). This is only
#' relevant for \code{propr} objects, as \code{propd} objects are always one-sided and only
#' have positive values.
#' @return An adjacency matrix.
#'
#' @export
getAdjacencyFDR <- function(object, fdr = 0.05, window_size = 1, tails = NULL) {

getAdjacencyFDR <-
function(object, fdr = 0.05, window_size = 1, tails = c('right', 'both')) {

if (inherits(object, "propr")){
adj <- getAdjacencyFDR.propr(object, fdr=fdr, window_size=window_size, tails=tails)

Expand Down Expand Up @@ -60,23 +67,18 @@ getAdjacencyFDR.propd <-
#' pairs from a \code{propd} object.
#' @export
getAdjacencyFDR.propr <-
function(object, fdr = 0.05, window_size = 1, tails = NULL) {
function(object, fdr = 0.05, window_size = 1, tails = c('right', 'both')) {

if (is.null(tails)) {
tails <- ifelse(object@has_meaningful_negative_values, 2, 1)
}
if (tails != 1 & tails != 2) {
stop("Please provide a valid value for tails: 1 or 2.")
}
if (tails == 1 & object@has_meaningful_negative_values) {
warning("Significant pairs are chosen based on one-sided FDR test.")
}
if (tails == 2 & !object@direct) {
stop("Two-sided FDR is not available for this metric.")
# handle tails argument
tails <- match.arg(tails)
if (tails == 'both' & !object@direct) {
warning("Running tails='right' instead")
tails <- 'right' # set to right, when non negative values can be expected for a given metric.
}

# correct fdr when two-sided
if (tails == 2) fdr <- fdr / 2
# correct fdr when considering both tails
# so that the total fdr is the given value
if (tails == 'both') fdr <- fdr / 2

# create empty matrix
adj <- matrix(0, nrow = ncol(object@matrix), ncol = ncol(object@matrix))
Expand All @@ -90,12 +92,12 @@ getAdjacencyFDR.propr <-
if (object@direct) {
adj[object@matrix >= 0 & object@matrix >= cutoff] <- 1
} else {
adj[object@matrix <= cutoff] <- 1
adj[object@matrix <= cutoff] <- 1 # don't have negative values
}
}

# for negative tail
if (tails == 2){
if (tails == 'both'){
cutoff <- getCutoffFDR(object, fdr=fdr, window_size=window_size, positive=F)
if (cutoff) adj[object@matrix < 0 & object@matrix <= cutoff] <- 1
}
Expand Down
4 changes: 2 additions & 2 deletions R/3-shared-getCutoff.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ getCutoffFDR.propr <- function(object, fdr = 0.05, window_size = 1, positive = T
# get index of FDR values below the threshold
index <- (df$FDR <= fdr) & (is.finite(df$FDR))
if (!any(index)) {
warning("No significant cutoff found for the given FDR, when positive = ", positive)
warning("No significant cutoff found for the given FDR, when positive tail = ", positive)
return(FALSE)
}

Expand Down Expand Up @@ -130,7 +130,7 @@ getCutoffFstat <- function(object, pval = 0.05, fdr_adjusted = FALSE) {

if (fdr_adjusted) {
message("Alert: Returning an empiric cutoff based on the $FDR slot.")
index <- (object@results$FDR < pval) & (is.finite(object@results$FDR))
index <- (object@results$FDR <= pval) & (is.finite(object@results$FDR))
if (any(index)) {
cutoff <- max(object@results$theta[index])
} else{
Expand Down
34 changes: 15 additions & 19 deletions R/3-shared-getResults.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ getResults <-

#' Get Significant Results from Object based on the permutation tests.
#'
#' This function provides a unified wrapper to retrieve results
#' from a \code{propr} or \code{propd} object keeping only the
#' statistically significant pairs.
#' This function retrieves results from a \code{propr} or \code{propd} object keeping only the
#' statistically significant pairs. The significance is determined by the cutoff value for which
#' the false discovery rate (FDR) is less or equal than the given value 'fdr'. The significant
#' pairs are those that have a value greater/less or equal than the cutoff, depending on the metric.
#'
#' @inheritParams getAdjacencyFDR
#' @return A \code{data.frame} of results.
#'
#' @export
getSignificantResultsFDR <-
function(object, fdr = 0.05, window_size = 1, tails = NULL) {
function(object, fdr = 0.05, window_size = 1, tails = c('right', 'both')) {

if (inherits(object, "propr")) {
results <- getSignificantResultsFDR.propr(object, fdr=fdr, window_size=window_size, tails=tails)
Expand Down Expand Up @@ -68,19 +69,13 @@ getSignificantResultsFDR.propd <-
#' only the statistically significant pairs.
#' @export
getSignificantResultsFDR.propr <-
function(object, fdr = 0.05, window_size = 1, tails = NULL) {
function(object, fdr = 0.05, window_size = 1, tails = c('right', 'both')) {

if (is.null(tails)) {
tails <- ifelse(object@has_meaningful_negative_values, 2, 1)
}
if (tails != 1 & tails != 2) {
stop("Please provide a valid value for tails: 1 or 2.")
}
if (tails == 1 & object@has_meaningful_negative_values) {
warning("Significant pairs are chosen based on one-sided FDR test.")
}
if (tails == 2 & !object@direct) {
stop("Two-sided FDR is not available for this metric.")
# handle tails argument
tails <- match.arg(tails)
if (tails == 'both' & !object@direct) {
warning("Running tails='right' instead")
tails <- 'right' # set to right, when non negative values can be expected for a given metric.
}

# function to subset the results data frame based on the cutoff
Expand All @@ -93,8 +88,9 @@ getSignificantResultsFDR.propr <-
}
}

# correct fdr when two-sided
if (tails == 2) fdr <- fdr / 2
# correct fdr when considering both tails
# so that the total fdr is the given value
if (tails == 'both') fdr <- fdr / 2

# define results data frame
df <- getResults(object)
Expand All @@ -107,7 +103,7 @@ getSignificantResultsFDR.propr <-
results <- rbind(results, subsetBeyondCutoff(part, cutoff))

# get the significant negative values
if (tails == 2) {
if (tails == 'both') {
cutoff <- getCutoffFDR(object, fdr=fdr, window_size=window_size, positive=F)
part <- df[which(df$propr < 0),]
results <- rbind(results, subsetBeyondCutoff(part, cutoff))
Expand Down
55 changes: 31 additions & 24 deletions R/3-shared-updateCutoffs.R
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
#' Update FDR by Permutation
#'
#' This function updates FDR for a set of cutoffs.
#'
#' This function wraps \code{updateCutoffs.propr} and
#' \code{updateCutoffs.propd}.
#' This function updates the FDR for each cutoff. By default, the set of cutoffs are determined
#' based on the quantile of the data, so that the cutoffs are evenly spaced across the data.
#' The FDR is calculated as the ratio between the number of permuted values beyond the cutoff
#' and the number of true values beyond the the cutoff.
#' When tails is set to 'right', the FDR is calculated only on the positive side of the data.
#' When tails is set to 'both', the FDR is calculated on both sides of the data.
#'
#' @param object A \code{propr} or \code{propd} object.
#' @param number_of_cutoffs An integer. The number of cutoffs to test.
#' Given this number, the cutoffs will be determined based on the quantile of the data.
#' In this way, the cutoffs will be evenly spaced across the data.
#' @param custom_cutoffs A numeric vector. When provided, this vector is used
#' as the FDR cutoffs to test, and number_of_cutoffs is ignored.
#' @param tails 1 for one-sided on the right, and 2 for two-sided. When two-sided,
#' the FDR is calculated for both positive and negative values. When NULL, use default
#' option for the given metric. This is only relevant for \code{propr} objects.
#' @param number_of_cutoffs An integer. The number of cutoffs to test. Given this number,
#' the cutoffs will be determined based on the quantile of the data. In this way, the
#' cutoffs will be evenly spaced across the data.
#' @param custom_cutoffs A numeric vector. When provided, this vector is used as the set of
#' cutoffs to test, and 'number_of_cutoffs' is ignored.
#' @param tails 'right' or 'both'. 'right' is for one-sided on the right. 'both' is to
#' combine one-sided on the right (positive values) and left (negative values). This
#' is only relevant for \code{propr} objects, as \code{propd} objects are always one-sided
#' and only have positive values.
#' @param ncores An integer. The number of parallel cores to use.
#' @return A \code{propr} or \code{propd} object with the FDR slot updated.
#'
#' @export
updateCutoffs <-
function(object,
number_of_cutoffs = 100,
custom_cutoffs = NULL,
tails = NULL,
tails = c('right','both'),
ncores = 1) {
tails <- match.arg(tails)

if (!is.null(tails)){
if (tails != 1 & tails != 2) stop("Tails only accept values 1 or 2, if not NULL.")
}

get_cutoffs <- function(values, number_of_cutoffs, custom_cutoffs, tails=1) {
# function to get the set of cutoffs
get_cutoffs <- function(values, number_of_cutoffs, custom_cutoffs, tails='right') {
if (!is.null(custom_cutoffs)) return(custom_cutoffs)
if (tails == 1) values <- values[values >= 0]
if (tails == 'right') {
values <- values[values >= 0]
if (length(values) == 0) stop("No positive values found.")
}
return(as.numeric(quantile(values, probs = seq(0, 1, length.out = number_of_cutoffs))))
}

# update FDR values for propr object
if (inherits(object, "propr")) {
if (is.null(tails)) tails <- ifelse(object@has_meaningful_negative_values, 2, 1)
if (tails == 1 & object@has_meaningful_negative_values) warning("One-sided FDR test is performed.")
if (tails == 2 & !object@direct) stop("Two-sided FDR is not available for this metric.")
if (tails == 'both' & !object@direct) {
warning("Running tails='right' instead")
tails <- 'right' # set to right, when non negative values can be expected for a given metric.
}
values <- object@results$propr
cutoffs <- get_cutoffs(values, number_of_cutoffs, custom_cutoffs, tails)
updateCutoffs.propr(object, cutoffs, ncores)

# update FDR values for propd object
} else if (inherits(object, "propd")) {
values <- object@results$theta
cutoffs <- get_cutoffs(values, number_of_cutoffs, custom_cutoffs, tails=1)
cutoffs <- get_cutoffs(values, number_of_cutoffs, custom_cutoffs, tails='right')
updateCutoffs.propd(object, cutoffs, ncores)

} else{
Expand All @@ -64,7 +72,6 @@ updateCutoffs <-
#' @export
updateCutoffs.propr <-
function(object, cutoffs, ncores) {

if (identical(object@permutes, list(NULL))) {
stop("Permutation testing is disabled.")
}
Expand Down
4 changes: 2 additions & 2 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pr <- updateCutoffs(
pr,
number_of_cutoffs = 100, # number of cutoffs to estimate FDR
custom_cutoffs = NULL, # or specify custom cutoffs
tails = 1, # 1 or 2-tailed test
tails = 'right', # consider only the positive values ('right') or both sides ('both')
ncores = 4 # parallelize here
)
```
Expand All @@ -81,7 +81,7 @@ pr <- updateCutoffs(
pr,
number_of_cutoffs = 100, # number of cutoffs to estimate FDR
custom_cutoffs = NULL, # or specify custom cutoffs
tails = 1, # 1 or 2-tailed test
tails = 'right', # consider only the positive values ('right') or both sides ('both')
ncores = 4 # parallelize here
)
```
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pr <- updateCutoffs(
pr,
number_of_cutoffs = 100, # number of cutoffs to estimate FDR
custom_cutoffs = NULL, # or specify custom cutoffs
tails = 1, # 1 or 2-tailed test
tails = 'right', # consider only the positive values ('right') or both sides ('both')
ncores = 4 # parallelize here
)
```
Expand Down Expand Up @@ -131,7 +131,7 @@ pr <- updateCutoffs(
pr,
number_of_cutoffs = 100, # number of cutoffs to estimate FDR
custom_cutoffs = NULL, # or specify custom cutoffs
tails = 1, # 1 or 2-tailed test
tails = 'right', # consider only the positive values ('right') or both sides ('both')
ncores = 4 # parallelize here
)
```
Expand Down
29 changes: 22 additions & 7 deletions man/getAdjacencyFDR.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 15 additions & 7 deletions man/getSignificantResultsFDR.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading