How to normalize model.matrix?

# first, create your data.frame
mydf <- data.frame(a = c(1,2,3), b = c(1,2,3), c = c(1,2,3))

# then, create your model.matrix
mym <- model.matrix(as.formula("~ a + b + c"), mydf)

# how can I normalize the model.matrix?

      

Currently I need to convert my model.matrix back to data.frame in order to run my normalization function:

normalize <- function(x) { return ((x - min(x)) / (max(x) - min(x))) }
m.norm <- as.data.frame(lapply(m, normalize))

      

Anyway, to avoid this step by just normalizing the model.matrix?

+3


source to share


3 answers


You can normalize each column without converting to a dataframe using the function apply

:

apply(mym, 2, normalize)
#   (Intercept)   a   b   c
# 1         NaN 0.0 0.0 0.0
# 2         NaN 0.5 0.5 0.5
# 3         NaN 1.0 1.0 1.0

      



You probably really want to leave the interception intact, with something like:

cbind(mym[,1,drop=FALSE], apply(mym[,-1], 2, normalize))
#   (Intercept)   a   b   c
# 1           1 0.0 0.0 0.0
# 2           1 0.5 0.5 0.5
# 3           1 1.0 1.0 1.0

      

+3


source


Another option is to vectorize this using a very useful package matrixStats

(although TBH is apply

usually very efficient for matrices as well and applies to columns). This way you can also keep your original data structure



library(matrixStats)
Max <- colMaxs(mym[, -1]) 
Min <- colMins(mym[, -1])
mym[, -1] <- (mym[, -1] - Min)/(Max - Min)
mym
#   (Intercept)   a   b   c
# 1           1 0.0 0.0 0.0
# 2           1 0.5 0.5 0.5
# 3           1 1.0 1.0 1.0
# attr(,"assign")
# [1] 0 1 2 3

      

+3


source


If you want to "normalize" in one sense, you can simply use a function scale

that centers and sets std.dev to 1.

> scale( mym )
  (Intercept)  a  b  c
1         NaN -1 -1 -1
2         NaN  0  0  0
3         NaN  1  1  1
attr(,"assign")
[1] 0 1 2 3
attr(,"scaled:center")
(Intercept)           a           b           c 
          1           2           2           2 
attr(,"scaled:scale")
(Intercept)           a           b           c 
          0           1           1           1 
> mym
  (Intercept) a b c
1           1 1 1 1
2           1 2 2 2
3           1 3 3 3
attr(,"assign")
[1] 0 1 2 3

      

As you can see, it doesn't really make sense to "normalize" the entire model matrix when the term "Intercept" is present. So you could do this:

> mym[ , -1 ] <- scale( mym[,-1] )
> mym
  (Intercept)  a  b  c
1           1 -1 -1 -1
2           1  0  0  0
3           1  1  1  1
attr(,"assign")
[1] 0 1 2 3

      

This is actually a model matrix that will be displayed if the default contrast is set to "contr.sum" and the columns are the factor type. It is only accepted as an "internal-

> mym <- model.matrix(as.formula("~ a + b + c"), mydf, contrasts.arg=list(a="contr.sum"))
Error in `contrasts<-`(`*tmp*`, value = contrasts.arg[[nn]]) : 
  contrasts apply only to factors
> mydf <- data.frame(a = factor(c(1,2,3)), b = c(1,2,3), c = c(1,2,3))
> mym <- model.matrix(as.formula("~ a + b + c"), mydf, contrasts.arg=list(a="contr.sum"))
> mym
  (Intercept) a1 a2 b c
1           1  1  0 1 1
2           1  0  1 2 2
3           1 -1 -1 3 3
attr(,"assign")
[1] 0 1 1 2 3
attr(,"contrasts")
attr(,"contrasts")$a
[1] "contr.sum"

      

+2


source







All Articles