Reputation: 7760
Imagine I have a dataframe called PAD. And I want to add new columns. I need to write many lines like this, (they do rowwise calculations).
PAD[,"MV1"] <- rowMeans(PAD[,1:3], na.rm=TRUE)
PAD[,"MV2"] <- rowMeans(PAD[,4:6], na.rm=TRUE)
PAD[,"MV3"] <- rowMeans(PAD[,7:9], na.rm=TRUE)
PAD[,"MV4"] <- rowMeans(PAD[,10:12], na.rm=TRUE)
PAD[,"MV5"] <- rowMeans(PAD[,13:15], na.rm=TRUE)
PAD[,"MV6"] <- rowMeans(PAD[,16:18], na.rm=TRUE)
PAD[,"MV7"] <- rowMeans(PAD[,19:21], na.rm=TRUE)
PAD[,"MV8"] <- rowMeans(PAD[,22:24], na.rm=TRUE)
or something with my own function
PAD[,"VV1"] <- apply(PAD[,1:3], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV2"] <- apply(PAD[,4:6], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV3"] <- apply(PAD[,7:9], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV4"] <- apply(PAD[,10:12], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV5"] <- apply(PAD[,13:15], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV6"] <- apply(PAD[,16:18], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV7"] <- apply(PAD[,19:21], 1, function(x) min(x), na.rm=TRUE))
PAD[,"VV8"] <- apply(PAD[,22:24], 1, function(x) min(x), na.rm=TRUE))
I know there exist ways to write it all in a single line (or two :) ). Something like a for loop but avoiding the loop, maybe we could call it, vectorized version.
How can I do it? Maybe something starting with paste0(.....) on both sides of the assignement? , or maybe creating a function and passing a vector, but I'm a little bit confused. I don't know if I have to use parse() or eval() or just generate sequences.
As you can see I'll take every N1 (here 3) columns, to calculate and assign it to N2 new ones (here 8).
And another question, is it better to assign it to ?
c(PAD[,"VV1"], PAD[,"VV2"], PAD[,"VV3"], ...)
or to ?
PAD[,"VV1","VV2","VV3"....]
Upvotes: 1
Views: 40
Reputation: 2828
It's two lines:
cols <- split(1:24, rep(1:8, each = 3))
for (i in 1:8) PAD[[paste0("MV", i)]] <- rowMeans(PAD[, cols[[i]]], na.rm = TRUE)
Edit:
If you want to use avoid using the for
loop, you can do this.
cols <- split(1:24, rep(1:8, each = 3))
tmp <- lapply(1:8, function(x) rowMeans(PAD[, cols[[x]]], na.rm = TRUE))
names(tmp) <- paste0("MV", 1:8)
PAD <- cbind(PAD, do.call(cbind, tmp))
Upvotes: 1
Reputation: 33970
for (i in 1:8) {
varname = paste('MV',i,sep='')
PAD[,varname] <- rowMeans(PAD[, (3*n-2):(3*n)], na.rm=TRUE)
}
Yes you can do a two-liner with *apply, it is less legible though.
Upvotes: 2