【问题标题】:R replace only specific values and keep all others in dataframeR 仅替换特定值并将所有其他值保留在数据框中
【发布时间】:2022-11-14 07:13:09
【问题描述】:

我的代码如下所示:

library(tidyverse)
df <- read.table(header=TRUE, text='
 subject sex control q1 q2
       1   M     7.9  1  1
       2   F     6.3  2  3
       3   F     9.5  3  1
       4   M    11.5  7  6
')

df %>% mutate_all(~case_when(
                              . == 1 ~ 7,
                              . == 7 ~ 1,
                              TRUE ~ . )
                  )

我想用 7 替换所有 1,反之亦然,但保留其他所有内容。

错误指出:

错误:mutate()subject 有问题。 我subject = (structure(function (..., .x = ..1, .y = ..2, . = ..1) ...。 x 必须是双精度向量,而不是整数向量。

一个解决方案表明 TRUE ~ as.numeric(as.character(.)) ) 有效,但随后性别栏为 NA

我怎样才能解决这个问题?

编辑(添加): 一个建议是使用嵌套的 if-else,这会起作用,但我真的希望有比以下更好的解决方案: df %&gt;% mutate_all(~ifelse(. == 1, 7, ifelse(. == 7, 1, .)))

想象一长串要替换的值。

【问题讨论】:

  • 对于Sex 的所有值,您得到NA 并非不合理。您希望将 MF 映射到哪些数值?您采用的方法假定字符列中的值是数字的字符串版本 - 11.57 等。 Sex 的情况并非如此。你需要给 R 一点帮助。另外,请注意mutate_all 及其同级已被across 取代。
  • 当然,mutate_all 可以替换为 mutate(across(everything()...

标签: r dplyr tidyverse case


【解决方案1】:

您可以使用mutate_at()mutate_if() 有选择地选择要应用转换的列。

df %>% mutate_at(c(3:5), ~case_when(
   . == 1 ~ 7,
   . == 7 ~ 1,
   TRUE ~ as.numeric(.))
)

df %>% mutate_if(is.numeric, ~case_when(
   . == 1 ~ 7,
   . == 7 ~ 1,
   TRUE ~ as.numeric(.))
)

【讨论】:

    【解决方案2】:

    我会在这里使用嵌套的ifelse() 调用和lapply()

    cols <- c("q1", "q2")  # or whatever columns you want
    df[cols] <- lapply(df[cols], function(x) ifelse(x == 1, 7, ifelse(x == 7, 1, x)))
    

    【讨论】:

    • 我很欣赏这个解决方案,但我认为这不是最好的
    • 实际上,如果唯一的要求是只交换两个值,那是非常理想的。如果您需要映射多个值,那么我可能会考虑使用 case_when()
    【解决方案3】:

    您可以将 mutate_all 包装在一个函数中,以跳过字符,例如

    custom_fun <- function(x){
      if(is.integer(x)|is.numeric(x)){
        case_when(
          x == 1 ~ 7,
          x == 7 ~ 1,
          TRUE ~ as.numeric(x) 
        )
      }else{
        x
      }
    } 
    
    df %>% mutate_all(custom_fun)
    

    【讨论】:

    • 这看起来像是一个可行的解决方案,但老实说,R,你不能那么复杂!
    • 不用担心,我的 dplyr 技能不是最好的,所以我希望有一种更简洁的方法
    【解决方案4】:

    尝试这个:

    df %>% 
      mutate(across(starts_with("q"), 
                    ~ ifelse(. == 1, 7,
                             ifelse(. == 7, 1, .))
                    ))
      subject sex control q1 q2
    1       1   M     7.9  7  7
    2       2   F     6.3  2  3
    3       3   F     9.5  3  7
    4       4   M    11.5  1  6
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 2022-01-24
      • 2021-03-23
      • 2020-01-27
      • 2019-12-26
      • 1970-01-01
      相关资源
      最近更新 更多