San
San

Reputation: 183

How to count logical values through multiple columns in R?

My goal is to count the total number of tasks each person (variable = name) has done. One person can do only one task per day.

My dataset looks like this:

name  task1 task2 task3 day
bill  TRUE  FALSE FALSE  1
bill  FALSE TRUE  FALSE  2
bill  FALSE FALSE FALSE  3
bill  NA    NA    NA     4
alex  FALSE FALSE FALSE  1
alex  TRUE  FALSE FALSE  2
alex  FALSE FALSE FALSE  3
alex  NA    NA     NA    4
rob   TRUE  FALSE FALSE  1
rob   TRUE  FALSE FALSE  2
rob   TRUE  FALSE FALSE  3
rob   NA    NA    NA     4

This is the output that I need:

name  total
bill   2
alex   1    
rob    3

My code: (As you can see I can summarise the number of tasks, but the output is still far away from what I need)

total <- sum1%>%
group_by(`name`)%>%
summarise(task1_processed=sum(task11, na.rm = TRUE), task2_processed = sum(task2, na.rm = TRUE),
               task3_processed = sum(task3, na.rm = TRUE))

Upvotes: 3

Views: 1235

Answers (4)

ThomasIsCoding
ThomasIsCoding

Reputation: 101608

A data.table option

setDT(df)[, .(total = sum(na.omit(unlist(.SD)))), name, .SDcols = patterns("^task")]

gives

   name total
1: bill     2
2: alex     1
3:  rob     3

Upvotes: 0

Waldi
Waldi

Reputation: 41220

You could use c_across to sum logical values across all columns:

library(dplyr)

df %>% group_by(name) %>% 
       summarize(total = sum(c_across(where(is.logical)), na.rm = TRUE)) %>%
       ungroup

  name  total
  <chr> <int>
1 alex      1
2 bill      2
3 rob       3

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

For each name you can sum the 'task' columns together.

library(dplyr)
df %>%
  group_by(name) %>%
  summarise(total = sum(unlist(select(cur_data(), starts_with('task'))), na.rm = TRUE))

#   name  total
#* <chr> <int>
#1 alex      1
#2 bill      2
#3 rob       3

Upvotes: 2

tmfmnk
tmfmnk

Reputation: 39858

One option could be:

df %>%
    group_by(name) %>%
    summarise(n = sum(unlist(across(starts_with("task"))), na.rm = TRUE))

  name      n
* <chr> <int>
1 alex      1
2 bill      2
3 rob       3

Or:

df %>%
    group_by(name) %>%
    summarise(n = sum(Reduce(`+`, across(starts_with("task"))), na.rm = TRUE))

Upvotes: 1

Related Questions