Is there a way to use rowSums and is.numeric to only sum numeric columns?

Viewed 1586

A quick question with hopefully a quick answer.

I was trying to use rowSums only on columns that had numeric data. I want to do something equivalent to this (using the built-in data set CO2 for a reproducible example):

# Reproducible example  
CO2 %>%
  mutate( Total = rowSums(.[c(-1, -2, -3)]) ) %>% 
  head()

  Plant   Type  Treatment conc uptake Total
1   Qn1 Quebec nonchilled   95   16.0 111.0
2   Qn1 Quebec nonchilled  175   30.4 205.4
3   Qn1 Quebec nonchilled  250   34.8 284.8
4   Qn1 Quebec nonchilled  350   37.2 387.2
5   Qn1 Quebec nonchilled  500   35.3 535.3
6   Qn1 Quebec nonchilled  675   39.2 714.2

I tried rowSums with mutate and is.numeric, but no success. Is there an easy way to do this?

# How do sum rows using is.numeric (below does not work)?                 
CO2 %>%
  mutate( Total = rowSums(., is.numeric(.)) )
2 Answers

We can use select_if with rowSums

library(dplyr)
CO2 %>% 
    mutate(Total = rowSums(select_if(., is.numeric), na.rm = TRUE)) %>%
    head
#  Plant   Type  Treatment conc uptake Total
#1   Qn1 Quebec nonchilled   95   16.0 111.0
#2   Qn1 Quebec nonchilled  175   30.4 205.4
#3   Qn1 Quebec nonchilled  250   34.8 284.8
#4   Qn1 Quebec nonchilled  350   37.2 387.2
#5   Qn1 Quebec nonchilled  500   35.3 535.3
#6   Qn1 Quebec nonchilled  675   39.2 714.2

the select_if solution is great! you can also expand on it with pmap_dbl if you want to quickly sub in row-wise functions other than sum.

library(tidyverse) # install.packages("tidyverse")

CO2 <- tribble(
  ~Plant,    ~Type,   ~Treatment, ~conc, ~uptake,
   "Qn1", "Quebec", "nonchilled",   95L,      16,
   "Qn1", "Quebec", "nonchilled",  175L,    30.4,
   "Qn1", "Quebec", "nonchilled",  250L,    34.8,
   "Qn1", "Quebec", "nonchilled",  350L,    37.2,
   "Qn1", "Quebec", "nonchilled",  500L,    35.3,
   "Qn1", "Quebec", "nonchilled",  675L,    39.2
  )

# creating a row-sum column
CO2 %>%
  mutate(total = pmap_dbl(select_if(., is.numeric), sum, na.rm = TRUE))

# alternatively, creating a row-minimum column
CO2 %>%
  mutate(min_val = pmap_dbl(select_if(., is.numeric), min, na.rm = TRUE))
Related