I have a procedure for normalizing variables, the details of which can be viewed in this white paper.

I would like to be able to make the routine scalable to handle any number of variables. Below is the R code for a 4 variable example with a regular correlation coefficient substituted for the preferred nonlinear coefficient (for simplicity and demonstration purposes). Any insights or comments are appreciated.

VN_Normalization <- function(A1, A2, A3, A4){

#Array1 Scaling Factor 
RG_Factor_A1_A2<- mean(A1)/mean(A2)
RG_Factor_A1_A3<- mean(A1)/mean(A3)
RG_Factor_A1_A4<- mean(A1)/mean(A4)

#Array2 Scaling Factor
RG_Factor_A2_A1<- mean(A2)/mean(A1)
RG_Factor_A2_A3<- mean(A2)/mean(A3)
RG_Factor_A2_A4<- mean(A2)/mean(A4)

#Array3 Scaling Factor
RG_Factor_A3_A1<- mean(A3)/mean(A1)
RG_Factor_A3_A2<- mean(A3)/mean(A2)
RG_Factor_A3_A4<- mean(A3)/mean(A4)

#Array4 Scaling Factor
RG_Factor_A4_A1<- mean(A4)/mean(A1)
RG_Factor_A4_A2<- mean(A4)/mean(A2)
RG_Factor_A4_A3<- mean(A4)/mean(A3)

#A1 as Reference Gene
A1_1 <- A1
A2_1 <- A2*RG_Factor_A1_A2*abs((cor(A1,A2)))
A3_1 <- A3*RG_Factor_A1_A3*abs((cor(A1,A3)))
A4_1 <- A4*RG_Factor_A1_A4*abs((cor(A1,A4)))

#A2 as Reference Gene
A1_2 <- A1*RG_Factor_A2_A1*abs((cor(A1,A2)))
A2_2 <- A2
A3_2 <- A3*RG_Factor_A2_A3*abs((cor(A2,A3)))
A4_2 <- A4*RG_Factor_A2_A4*abs((cor(A2,A4)))

#A3 as Reference Gene
A1_3 <- A1*RG_Factor_A3_A1*abs((cor(A1,A3)))
A2_3 <- A2*RG_Factor_A3_A2*abs((cor(A3,A2)))
A3_3 <- A3
A4_3 <- A4*RG_Factor_A3_A4*abs((cor(A3,A4)))

#A4 as Reference Gene
A1_4 <- A1*RG_Factor_A4_A1*abs((cor(A1,A4)))
A2_4 <- A2*RG_Factor_A4_A2*abs((cor(A4,A2)))
A3_4 <- A3*RG_Factor_A4_A3*abs((cor(A4,A3)))
A4_4 <- A4

A1_Normalized <- (A1_1+A1_2+A1_3+A1_4)/4
A2_Normalized <- (A2_1+A2_2+A2_3+A2_4)/4
A3_Normalized <- (A3_1+A3_2+A3_3+A3_4)/4
A4_Normalized <- (A4_1+A4_2+A4_3+A4_4)/4

p = sample(rainbow(10))
  las=2, names=c("Array1","Array2","Array3","Array4",


I feel the key to generalizing your code is to store your variables into a matrix. Then let vectorized functions (colMeans, cor, *, etc.) do their magic:

A <- cbind(A1, A2, A3, A4)

VN_Normalization <- function(A) {
   m  <- colMeans(A)
   RG <- m %o% (1/m)
   scales <- colMeans(RG * abs(cor(A)))
   A_Normalized <- t(t(A) * scales)

   n <- ncol(A)
   i <- seq_len(n)
   labels <- c(sprintf("Array%i", i),
               sprintf("Array%i_Normalized", i))
   boxplot(cbind(A, A_Normalized),
           las = 2, names = labels,
           col = c(rep("white", n), rainbow(n)))  

Please let me know if I missed anything (I assumed A1, A2, etc. were numeric vectors of equal lengths.)

  • \$\begingroup\$ Thanks @flodel, you did not miss anything as that was a valid assumption! Is there a way to store the normalized variables as global variables using the colnames(A)[i] and then pasting _Normalized to the result? For example if A<- cbind(SPY,TLT) I'd like to store SPY_Normalized and TLT_Normalized. I tried this paste(colnames(A)[i], "_Normalized", sep="") <<- A_Normalized[,i] without success. \$\endgroup\$
    – Fred Viole
    May 1 '15 at 13:42
  • 1
    \$\begingroup\$ To answer your exact request, you would need to use the assign function. Later, you would need to use get to access e.g. SNP_Normalized given X <- "SNP": get(paste(X, "Normalized", sep = "_")). This is a really bad approach for many, many reasons. The right way to do things is to keep all your normalized variables in a matrix as well (or a list or a data.frame if you want to modify the code a little). Just add return(A_Normalized) at the end of the function. Call the function as follows: Normalized <- VN_Normalization(A). Then, you will be able to access Normalized[, X]. \$\endgroup\$
    – flodel
    May 2 '15 at 11:15

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.