2

我有一个数据框,我想在其中转换一组列的值,条件是同一行中另一组列中的值。我正在尝试使用 和 的组合来做到这一点,但未能做到这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

在该表中,我想转换所有以 开头的列的"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

我尝试了一些关于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

我错过了什么?我意识到,如果我首先将数据从宽到长重塑,这会更容易,但我希望学习一些有关tidyverse函数或语法的知识,并找到一种方法来做到这一点,而无需重塑数据。

4

1 回答 1

5

我们可以使用replaceifelse/replace被向量化,所以可以避免rowwise

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

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

dat %>% 
   mutate_at(vars(starts_with('sim')),  ~.* NA^(cat1 == cat2))
于 2020-02-06T19:31:58.543 回答