【问题标题】:mutate_at (or across) and ifelse statementmutate_at(或cross)和ifelse语句
【发布时间】:2020-10-13 14:36:04
【问题描述】:

类似于这个question,给定tmpp

library(data.table)
library(tidyverse)
tmpp <- data.table(
  "ID" = c(1,1,1,2,2), 
  "Date" = c(1,2,3,1,2), 
  "total_neg" = c(1,1,0,0,2),
  "total_pos" = c(4,5,2,4,5),
  "H1" = c(5,4,0,5,-5),
  "H2" = c(5,-10,5,5,-5),
  "H3" = c(-10,6,5,0,10)
)
tmpp
#    ID Date total_neg total_pos H1  H2  H3
# 1:  1    1         1         4  5   5 -10
# 2:  1    2         1         5  4 -10   6
# 3:  1    3         0         2  0   5   5
# 4:  2    1         0         4  5   5   0
# 5:  2    2         2         5 -5  -5  10

我想用NA 替换所有以H 开头的变量,其中total_neg == 1

#    ID Date total_neg total_pos H1  H2  H3
# 1:  1    1         1         4  NA NA NA
# 2:  1    2         1         5  NA NA NA
# 3:  1    3         0         2  0   5   5
# 4:  2    1         0         4  5   5   0
# 5:  2    2         2         5 -5  -5  10

为什么这些不起作用?

tmpp %>%
  mutate_at(vars(matches("H")), ~ifelse( .$total_neg == 1, NA, .))

tmpp %>%
  mutate_at(vars(matches("H"),
            .funs = list(~ ifelse(.$total_neg == 1, NA, .))))
#im guessing the first dot in the ifelse statements above is referring to the H columns so I tried:
tmpp %>%
  mutate_at(vars(matches("H"),
                 .funs = list(~ ifelse(tmpp$total_neg == 1, NA, .))))

也很高兴看到across 版本,谢谢

【问题讨论】:

  • 对于您的第一个选项,只需删除 .$...所以它将是 mutate_at(vars(matches("H")), ~ ifelse(total_neg == 1, NA, .))。但是既然你定义了一个data.table,为什么不自始至终使用data.table方法呢?

标签: r dplyr


【解决方案1】:

一个简单的 data.table 解决方案,一次就地更新所有列,仅针对子集

tmpp[total_neg == 1, grep("^H", names(tmpp)) := NA]
tmpp
#    ID Date total_neg total_pos H1 H2 H3
# 1:  1    1         1         4 NA NA NA
# 2:  1    2         1         5 NA NA NA
# 3:  1    3         0         2  0  5  5
# 4:  2    1         0         4  5  5  0
# 5:  2    2         2         5 -5 -5 10

【讨论】:

    【解决方案2】:

    您不需要在dplyr 管道中使用$。在mutate_at/across 中,它指的是列值。试试看:

    library(dplyr)
    tmpp %>% mutate(across(starts_with('H'), ~replace(., total_neg == 1, NA)))
    
    #   ID Date total_neg total_pos H1 H2 H3
    #1:  1    1         1         4 NA NA NA
    #2:  1    2         1         5 NA NA NA
    #3:  1    3         0         2  0  5  5
    #4:  2    1         0         4  5  5  0
    #5:  2    2         2         5 -5 -5 10
    

    【讨论】:

      【解决方案3】:

      您的猜测是正确的:在 purrr 样式的匿名函数内部(在您的 ~ 之后),. 指的是函数参数,它是一个单列,而不是您的数据框管道输入。解决方案是通过删除 .$ 来简化。

      tmpp %>%
        mutate_at(vars(matches("H")), ~ifelse(total_neg == 1, NA, .))
      #    ID Date total_neg total_pos H1 H2 H3
      # 1:  1    1         1         4 NA NA NA
      # 2:  1    2         1         5 NA NA NA
      # 3:  1    3         0         2  0  5  5
      # 4:  2    1         0         4  5  5  0
      # 5:  2    2         2         5 -5 -5 10
      

      如果你想修改“所有以H开头的变量”,我强烈建议使用starts_with("H")而不是matches("H")

      【讨论】:

        【解决方案4】:

        也许您可以在across() 中使用starts_with()。代码如下:

        library(data.table)
        library(tidyverse)
        tmpp <- data.table(
          "ID" = c(1,1,1,2,2), 
          "Date" = c(1,2,3,1,2), 
          "total_neg" = c(1,1,0,0,2),
          "total_pos" = c(4,5,2,4,5),
          "H1" = c(5,4,0,5,-5),
          "H2" = c(5,-10,5,5,-5),
          "H3" = c(-10,6,5,0,10)
        )
        #Code
        tmpp %>% 
          mutate(across(starts_with('H'),~ifelse(total_neg==1,NA,.)))
        

        输出:

           ID Date total_neg total_pos H1 H2 H3
        1:  1    1         1         4 NA NA NA
        2:  1    2         1         5 NA NA NA
        3:  1    3         0         2  0  5  5
        4:  2    1         0         4  5  5  0
        5:  2    2         2         5 -5 -5 10
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-31
          • 1970-01-01
          • 2013-08-03
          • 1970-01-01
          • 1970-01-01
          • 2017-07-22
          相关资源
          最近更新 更多