I want to count the number of instances of some text (or factor level) row wise, across a subset of columns using dplyr.
Here's the input:
> input_df
num_col_1 num_col_2 text_col_1 text_col_2
1 1 4 yes yes
2 2 5 no yes
3 3 6 no <NA>
And here's the desired output:
> output_df
num_col_1 num_col_2 text_col_1 text_col_2 sum_yes
1 1 4 yes yes 2
2 2 5 no yes 1
3 3 6 no <NA> 0
In sum_yes
we have counted the number of "yes" in that row.
I have tried two methods:
Attempted solution 1:
text_cols = c("text_col_1","text_col_2")
df = input_df %>% mutate(sum_yes = rowSums( select(text_cols) == "yes" ), na.rm = TRUE)
Errors with:
Error in mutate_impl(.data, dots) :
Evaluation error: no applicable method for 'select_' applied to an object of class "character".
Attempted solution 2:
text_cols = c("text_col_1","text_col_2")
df = input_df %>% select(text_cols) %>% rowsum("yes", na.rm = TRUE)
Errors with:
Error in rowsum.data.frame(., "yes", na.rm = TRUE) :
incorrect length for 'group'
mutate
and take sum of number of "yes" for each row.library(dplyr)
df %>% mutate(sum_yes = rowSums(.[text_cols] == "yes"))
# num_col_1 num_col_2 text_col_1 text_col_2 sum_yes
#* <int> <int> <fct> <fct> <int>
#1 1 4 yes yes 2
#2 2 5 no yes 1
#3 3 6 no <NA> 0
Inspired from this answer.
rowwise
with c_across
: df %>%
rowwise() %>%
mutate(sum_yes = sum(c_across(all_of(text_cols)) == "yes"))
do
with rowwise
df %>%
rowwise() %>%
do((.) %>% as.data.frame %>%
mutate(sum_yes = sum(.=="yes")))
do
and rowwise
df %>%
select(text_cols) %>%
mutate(sum_yes = rowSums(. == "yes"))
df$sum_yes <- rowSums(df[text_cols] == "yes")
We can also use reduce
with map
library(tidyverse)
df %>%
select(text_cols) %>%
map(~ .x == "yes" & !is.na(.x)) %>%
reduce(`+`) %>%
bind_cols(df, sum_yes = .)
# num_col_1 num_col_2 text_col_1 text_col_2 sum_yes
#1 1 4 yes yes 2
#2 2 5 no yes 1
#3 3 6 no <NA> 0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.