Diego Trindade
Diego Trindade

Reputation: 95

Omitting columns instead of dropping them in purrr

I need to calculate an index for multiple lists. However, I can only do this if I drop some columns (here represented by "w" and "x"). For ex.

library(tidyverse)
lists<- list(
  l1=tribble(
  ~w, ~x, ~y, ~z,
  #--|--|--|----
  12, "a", 2, 1,
  12, "a",5, 3,
  12, "a",6, 2),

  l2=tribble(
    ~w, ~x, ~y, ~z,
    #--|--|--|----
    13,"b", 5, 7,
    13,"b", 4, 6,
    13,"b", 3, 2)) 
lists %>% 
  map(~ .x %>%  
        #group_by(w,x) %>% 
        select(-w,-x) %>%  
        mutate(row_sums = rowSums(.)))

Instead of dropping those columns I would like to keep/omit them and calculate the index only for "y" and "z".

I manage to do this by first extracting those columns and binding them again afterward. For ex.

select.col<-lists %>% 
  map_dfr(~ .x %>% 
            select(w,x))

lists %>% 
  map_dfr(~ .x %>%  
        select(-w,-x) %>%  
        mutate(row_sums = rowSums(.))) %>% 
        bind_cols(select.col)

However, this is not so elegant and I had to bind the lists (map_dfr), I would like to keep them as a list though.

Probably, another approach would be to use select_if(., is.numeric), but as I have some numeric columns I need to omit, I'm not sure whether this is the best option.

I'm certain there is a simple solution to this problem. Can anyone take a look at it?

Upvotes: 3

Views: 219

Answers (2)

akrun
akrun

Reputation: 887531

Here is a tidyverse approach to get the row sums

library(tidyverse)
lists %>% 
    map(~ .x %>%
            mutate(row_sums = select(., y:z) %>% 
                   reduce(`+`)))
#$l1
# A tibble: 3 x 5
#      w x         y     z row_sums
#  <dbl> <chr> <dbl> <dbl>    <dbl>
#1    12 a         2     1        3
#2    12 a         5     3        8
#3    12 a         6     2        8

#$l2
# A tibble: 3 x 5
#      w x         y     z row_sums
#  <dbl> <chr> <dbl> <dbl>    <dbl>
#1    13 b         5     7       12
#2    13 b         4     6       10
#3    13 b         3     2        5

Or using base R

lapply(lists, transform, row_sums = y + z)

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 389155

Instead of dropping the columns, you can select the columns for which you want to take the sum.

You can select by name

library(dplyr)
library(purrr)

lists %>% map(~ .x %>% mutate(row_sums = rowSums(.[c("y", "z")])))


#$l1
# A tibble: 3 x 5
#      w x         y     z row_sums
#  <dbl> <chr> <dbl> <dbl>    <dbl>
#1    12 a         2     1        3
#2    12 a         5     3        8
#3    12 a         6     2        8

#$l2
# A tibble: 3 x 5
#      w x         y     z row_sums
#  <dbl> <chr> <dbl> <dbl>    <dbl>
#1    13 b         5     7       12
#2    13 b         4     6       10
#3    13 b         3     2        5

Or also by position of columns

lists %>% map(~ .x %>%  mutate(row_sums = rowSums(.[3:4])))

Upvotes: 3

Related Questions