【问题标题】:Dplyr across + mutate + condition to select the columnsDplyr cross + mutate + condition 选择列
【发布时间】:2020-10-27 13:20:07
【问题描述】:

我确信解决方案是单线,但我正在用头撞墙。 请参阅帖子末尾的非常短的代表;如何告诉 dplyr 我只想将没有 NA 的列加倍?

非常感谢

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union


df <- tibble(x=1:10, y=101:110,
             w=c(6,NA,4,NA, 5,0,NA,4,8,17 ),
             z=c(2,3,4,NA, 5,10,22,34,58,7 ),
             k=rep("A",10))


df
#> # A tibble: 10 x 5
#>        x     y     w     z k    
#>    <int> <int> <dbl> <dbl> <chr>
#>  1     1   101     6     2 A    
#>  2     2   102    NA     3 A    
#>  3     3   103     4     4 A    
#>  4     4   104    NA    NA A    
#>  5     5   105     5     5 A    
#>  6     6   106     0    10 A    
#>  7     7   107    NA    22 A    
#>  8     8   108     4    34 A    
#>  9     9   109     8    58 A    
#> 10    10   110    17     7 A


df %>% mutate(across(where(is.numeric), ~.x*2))
#> # A tibble: 10 x 5
#>        x     y     w     z k    
#>    <dbl> <dbl> <dbl> <dbl> <chr>
#>  1     2   202    12     4 A    
#>  2     4   204    NA     6 A    
#>  3     6   206     8     8 A    
#>  4     8   208    NA    NA A    
#>  5    10   210    10    10 A    
#>  6    12   212     0    20 A    
#>  7    14   214    NA    44 A    
#>  8    16   216     8    68 A    
#>  9    18   218    16   116 A    
#> 10    20   220    34    14 A


##now double the value of all the columns without NA. How to fix this...

df %>% mutate(across(where(sum(is.na(.x))==0), ~.x*2))
#> Error: Problem with `mutate()` input `..1`.
#> ✖ object '.x' not found
#> ℹ Input `..1` is `across(where(sum(is.na(.x)) == 0), ~.x * 2)`.

reprex package (v0.3.0.9001) 于 2020 年 10 月 27 日创建

【问题讨论】:

    标签: r dplyr across


    【解决方案1】:

    这是您正在寻找的单线

    df %>% mutate(across(where(~is.numeric(.) && all(!is.na(.))), ~.x*2))
    

    输出

    # A tibble: 10 x 5
           x     y     w     z k    
       <dbl> <dbl> <dbl> <dbl> <chr>
     1     2   202     6     2 A    
     2     4   204    NA     3 A    
     3     6   206     4     4 A    
     4     8   208    NA    NA A    
     5    10   210     5     5 A    
     6    12   212     0    10 A    
     7    14   214    NA    22 A    
     8    16   216     4    34 A    
     9    18   218     8    58 A    
    10    20   220    17     7 A 
    

    【讨论】:

    • 您的解决方案有效,这让我大吃一惊,但如果您删除 is.numeric 参数,它就会失败。我无法理解为什么 all(!is.na(.)) 不被认为是返回逻辑,但 ~is.numeric(.) &amp;&amp; all(!is.na(.)) 被认为是逻辑
    • ~all(!is.na(.)) 失败,因为它还选择了字符类型的列 k。 @SirTain
    • 哦,我明白了,我误读了我的错误文本。失败的不是列的选择,而是我试图乘以 2 的部分失败,因为我不小心选择了列 k 并且我不能将字母 A 乘以 2。
    【解决方案2】:

    请注意,目的是选择没有 NA 任何数字的列。回想一下where 的输入必须是一个函数。在您的情况下,只需:

    df %>% mutate(across(where(~is.numeric(.) & sum(is.na(.x))==0), ~.x*2))
    

    好吧,给你其他方法:

    df %>% mutate(across(where(~!anyNA(.) & is.numeric(.)), ~.*2))
    # A tibble: 10 x 5
           x     y     w     z k    
       <dbl> <dbl> <dbl> <dbl> <chr>
     1     2   202     6     2 A    
     2     4   204    NA     3 A    
     3     6   206     4     4 A    
     4     8   208    NA    NA A    
     5    10   210     5     5 A    
     6    12   212     0    10 A    
     7    14   214    NA    22 A    
     8    16   216     4    34 A    
     9    18   218     8    58 A    
    10    20   220    17     7 A
    

    如果你知道如何使用取反函数:

    df %>% mutate(across(where(~Negate(anyNA)(.) & is.numeric(.)), ~.*2))
    

    【讨论】:

    • 你的答案和 Ekoam 的答案都很完美,所以我根据个人喜好选择了一个。我忘记了,除其他外,我需要一个“~”来输入 where 的函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2020-09-21
    • 2022-08-23
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多