#' Does nothing, just returns the original data
#'
#' @param data data matrix
#' @return The data matrix
noNormalization <- function(data) {
return(data)
}
#' Performs z-normalization on all columns
#' @importFrom matrixStats colMeans2
#' @importFrom matrixStats colSds
#' @param data data matrix
#' @return Data matrix with same dimensions, with each column z-normalized.
colNormalization <- function(data) {
mu <- colMeans2(data)
sigma <- colSds(data)
sigma[sigma == 0] <- 1.0
ndata <- t(
(t(data) - mu)/sigma
)
return(ndata)
}
#' Performs z-normalization on all rows
#' @importFrom matrixStats rowMeans2
#' @importFrom matrixStats rowSds
#' @param data data matrix
#' @return Data matrix with same dimensions, with each row z-normalized.
rowNormalization <- function(data) {
mu <- rowMeans2(data)
sigma <- rowSds(data)
sigma[sigma == 0] <- 1.0
ndata <- (data - mu) / sigma
return(ndata)
}
#' Performs z-normalization on all columns and rows
#'
#' @param data data matrix
#' @return Data matrix with same dimensions, with each row and column z-normalized.
rowAndColNormalization <- function(data) {
data = rowNormalization(data)
data = colNormalization(data)
return(data)
}
#' Creaes a new version of the data that has ranks (column-wise) instead of values.
#' @importFrom matrixStats colRanks
#' @param data data matrix
#' @return Data matrix with same dimensions, with each value representing its column-wise rank.
colRankNormalization <- function(data) {
rdata = colRanks(data, ties.method="min", preserveShape=TRUE)
rownames(rdata) <- rownames(data)
colnames(rdata) <- colnames(data)
return(rdata)
}
#' Calculates the specified normalized data matrix
#' @param data numeric matrix
#' @param func normalization method to apply
#' @return Normalized data matrix according to function specified.
getNormalizedCopy <- function(data, func) {
data <- matLog2(data)
if (func == "none") {
return(noNormalization(data))
} else if (func == "znorm_columns") {
return(colNormalization(data))
} else if (func == "znorm_rows") {
return(rowNormalization(data))
} else if (func == "znorm_rows_then_columns") {
return(rowAndColNormalization(data))
} else if (func == "rank_norm_columns") {
return(colRankNormalization(data))
}
stop("Normalization method not recognized.")
}
#' Calculates the specified normalized data matrix
#'
#' @importFrom Matrix rowMeans
#' @importFrom Matrix colMeans
#'
#' @param data numeric matrix
#' @param func normalization method to apply
#' @return NormData normalized data object that maintains sparse structure
getNormalizedCopySparse <- function(data, func) {
data <- matLog2(data)
if (!(func %in% c(
"none", "znorm_columns",
"znorm_rows", "znorm_rows_then_columns"
))){
stop("Normalization method not recognized.")
}
rowOffsets <- NULL
colOffsets <- NULL
rowScaleFactors <- NULL
colScaleFactors <- NULL
if (func == "znorm_rows" || func == "znorm_rows_then_columns") {
rowOffsets <- rowMeans(data) * -1
rowScaleFactors <- rowVarsSp(data) ** -0.5
rowScaleFactors[is.infinite(rowScaleFactors)] <- 1
}
if (func == "znorm_columns") {
colOffsets <- colMeans(data) * -1
colScaleFactors <- colVarsSp(data) ** -0.5
colScaleFactors[is.infinite(colScaleFactors)] <- 1
}
if (func == "znorm_rows_then_columns") {
result <- .colNormHelper(data, rowOffsets, rowScaleFactors)
colOffsets <- result$colOffsets
colScaleFactors <- result$colScaleFactors
colScaleFactors[is.infinite(colScaleFactors)] <- 1
}
nd <- NormData(data, rowOffsets = rowOffsets, colOffsets = colOffsets,
rowScaleFactors = rowScaleFactors, colScaleFactors = colScaleFactors)
return(nd)
}
#' Initialize a new NormData object
#'
#' @importFrom Matrix Matrix
#' @importFrom matrixStats colCounts
#'
#' @param data expression data matrix
#' @param rowOffsets offsets to be subtracted from each row
#' @param rowScaleFactors factors to scale each row
#' @param colOffsets offsets to be subtracted from each column
#' @param colScaleFactors factors to scale each column
#' @return NormData object
NormData <- function(data, rowOffsets = NULL, rowScaleFactors = NULL,
colOffsets = NULL, colScaleFactors = NULL) {
if (is.null(rowOffsets)){
rowOffsets <- numeric(nrow(data))
}
if (is.null(rowScaleFactors)){
rowScaleFactors <- numeric(nrow(data)) + 1
}
if (is.null(colOffsets)){
colOffsets <- numeric(ncol(data))
}
if (is.null(colScaleFactors)){
colScaleFactors <- numeric(ncol(data)) + 1
}
if (!is(data, "Matrix")) {
colFill <- colCounts(data, cols = seq_len(min(ncol(data), 500)), value = 0) / nrow(data)
if (mean(colFill) < .5){
data <- as(data, "dgCMatrix")
} else {
data <- as(data, "dgeMatrix")
}
}
.Object <- new("NormData",
data = data,
rowOffsets = rowOffsets,
colOffsets = colOffsets,
rowScaleFactors = rowScaleFactors,
colScaleFactors = colScaleFactors
)
return(.Object)
}
#' Calculates the column znormalization after row znormalization
#'
#' Helper to do this without inflating the matrix
#'
#' @importFrom Matrix Matrix
#' @importFrom Matrix Diagonal
#' @importFrom stats setNames
#'
#' @param data expression data matrix
#' @param rowOffsets offsets to be subtracted from each row
#' @param rowScaleFactors factors to scale each row
#' @return colOffsets and colScaleFactors
.colNormHelper <- function(data, rowOffsets, rowScaleFactors) {
E <- data
NCells <- ncol(E)
NGenes <- nrow(E)
Rs <- Diagonal(x = rowScaleFactors)
Rog <- Matrix(rowOffsets, ncol = 1)
Roc <- Matrix(1, nrow = 1, ncol = NCells)
C1 <- Matrix(1, nrow = 1, ncol = NGenes)
C1Rs <- C1 %*% Rs
C1RsE <- C1 %*% Rs %*% E
Co <- ( (C1RsE) + (C1Rs %*% Rog %*% Roc) ) / NGenes * -1
Cog <- Matrix(1, ncol = 1, nrow = NGenes)
Coc <- Co
t1 <- C1 %*% (Rs %*% E) ** 2
t2 <- 2 * Matrix(rowOffsets * rowScaleFactors, nrow = 1) %*% Rs %*% E
t3 <- 2 * (C1RsE) * Co
t4 <- Matrix(sum( (rowScaleFactors * rowOffsets) ** 2),
nrow = 1, ncol = NCells)
t5 <- 2 * Matrix(sum(rowScaleFactors * rowOffsets), nrow = 1, ncol = NCells) * Co
t6 <- Co * Co * NGenes
Cs <- (t1 + t2 + t3 + t4 + t5 + t6) / (NGenes - 1)
colOffsets <- setNames(as.numeric(Co), colnames(Co))
colScaleFactors <- setNames(as.numeric(Cs), colnames(Cs))
colScaleFactors <- colScaleFactors ** -0.5
return(list(colOffsets = colOffsets, colScaleFactors = colScaleFactors))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.