R: dplyr - 列名称的更改因子 "SI" 为 "mutate"

R: dplyr - Change factor "SI" for column name with "mutate"

我有这个data.frame。我需要遍历每一列并搜索 "SI",然后将其更改为列名。

我有这个:

SKU             Tv.y.Video  Cómputo     Tecnología
2003091090002P     NO          NO           NO
2003091090002      NO          NO           NO
2003120060006P     NO          NO           NO
2003120060006P     NO          NO           NO
2003120060006      NO          NO           NO
2004121460000P     NO          SI           NO
2004121460000      NO          SI           NO
2004121440002P     NO          SI           NO
2004121440002      NO          SI           NO
2004123030003P     NO          SI           NO

需要得到这个:

         SKU         Tv.y.Video   Cómputo       Tecnología
   2003091090002P      NO          NO           NO
   2003091090002       NO          NO           NO
   2003120060006P      NO          NO           NO
   2003120060006P      NO          NO           NO
   2003120060006       NO          NO           NO
   2004121460000P      NO          Cómputo      NO
   2004121460000       NO          Cómputo      NO
   2004121440002P      NO          Cómputo      NO
   2004121440002       NO          Cómputo      NO
   2004123030003P      NO          Cómputo      NO

我的代码:

我已经用这段代码试过了:

df$Tv.y.Video <- mutate(df$Tv.y.Video,
                Tv.y.Video = ifelse(sub("SI", Tv.y.Video), "Tv.y.Video", Tv.y.Video))

但是收到这条消息:

Error in UseMethod("mutate_") : 
  no applicable method for 'mutate_' applied to an object of class "factor"

所以我将该列的 class 更改为字符:

df$Tv.y.Video <- as.character(df$Tv.y.Video)

并收到此消息:

Error in UseMethod("mutate_") : 
  no applicable method for 'mutate_' applied to an object of class "character"

这是 str(df) 的结果:

    'data.frame':   10 obs. of  4 variables:
 $ SKU       : Factor w/ 9028 levels "2003014460004",..: 9 8 16 16 15 842 841 840 839 846
 $ Tv.y.Video: chr  "NO" "NO" "NO" "NO" ...
 $ Cómputo   : Factor w/ 2 levels "NO","SI": 1 1 1 1 1 2 2 2 2 2
 $ Tecnología: Factor w/ 2 levels "NO","SI": 1 1 1 1 1 1 1 1 1 1

如果您想尝试一下,这里有一个基本的 R 方法:

# change the class to character for all columns:
df[] <- lapply(df, as.character)
# replace SI entries with column names:
df[] <- Map(function(cols, df_names) replace(cols, which(cols == "SI"), 
               df_names), df, names(df) )
df
#              SKU Tv.y.Video C.mputo Tecnolog.a
#1  2003091090002P         NO      NO         NO
#2   2003091090002         NO      NO         NO
#3  2003120060006P         NO      NO         NO
#4  2003120060006P         NO      NO         NO
#5   2003120060006         NO      NO         NO
#6  2004121460000P         NO C.mputo         NO
#7   2004121460000         NO C.mputo         NO
#8  2004121440002P         NO C.mputo         NO
#9   2004121440002         NO C.mputo         NO
#10 2004123030003P         NO C.mputo         NO

评论后编辑:

OP 中尝试的代码的主要问题:

df$Tv.y.Video <- mutate(df$Tv.y.Video,
                Tv.y.Video = ifelse(sub("SI", Tv.y.Video), "Tv.y.Video", Tv.y.Video))

是您试图直接在列上使用 mutate。通常,dplyr 与 data.frame-like 对象一起工作,并且 dplyr 中的大多数函数都期望一个 data.frame-like 对象作为第一个参数。在这里,它将是 df,因此您需要开始如下内容:

df <- mutate(df, 
      Tv.y.Video = ifelse(Tv.y.Video == "SI", "Tv.y.Video", Tv.y.Video)
)

或者您可以使用 "pipe" 运算符 (%>%),它让您先指定 data.frame,然后将其 "pipe" 指定为 mutate。但是请注意,在引擎盖下 mutate 仍然使用 df 作为其第一个参数,如上所示。 pipe 主要使其更易于阅读,并允许您创建由管道连接的长操作序列。对于管道运算符,它将是:

df <- df %>% 
        mutate(
          Tv.y.Video = ifelse(Tv.y.Video == "SI", "Tv.y.Video", Tv.y.Video)
)

另请注意,replace 会比 ifelse 快,这就是我使用它作为基本 R 方法的原因。

它应该这样工作:

library(dplyr)
df <- mutate(df,Tv.y.Video = ifelse(Tv.y.Video=="SI",
    "Tv.y.Video",Tv.y.Video), Cómputo = ifelse(Cómputo=="SI", "Cómputo",Cómputo),
    Cómputo = ifelse(Tecnología=="SI", "Tecnología",Tecnología))

对于所有三列,它检查 'SI' 是否存在。如果是,它将 'SI' 替换为列名。如果否,则该值不会更改。