dplyr mutate ifelse 语句中的 gsub 返回第一个项目而不是选定的项目
gsub in dplyr mutate ifelse statement returning first item rather than selected items
我想 运行 有选择地进行变异,给定可变输入。然后 mutate 需要 运行 chr 列上的 gsub。例如:
thing <- "yes"
starwars %>% mutate(homeworld =
ifelse(thing == "yes",
gsub("oo", "_", homeworld),
homeworld)) %>%
select(name, homeworld)
上面代码中的 gsub 似乎对 homeworld 的第一项执行替换,并将所有 homeworld 值替换为:
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Tat_ine
4 Darth Vader Tat_ine
我期望的时间:
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
如果我不包含 ifelse 语句,这会起作用:
starwars %>% mutate(homeworld = gsub("oo", "_", homeworld))
使用rowwise
thing <- "yes"
starwars %>%
rowwise() %>%
mutate(homeworld =
ifelse(thing == "yes",
gsub("oo", "_", homeworld),
homeworld)) %>%
select(name, homeworld) %>%
ungroup()
# A tibble: 87 x 2
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
5 Leia Organa Alderaan
6 Owen Lars Tat_ine
7 Beru Whitesun lars Tat_ine
备注
这个问题已经被诊断出来 。
问题
ifelse()
returns a value with the same shape as test
.
因为 test
是 (logical
) 标量 thing == "yes"
thing == "yes"
# [1] TRUE
那么你的 ifelse()
returns 只有 (character
) 标量 "Tat_ine"
ifelse(thing == "yes", gsub("oo", "_", starwars$homeworld), starwars$homeworld)
# [1] "Tat_ine"
它在整个 homeworld
列中作为常量循环使用。
解决方案
您可以执行rowwise()
操作(使用dplyr
),如 by Yuriy Saraykin所述,或者您可以使用[=]有效地矢量化您的条件25=]:
thing <- "yes"
starwars %>% mutate(homeworld = case_when(thing == "yes" ~ gsub("oo", "_", homeworld),
TRUE ~ homeworld)) %>%
select(name, homeworld)
结果(如下所示)应符合您的预期:
# A tibble: 87 x 2
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
5 Leia Organa Alderaan
6 Owen Lars Tat_ine
7 Beru Whitesun lars Tat_ine
8 R5-D4 Tat_ine
9 Biggs Darklighter Tat_ine
10 Obi-Wan Kenobi Stewjon
# ... with 77 more rows
我想 运行 有选择地进行变异,给定可变输入。然后 mutate 需要 运行 chr 列上的 gsub。例如:
thing <- "yes"
starwars %>% mutate(homeworld =
ifelse(thing == "yes",
gsub("oo", "_", homeworld),
homeworld)) %>%
select(name, homeworld)
上面代码中的 gsub 似乎对 homeworld 的第一项执行替换,并将所有 homeworld 值替换为:
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Tat_ine
4 Darth Vader Tat_ine
我期望的时间:
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
如果我不包含 ifelse 语句,这会起作用:
starwars %>% mutate(homeworld = gsub("oo", "_", homeworld))
使用rowwise
thing <- "yes"
starwars %>%
rowwise() %>%
mutate(homeworld =
ifelse(thing == "yes",
gsub("oo", "_", homeworld),
homeworld)) %>%
select(name, homeworld) %>%
ungroup()
# A tibble: 87 x 2
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
5 Leia Organa Alderaan
6 Owen Lars Tat_ine
7 Beru Whitesun lars Tat_ine
备注
这个问题已经被诊断出来
问题
ifelse()
returns a value with the same shape astest
.
因为 test
是 (logical
) 标量 thing == "yes"
thing == "yes"
# [1] TRUE
那么你的 ifelse()
returns 只有 (character
) 标量 "Tat_ine"
ifelse(thing == "yes", gsub("oo", "_", starwars$homeworld), starwars$homeworld)
# [1] "Tat_ine"
它在整个 homeworld
列中作为常量循环使用。
解决方案
您可以执行rowwise()
操作(使用dplyr
),如
thing <- "yes"
starwars %>% mutate(homeworld = case_when(thing == "yes" ~ gsub("oo", "_", homeworld),
TRUE ~ homeworld)) %>%
select(name, homeworld)
结果(如下所示)应符合您的预期:
# A tibble: 87 x 2
name homeworld
<chr> <chr>
1 Luke Skywalker Tat_ine
2 C-3PO Tat_ine
3 R2-D2 Nab_
4 Darth Vader Tat_ine
5 Leia Organa Alderaan
6 Owen Lars Tat_ine
7 Beru Whitesun lars Tat_ine
8 R5-D4 Tat_ine
9 Biggs Darklighter Tat_ine
10 Obi-Wan Kenobi Stewjon
# ... with 77 more rows