Mutate with custom function in R does not work

I have a data frame, containing a column called: "Frequency". Frequency has values like "Year", "Week", "Month" etc. Now I want to create a new column based on the Frequency column where Year's new corresponding value will be 1, Month's corresponding value will be 12 and Week corresponding value will be 48. I tried to make a function for this as "getValue" and tried to make a new column applying a mutation (dplyr) on that funcion. But unfortunately I am getting the following warning and all values being transformed by the value of "1".

getValue - function(input) {

          if (input == 'Year')
          {
            result - 1
          } 
          else if(input == 'Month')
          {
            result - 12
          } 
          else if(input == 'Week')
          {
            result - 48
          } 

          return(result)
        }

      Data =  mutate(gateway, YearlyHit = getValue(gateway$Frequency))
      Data

Here is the warning message I am getting -

Warning message:
In if (input == "Year") { :
  the condition has length  1 and only the first element will be used

How can I achieve the required result in R?

Topic dplyr dataframe r

Category Data Science


An alternative approach is using mutating and ifelse:

Data for minimum reproducible example:

df = tibble(
            x = 1:10,
            Frequency = c('Year','Week','Month',
            'Month','Year','Week','Year','Year',
            'Week','Month')
            )
# A tibble: 10 x 2
       x Frequency
   <int> <chr>    
 1     1 Year     
 2     2 Week     
 3     3 Month    
 4     4 Month    
 5     5 Year     
 6     6 Week     
 7     7 Year     
 8     8 Year     
 9     9 Week     
10    10 Month   

df %>% mutate(YearlyHit = ifelse(Frequency == 'Year', 1,
                  ifelse(Frequency == 'Month', 12,
                  ifelse(Frequency == 'Week', 48,NA))))

Also you can achieve this with %in% operator:

df %>% mutate(YearlyHit = ifelse(Frequency %in% 'Year', 1,
                  ifelse(Frequency %in% 'Month', 12,
                  ifelse(Frequency %in% 'Week', 48,NA))))

Or maybe this is more readable:

df %>%
  mutate(YearlyHit = 1 * (Frequency == 'Year') +
                   12 * (Frequency == 'Month')+
                   48 * (Frequency == 'Week'))
                   
# A tibble: 10 x 3
       x Frequency YearlyHit
   <int> <chr>         <dbl>
 1     1 Year              1
 2     2 Week             48
 3     3 Month            12
 4     4 Month            12
 5     5 Year              1
 6     6 Week             48
 7     7 Year              1
 8     8 Year              1
 9     9 Week             48
10    10 Month            12

The function you are passing to mutate, getValue doesn't understand vector data.

Try:

v_getValue <- Vectorize(getValue)    
Data =  mutate(gateway, YearlyHit = v_getValue(gateway$Frequency))

More detail here


Why don't you solve it in this way?

mutate(gateway, YearlyHit = case_when(Frequency == 'Year' ~ 1,
                                      Frequency == 'Month' ~ 12,
                                      Frequency == 'Week' ~ 48)
)

My question was solved by the following command:

gateway$newcol <- mapply(getValue, gateway$Frequency)

instead of:

Data =  mutate(gateway, YearlyHit = getValue(gateway$Frequency))

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.