Add row to a data frame with total sum for each column
Do you need the Language column in your data, or is it more appropriate to think of that column as the row.names
? That would change your data.frame from 4 observations of 3 variables to 4 observations of 2 variables (Files & LOC).
x <- data.frame(Files = c(4009, 210, 35), LOC = c(15328,876, 200),
row.names = c("C++", "Java", "Python"), stringsAsFactors = FALSE)
x["Total" ,] <- colSums(x)
> x
Files LOC
C++ 4009 15328
Java 210 876
Python 35 200
Total 4254 16404
Here's a way that gets you what you want, but there may very well be a more elegant solution.
rbind(x, data.frame(Language = "Total", t(colSums(x[, -1]))))
For the record, I prefer Chase's answer if you don't absolutely need the Language
column.
A tidyverse
way to do this would be to use bind_rows
(or eventually add_row
) and summarise
to compute the sums. Here the issue is that we want sums for all but one, so a trick would be:
summarise_all(x, ~if(is.numeric(.)) sum(.) else "Total")
In one line:
x %>%
bind_rows(summarise_all(., ~if(is.numeric(.)) sum(.) else "Total"))
Edit with dplyr >=1.0
One can also use across()
, which is slightly more verbose in this case:
x %>%
bind_rows(summarise(.,
across(where(is.numeric), sum),
across(where(is.character), ~"Total")))
See adorn_totals()
from the janitor package:
library(janitor)
x %>%
adorn_totals("row")
#> Language Files LOC
#> C++ 4009 15328
#> Java 210 876
#> Python 35 200
#> Total 4254 16404
The numeric columns remain of class numeric.
Disclaimer: I created this package, including adorn_totals()
which is made for precisely this task.