I have 5 columns of numeric data (m1,m2,m3,m4,m5) and I want to generate a new column with the mean value of all the m's in the same row. That is:
(m1 + m2 + m3 + m4 + m5)/5
I have a problem with the management of NA values: I want the mean value to be NA if, and only if, all the individual values of the m's are NA. But, if I use na.rm, then NA's are substituted by zeroes and no NA is in the column of means. On the other hand, if I don't use na.rm, the column of means is NA if ANY of the m's is NA.
I have done the following:
m <- rowSums(data.frame(m1,m2,m3,m4,m5)/5, na.rm=TRUE)
for (i in 1:length(m)) {
if ( all(is.na(c(m1[i],m2[i],m3[i],m4[i],m5[i])))) {
m[i] <- NA
}
}
It works, but I'm almost sure that R can do it in a better way. How can it be done without loops?
Maybe the question sounds a little bit trivial. Sorry for that, but I am new in R.
Thanks in advance.
Use rowMeans instead of rowSums :
Df <- data.frame(
m1 = c(NA,1:10,NA),
m2 = c(10:5,NA,4:1,NA),
m3 = c(11,12,NA,13:20,NA)
)
rowMeans(Df,na.rm=T)
[1] 10.500000 7.333333 5.000000 7.666667 8.000000 8.333333 11.000000
9.333333 9.666667 10.000000 10.333333 NA
The answer is quite simple and you'll kick yourself when I reveal all ;-)
First a reproducible example:
set.seed(1)
dat <- matrix(runif(100*5), ncol = 5)
## add some random NA
dat[sample(NROW(dat) * NCOL(dat), 100)] <- NA
dat <- data.frame(dat)
names(dat) <- paste("m", 1:5, sep = "")
## make 1 row all NA
dat[10, ] <- rep(NA, NCOL(dat))
The solution is to use rowMeans()
not rowSums()
:
> rowMeans(dat, na.rm = TRUE)
[1] 0.5040661 0.2447789 0.5785721 0.6552587 0.5000273 0.6553183
[7] 0.5017969 0.5961018 0.3778305 NA 0.7843261 0.3118411
[13] 0.6023241 0.7230658 0.4849793 0.3579792 0.5321065 0.5891246
[19] 0.5985094 0.6450797 0.5884122 0.3308921 0.4659702 0.3595603
[25] 0.6291160 0.5420563 0.3555441 0.3922415 0.4554090 0.6912613
[31] 0.5849739 0.1436432 0.3363359 0.5620860 0.4845476 0.6243143
[37] 0.6453576 0.3102552 0.6801590 0.5730385 0.6595771 0.4125847
[43] 0.5950305 0.3908888 0.5228980 0.4290490 0.3219740 0.4941847
[49] 0.3203416 0.6077816 0.6725149 0.6037703 0.4706785 0.3780164
[55] 0.2773157 0.2887002 0.5679866 0.5216224 0.4181383 0.4182203
[61] 0.3985725 0.4043380 0.3024113 0.5441925 0.6163834 0.5365182
[67] 0.3324975 0.5444736 0.6809868 0.5073465 0.4122997 0.6164483
[73] 0.4803133 0.3044119 0.2990064 0.5280371 0.5925953 0.6079630
[79] 0.5144217 0.7415579 0.4059379 0.3966217 0.7344768 0.7502413
[85] 0.4064067 0.2837371 0.6139601 0.3669062 0.5450748 0.4665940
[91] 0.3618159 0.4623254 0.5885807 0.4686613 0.4246080 0.6322250
[97] 0.2747088 0.4716259 0.4306550 0.1015050
Compare the entry for row 10 using both approaches:
> rowMeans(dat, na.rm = TRUE)[10]
[1] NA
> rowSums(dat/5, na.rm = TRUE)[10]
[1] 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With