Reputation: 533
aaa<-data.frame(group=c("A","B"),x1=c(2,8),x2=c(8,2),total=c(10,10),stringsAsFactors=FALSE)
Now I want to compute row percent as new row below freqency row. New dataframe like:
group x1 x2 total
A 2 8 10
% 20.00 80.00
B 8 2
% 80.00 20.00 10
How to do it in R? Thank you!
Upvotes: 2
Views: 558
Reputation: 99331
In future questions, please show that you've made at least minimal effort to solve the problem yourself.
Here are two ways that use lapply
. The second was added later in an edit because it is much simpler that the first, and probably much faster.
> newD <- do.call(rbind, lapply(seq(nrow(aaa)), function(i){
x1 <- 100*(aaa$x1[i]/aaa$total[i])
x2 <- 100*(aaa$x2[i]/aaa$total[i])
rbind(aaa[i, ], c('%', x1, x2, ''))
}))
> rownames(newD) <- seq(nrow(newD))
> newD
# group x1 x2 total
# 1 A 2 8 10
# 2 % 20 80
# 3 B 8 2 10
# 4 % 80 20
The second, much better lapply
method:
> pct <- cbind(group = '%', 100*aaa[2:3]/aaa$total, total = '')
> do.call(rbind, lapply(seq(nrow(aaa)), function(i){ rbind(aaa[i,], pct[i,]) }))
## group x1 x2 total
## 1 A 2 8 10
## 2 % 20 80
## 22 B 8 2 10
## 21 % 80 20
Added, per your comment: A for
loop method
> x1 <- x2 <- numeric(nrow(aaa))
> rb <- vector('list', nrow(aaa)/2)
> for(i in seq(nrow(aaa))){
x1[i] <- 100*(aaa$x1[i]/aaa$total[i])
x2[i] <- 100*(aaa$x2[i]/aaa$total[i])
rb[[i]] <- rbind(aaa[i, ], c('%', x1[i], x2[i], ''))
}
> do.call(rbind, rb)
# group x1 x2 total
# 1 A 2 8 10
# 2 % 20 80
# 22 B 8 2 10
# 21 % 80 20
Upvotes: 3