1

I've this data.frame. And i need to loop through every column and search for "SI", then change it for the columns name.

I have this:

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

Need to get this:

         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

My code:

I've tried this with this code:

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

But got this message:

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

So i've change the class of that column to character with this:

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

And got this message:

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

This is the result from 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
Omar Gonzales
  • 2,878
  • 7
  • 38
  • 83

2 Answers2

4

Here's a base R approach, if you want to give it a try:

# 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

Edit after comment:

The main problem with the attempted code in the 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))

is that you are trying to use mutate only on a column directly. Generally, dplyr works with data.frame-like objects and most functions in dplyr expect a data.frame-like object as the first argument. Here, it would be df, so you would need to start something like the following:

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

Or you can use the "pipe" operator (%>%) which lets you specify the data.frame first and then "pipe" it into mutate. Note however, that under the hood mutate still uses df as its first argument as displayed above. The pipe mainly makes it easier to read and allows you to create long sequences of manipulations connected by pipes. With the pipe operator it would be:

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

Also note that replace would be faster than ifelse, which is why I used it my base R approach.

talat
  • 62,625
  • 18
  • 110
  • 141
0

It should work this way:

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))

For all three columns it checks if 'SI' exists. If yes it replaces 'SI' with the column name. If no the value doesn't change.

rdatasculptor
  • 7,072
  • 7
  • 49
  • 70