Harry
Harry

Reputation: 65

R apply and for loop calculation

Would someone be able to explain why this apply doesn't work correctly? I wanted to normalise all the values in each row by the sum of the values in each row - such that the sum of each row =1 However, when I did this using an apply function, the answer is incorrect.

data <- data.frame(Sample=c("A","B","C"),val1=c(1235,34567,234346),val2=c(3445,23446,234235),val3=c(457643,234567,754234))

norm <- function(x){
  x/sum(x)}

applymeth <- data
applymeth[,2:4] <- apply(applymeth[,2:4], 1, norm)
rowSums(applymeth[,2:4])

loopmeth <- data
for(i in 1:nrow(data)){
  loopmeth[i,2:4] <- norm(loopmeth[i,2:4])
}
rowSums(loopmeth[,2:4])

Thanks.

Upvotes: 0

Views: 53

Answers (1)

jogo
jogo

Reputation: 12559

apply() gives you (in the result) a matrix column by column - in your case from a row-by-row input. You have to transpose the result:

applymeth <- data
applymeth[,2:4] <- t(apply(applymeth[,2:4], 1, norm))
rowSums(applymeth[,2:4])

Have a look at

apply(matrix(1:12, 3), 1, norm)

The reason for this result of apply() is a convention:
in a matrix or a multidimensional array the index of the first dimension is running first, then the second and so on. Example:

array(1:12, dim=c(2,2,3))

So (without any reorganisation of the data) apply() produces one column after the other. This behavior not depends on the parameter MARGIN= of the function apply().

Upvotes: 1

Related Questions