我如何在 `mutate_at` 中应用一个函数来对其他列中的值进行逐行条件处理?

ulf*_*der 2 r dplyr mutate rowwise

我有一个数据框,我想在其中转换一组列的值,条件是同一行中另一组列中的值。我想,未能做到这一点在tidyverse与组合rowwisemutate_at。这是一个可重现的示例。

library(dplyr)

set.seed(20912)
dat <- data.frame(cat1 = sample(LETTERS[1:2], 10, replace = TRUE), cat2 = sample(LETTERS[1:2], 10, replace = TRUE), id = 3, sim_1 = rnorm(10), sim_2 = rnorm(10), stringsAsFactors = FALSE)

> dat
   cat1 cat2 id      sim_1       sim_2
1     A    A  3 -0.1054062 -0.47563580
2     B    A  3 -1.7198921  0.76713640
3     A    B  3 -0.5946627 -0.33958464
4     B    B  3 -1.6547488 -0.13026564
5     B    B  3 -0.3779149  1.29590315
6     B    B  3  0.6271939  0.08707965
7     B    B  3  1.6376711  1.02151753
8     A    B  3  1.7675520  1.66983954
9     B    A  3 -0.3284081 -1.28175621
10    B    B  3  0.8431148 -0.15415091
Run Code Online (Sandbox Code Playgroud)

在该表中,我想转换以 开头的所有列"sim_"的值,条件是cat1和的值cat2。举例来说,我想用 替换所有"sim_*"列中的值NA,但只在cat1 == cat2. 所以我的预期结果是:

   cat1 cat2 id      sim_1      sim_2
1     A    A  3         NA         NA
2     B    A  3 -1.7198921  0.7671364
3     A    B  3 -0.5946627 -0.3395846
4     B    B  3         NA         NA
5     B    B  3         NA         NA
6     B    B  3         NA         NA
7     B    B  3         NA         NA
8     A    B  3  1.7675520  1.6698395
9     B    A  3 -0.3284081 -1.2817562
10    B    B  3         NA         NA
Run Code Online (Sandbox Code Playgroud)

我尝试了一些关于rowwiseplus主题的变体,但mutate_at没有运气。例如:

> dat %>% rowwise() %>% mutate_at(vars(starts_with("sim_")), function(x) { ifelse(cat1 == cat2, NA, x) })
Error in ifelse(cat1 == cat2, x, 0) : object 'cat1' not found
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我意识到如果我首先将数据从宽到长tidyverse重新整形会更容易,但我希望了解有关函数或语法的知识,并找到一种无需重新整形数据的方法。

akr*_*run 5

我们可以使用replaceifelse/replace进行矢量化,因此可以避免rowwise

library(dplyr)
dat %>%
   mutate_at(vars(starts_with('sim')), ~ replace(., cat1 == cat2, NA_real_))
Run Code Online (Sandbox Code Playgroud)

或者因为这些是数字列,可以直接进行转换

dat %>% 
   mutate_at(vars(starts_with('sim')),  ~.* NA^(cat1 == cat2))
Run Code Online (Sandbox Code Playgroud)