Why ifelse with character statement is not working?

Viewed 106

I am having problem today to understand how functions works.

This is my code:

my_fun<- function(x){
        ifelse(as.character(x) == 'Species',
              a<- iris %>% select(x),
              a<- iris*2)
        
        a
}

my_fun(x = Species)

Why is it not working?

3 Answers

There are three changes to be made,

  1. converting to character would be with deparse/substitute

  2. if/else would be appropriate as ifelse requires all the arguments to be of same length

  3. iris * 2 as an else option wouldn't work as the dataset includes a factor column as well. So, we need to multiply only those numeric columns

    my_fun <- function(x) {               
             x <- deparse(substitute(x))
             if(x == 'Species') {
                 iris %>% 
                   select(all_of(x)) 
               } else {
                    iris  %>%
                     mutate(across(where(is.numeric), ~ .* 2))
             }
      }
    

-testing

my_fun(Species)
#       Species
#1       setosa
#2       setosa
#3       setosa
#4       setosa
#5       setosa
#6       setosa
#...
     

and if we pass another input

my_fun(hello)
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#1           10.2         7.0          2.8         0.4     setosa
#2            9.8         6.0          2.8         0.4     setosa
#3            9.4         6.4          2.6         0.4     setosa
#4            9.2         6.2          3.0         0.4     setosa
#5           10.0         7.2          2.8         0.4     setosa
#6           10.8         7.8          3.4         0.8     setosa
# ...
library(tidyverse)
my_fun <- function(x) {
  if(x == "Species") {
    iris %>% select(x)
  } else {
     iris * 2
  }
}

my_fun("Species")

Why?

You have an error because Species when evaluated is not found since it was not a defined variable.

One can use Non Standard Evaluation (NSE) feature with deparse and substitute see @akrun answer. But maybe you want to call your function with a character like that my_fun("Species").

The other mistake is that ifelse is a vectorized version of if/else and here you just want to test one value (x).

If you would like to ifelse anyway, here is a variation base on answers by @akrun and @pietrodito

my_fun <- function(x) {
  x <- deparse(substitute(x))
  ifelse(x == "Species",
    a <- list(iris %>% select(x)),
    a <- list(iris * 2)
  )
  a[[1]]
}

which gives

> my_fun(Species)
       Species
1       setosa
2       setosa
3       setosa
4       setosa
5       setosa
6       setosa
7       setosa
8       setosa
9       setosa
10      setosa
11      setosa
12      setosa
13      setosa
14      setosa
15      setosa
16      setosa
17      setosa
18      setosa
19      setosa
20      setosa
21      setosa
22      setosa
23      setosa
24      setosa
25      setosa
26      setosa
27      setosa
28      setosa
29      setosa
30      setosa
31      setosa
32      setosa
33      setosa
34      setosa
35      setosa
36      setosa
37      setosa
38      setosa
39      setosa
40      setosa
41      setosa
42      setosa
43      setosa
44      setosa
45      setosa
46      setosa
47      setosa
48      setosa
49      setosa
50      setosa
51  versicolor
52  versicolor
53  versicolor
54  versicolor
55  versicolor
56  versicolor
57  versicolor
58  versicolor
59  versicolor
60  versicolor
61  versicolor
62  versicolor
63  versicolor
64  versicolor
65  versicolor
66  versicolor
67  versicolor
68  versicolor
69  versicolor
70  versicolor
71  versicolor
72  versicolor
73  versicolor
74  versicolor
75  versicolor
76  versicolor
77  versicolor
78  versicolor
79  versicolor
80  versicolor
81  versicolor
82  versicolor
83  versicolor
84  versicolor
85  versicolor
86  versicolor
87  versicolor
88  versicolor
89  versicolor
90  versicolor
91  versicolor
92  versicolor
93  versicolor
94  versicolor
95  versicolor
96  versicolor
97  versicolor
98  versicolor
99  versicolor
100 versicolor
101  virginica
102  virginica
103  virginica
104  virginica
105  virginica
106  virginica
107  virginica
108  virginica
109  virginica
110  virginica
111  virginica
112  virginica
113  virginica
114  virginica
115  virginica
116  virginica
117  virginica
118  virginica
119  virginica
120  virginica
121  virginica
122  virginica
123  virginica
124  virginica
125  virginica
126  virginica
127  virginica
128  virginica
129  virginica
130  virginica
131  virginica
132  virginica
133  virginica
134  virginica
135  virginica
136  virginica
137  virginica
138  virginica
139  virginica
140  virginica
141  virginica
142  virginica
143  virginica
144  virginica
145  virginica
146  virginica
147  virginica
148  virginica
149  virginica
150  virginica
Related