R dplyr按组条件进行mutate

3

我有一个分组的数据框,想要在条件检查某个列的all()的前提下对该列进行变换。

在这个例子中,我有一个简单的数据框有3列;我按照code列对其进行分组,如果该组的B列全部为NA,我想要复制A列的值,否则保留B列中原来不是NA的值。

输入:

> example <- tibble::tribble(
  ~code, ~A, ~B,
  "1", 0.5, 0.7,
  "1", 0.5, 0.3,
  "1", 0.5, 0.25,
  "2", 0.2, NA,
  "2", 0.8, NA,
  "2", 0.5, NA
)
> example %>% dplyr::group_by(code)
# A tibble: 6 x 3
# Groups:   code [2]
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5  0.7 
2 1       0.5  0.3 
3 1       0.5  0.25
4 2       0.2 NA   
5 2       0.8 NA   
6 2       0.5 NA   

期望的输出:

# A tibble: 6 x 3
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5  0.7 
2 1       0.5  0.3 
3 1       0.5  0.25
4 2       0.2  0.2 
5 2       0.8  0.8 
6 2       0.5  0.5 

我曾尝试使用ifelse()函数,它可以检查all(is.na(B))是否成立,但它的行为与标准不同,并仅从第一个值进行复制。

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    B = ifelse(all(is.na(B)), A, B)
  )
# A tibble: 6 x 3
# Groups:   code [2]
  code      A     B
  <chr> <dbl> <dbl>
1 1       0.5   0.7
2 1       0.5   0.7
3 1       0.5   0.7
4 2       0.2   0.2
5 2       0.8   0.2
6 2       0.5   0.2

给定固定值是可以的。

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    isBna = ifelse(all(is.na(B)), 'y', 'n')
  )
# A tibble: 6 x 4
# Groups:   code [2]
  code      A     B isBna
  <chr> <dbl> <dbl> <chr>
1 1       0.5  0.7  n    
2 1       0.5  0.3  n    
3 1       0.5  0.25 n    
4 2       0.2 NA    y    
5 2       0.8 NA    y    
6 2       0.5 NA    y      

使用 dplyr::if_else() 时,若 AB 的值不是固定的,则会报错。

example %>% 
  dplyr::group_by(code) %>%
  dplyr::mutate(
    B = if_else(all(is.na(B)), A, B)
  )
Error: Problem with `mutate()` input `B`.
x `true` must be length 1 (length of `condition`), not 3.
ℹ Input `B` is `if_else(all(is.na(B)), A, B)`.
ℹ The error occurred in group 1: code = "1".
Run `rlang::last_error()` to see where the error occurred.     

我的实际错误案例与此略有不同。

# sometime like this
Error: Problem with `mutate()` input `xx`.
x `false` must be a logical vector, not a double vector.

# and sometimes like this
Error: Problem with `mutate()` input `xx`.
x `false` must be length 1 (length of `condition`), not 12.

有没有办法在管道链%>%内实现我的目标? 提前致谢。
1个回答

4

使用if/else替代ifelse,因为all返回长度为1的输出,而ifelse会返回与输入相同长度的输出,因此会在整个组中循环使用第一个元素。

library(dplyr)

example %>% 
  group_by(code) %>%
  mutate(B = if(all(is.na(B))) A else B))

#   code    A     B
#  <chr> <dbl> <dbl>
#1 1       0.5  0.7 
#2 1       0.5  0.3 
#3 1       0.5  0.25
#4 2       0.2  0.2 
#5 2       0.8  0.8 
#6 2       0.5  0.5 

谢谢你的解决方案!我感到有点好笑,我怎么会忽略了这个简单的“if”语句。 - alperceire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接