Reputation: 463
I would like to fill a column conditionally using dplyr::mutate. One level of the new variable should correspond to if a value was present at all in the previous column and the other level is an 'else' condition.
I have a dataframe:
group piece answer agreement
group1 A noise good
group1 A silence good
group1 A silence good
group1 B silence bad
group1 B loud_noise bad
group1 B noise bad
group1 B loud_noise bad
group1 B noise bad
group2 C silence good
group2 C silence good
I want to create a new variable grouping by group where if 'bad' appears in 'agreement', then the value should be 'inconsistent' but if all of the values of 'agreement' are 'good', then the value should be 'consistent.'
group piece answer agreement new_agreement
group1 A noise good bad
group1 A silence good bad
group1 A silence good bad
group1 B silence bad bad
group1 B loud_noise bad bad
group1 B noise bad bad
group1 B loud_noise bad bad
group1 B noise bad bad
group2 C silence good good
group2 C silence good good
But case_when doesn't quite do that - it's just copying the same variable over again:
newdf <- df %>%
group_by(group) %>%
mutate(new_agreement = case_when(agreement == 'bad' ~
"inconsistent", agreement =='good' ~ "consistent")) %>%
as.data.frame()
Upvotes: 3
Views: 977
Reputation: 61154
Just add any(agreement == 'bad')
df %>%
group_by(group) %>%
mutate(new_agreement = case_when(any(agreement == 'bad') ~"inconsistent",
agreement =='good' ~ "consistent"))
# A tibble: 10 x 5
# Groups: group [2]
group piece answer agreement new_agreement
<fct> <fct> <fct> <fct> <chr>
1 group1 A noise good inconsistent
2 group1 A silence good inconsistent
3 group1 A silence good inconsistent
4 group1 B silence bad inconsistent
5 group1 B loud_noise bad inconsistent
6 group1 B noise bad inconsistent
7 group1 B loud_noise bad inconsistent
8 group1 B noise bad inconsistent
9 group2 C silence good consistent
10 group2 C silence good consistent
You can even use if_else
with any
:
df %>%
group_by(group) %>%
mutate(new_agreement= if_else(any(agreement=="bad"), "inconsistent", "consistent") )
Upvotes: 3
Reputation: 76402
With case_when
, use any
.
library(dplyr)
df %>%
group_by(group) %>%
mutate(new_agreement = case_when(
any(agreement == 'bad') ~ 'inconsistent',
TRUE ~ 'consistent'))
## A tibble: 10 x 5
## Groups: group [2]
# group piece answer agreement new_agreement
# <fct> <fct> <fct> <fct> <chr>
# 1 group1 A noise good inconsistent
# 2 group1 A silence good inconsistent
# 3 group1 A silence good inconsistent
# 4 group1 B silence bad inconsistent
# 5 group1 B loud_noise bad inconsistent
# 6 group1 B noise bad inconsistent
# 7 group1 B loud_noise bad inconsistent
# 8 group1 B noise bad inconsistent
# 9 group2 C silence good consistent
#10 group2 C silence good consistent
Data in dput
format.
df <-
structure(list(group = structure(c(1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 2L, 2L), .Label = c("group1", "group2"),
class = "factor"), piece = structure(c(1L, 1L, 1L, 2L,
2L, 2L, 2L, 2L, 3L, 3L), .Label = c("A", "B", "C"),
class = "factor"), answer = structure(c(2L, 3L, 3L,
3L, 1L, 2L, 1L, 2L, 3L, 3L), .Label = c("loud_noise",
"noise", "silence"), class = "factor"), agreement =
structure(c(2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L),
.Label = c("bad", "good"), class = "factor")),
class = "data.frame", row.names = c(NA, -10L))
Upvotes: 0