mel*_*bez 3 if-statement r conditional-statements dplyr tidyverse
我在 R 中有一个数据框,如下所示:
a b c condition
1 4 2 acap
2 3 1 acap
2 4 3 acap
5 6 8 ncap
5 7 6 ncap
8 7 6 ncap
Run Code Online (Sandbox Code Playgroud)
我正在尝试重新编码 a、b 和 c 列中的值以用于条件 ncap(以及此处未显示的 2 个其他条件),同时单独保留 acap 的值。
以下代码适用于前 3 列。我试图弄清楚如何将它仅应用于我按条件指定的行,同时将所有内容保留在同一数据框中。
df = df %>%
mutate_at(vars(a:c), function(x)
case_when x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)
Run Code Online (Sandbox Code Playgroud)
这是预期的输出。
a b c condition
1 4 2 acap
2 3 1 acap
2 4 3 acap
1 2 4 ncap
1 3 2 ncap
4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)
我四处寻找这个问题的答案,但找不到。如果有人知道已经存在的答案,我会很感激被引导到它。
我们可以使用iecase_when创建的条件,row_number如果行号是 4 到 6,则从值中减去 4 或返回值
df %>%
mutate_at(vars(a:c), funs(case_when(row_number() %in% 4:6 ~ . - 4L,
TRUE ~ .)))
# a b c condition
#1 1 4 2 acap
#2 2 3 1 acap
#3 2 4 3 acap
#4 1 2 4 ncap
#5 1 3 2 ncap
#6 4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)
如果这是基于值而不是行,则在值上创建条件
df %>%
mutate_at(vars(a:c), funs(case_when(. %in% 5:8 ~ . - 4L,
TRUE ~ .)))
# a b c condition
#1 1 4 2 acap
#2 2 3 1 acap
#3 2 4 3 acap
#4 1 2 4 ncap
#5 1 3 2 ncap
#6 4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)
或者,如果它基于“条件”中的值
df %>%
mutate_at(vars(a:c), funs(case_when(condition == 'ncap' ~ . - 4L,
TRUE ~ .)))
Run Code Online (Sandbox Code Playgroud)
或者不使用任何 case_when
df %>%
mutate_at(vars(a:c), funs( . - c(0, 4)[(condition == 'ncap')+1]))
# a b c condition
#1 1 4 2 acap
#2 2 3 1 acap
#3 2 4 3 acap
#4 1 2 4 ncap
#5 1 3 2 ncap
#6 4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)
在 中base R,我们可以通过创建索引来做到这一点
i1 <- df$condition =='ncap'
df[i1, 1:3] <- df[i1, 1:3] - 4
Run Code Online (Sandbox Code Playgroud)
df <- structure(list(a = c(1L, 2L, 2L, 5L, 5L, 8L), b = c(4L, 3L, 4L,
6L, 7L, 7L), c = c(2L, 1L, 3L, 8L, 6L, 6L), condition = c("acap",
"acap", "acap", "ncap", "ncap", "ncap")), class = "data.frame",
row.names = c(NA, -6L))
Run Code Online (Sandbox Code Playgroud)
您可以使用filter将重新编码值仅应用于特定行(此处不等于“acap”)
library(dplyr)
df %>%
filter(condition != "acap") %>%
mutate_at(vars(a:c), function(x)
case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4))
# a b c condition
#1 1 2 4 ncap
#2 1 3 2 ncap
#3 4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)
如果您再次需要整个数据框,我们可以这样做
df %>%
filter(condition == "acap") %>%
bind_rows(df %>%
filter(condition != "acap") %>%
mutate_at(vars(a:c), function(x)
case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)))
# a b c condition
#1 1 4 2 acap
#2 2 3 1 acap
#3 2 4 3 acap
#4 1 2 4 ncap
#5 1 3 2 ncap
#6 4 3 2 ncap
Run Code Online (Sandbox Code Playgroud)