Helmut
★★★
avatar
Homepage
Vienna, Austria,
2015-10-27 21:06

Posting: # 15584
Views: 6,465
 

 R inferno (rant) [Software]

Hi useRs!

Sometimes this nice piece drives me nuts.

x1 <- 12
x2 <- 13
x1 < x2
[1] TRUE
     Bravo! Bravissimo!

ifelse (x1 < x2,
  cat(x1, "less than", x2, "\n"),
  cat(x1, "at least", x2, "\n"))

12 less than 13
Error in ifelse(x1 < x2, cat(x1, "less than", x2, "\n"), cat(x1, "at least",  :
  replacement has length zero
In addition: Warning message:
In rep(yes, length.out = length(ans)) :
  'x' is NULL so the result will be NULL

   What the f…k?

if (x1 < x2) {
  cat(x1, "less than", x2, "\n")
} else {
  cat(x1, "at least", x2, "\n")
}

12 less than 13
   Thank you sooo much!


Cheers,
Helmut Schütz
[image]

The quality of responses received is directly proportional to the quality of the question asked. 🚮
Science Quotes
ElMaestro
★★★

Belgium?,
2015-10-28 08:44

@ Helmut
Posting: # 15585
Views: 5,212
 

 R inferno (rant)

Haha Hötzi,

» ifelse (x1 < x2,
»   cat(x1, "less than", x2, "\n"),
»   cat(x1, "at least", x2, "\n"))
»
» 12 less than 13
» Error in ifelse(x1 < x2, cat(x1, "less than", x2, "\n"), cat(x1, "at least",  :
»   replacement has length zero
» In addition: Warning message:
» In rep(yes, length.out = length(ans)) :
»   'x' is NULL so the result will be NULL

»    What the f…k?

I agree ifelse(a,b,c) is a borderline silly function. It is in no way clear from the error message but b and c should be lean and mean variables rather than expressions. Therefore ifelse (a, do.this(blah), do.that(blah)) will only cause headache, at least as long as do.this/that(blah) doesn't return a value.
Like you I'd much prefer the classical if else construct.

I think this also goes to show that error messages should be user-friendly. If I am not mistaking only the guy who wrote the function understands that mumbo-jumbo. Preventive keelhauling would indeed seem to be a proper action to take.

I could be wrong, but...
Best regards,
ElMaestro
d_labes
★★★

Berlin, Germany,
2015-10-28 09:42

@ ElMaestro
Posting: # 15587
Views: 5,175
 

 Vectorized if

Hi Öberster Größter Meister!

» I agree ifelse(a,b,c) is a borderline silly function.

Disagree. Very handy function if vectorized if is needed. Used it myself heavily in my codes for simulations.

» Like you I'd much prefer the classical if else construct.

Typical for coders coming from C, Fortran or so relying mostly on for loops and without vector constructs :cool:.
Will not work in R if you have vectors to compare. See "R Inferno" Circle 3.2, link in my post to Helmut.

» I think this also goes to show that error messages should be user-friendly.

Full ACK. Here R is as obscure or even more obscure as other languages. See here.

Regards,

Detlew
d_labes
★★★

Berlin, Germany,
2015-10-28 09:18

@ Helmut
Posting: # 15586
Views: 5,167
 

 R inferno (without rant)

Dear Helmut,

» ifelse (x1 < x2,
»   cat(x1, "less than", x2, "\n"),
»   cat(x1, "at least", x2, "\n"))
»
» 12 less than 13
» Error in ifelse(x1 < x2, cat(x1, "less than", x2, "\n"), cat(x1, "at least",  :
»   replacement has length zero
» In addition: Warning message:
» In rep(yes, length.out = length(ans)) :
»   'x' is NULL so the result will be NULL

»    What the f…k?

Not only SAS is a beast :-D.

ifelse() is a (vectorized) function for conditional replacement / selection of values, not for conditional doing sumfink like output with cat().

From the man page of ifelse():
Usage
ifelse(test, yes, no)

Arguments
test  an object which can be coerced to logical mode.
yes   return values for true elements of test.
no    return values for false elements of test.

What is the return value of cat()?:
x <- cat("sumfink\n")
x


Gives NULL.

From the man page of cat():
Value
None (invisible NULL).


All the f#+~ing behaviour as described and documented. No reason to rant :cool:.
For some inferno <- TRUE see Patrick Burns "R Inferno" Circle 3.2 and 8.2.7


If you really need a vectorized solution (if x1, x2 are vectors) I suggest the following:
cat(ifelse(x1 < x2,
           paste0(x1, " less than ", x2),
           paste0(x1, " at least ", x2 )
          ), sep="\n")


Try it with
x1 <- c(12, 13)
x2 <- c(13, 12)


BTW: Works of course also if x1 and x2 are scalars as in your example :thumb up:.

Regards,

Detlew
Activity
 Admin contact
20,122 posts in 4,245 threads, 1,383 registered users;
online 20 (1 registered, 19 guests [including 7 identified bots]).
Forum time (Europe/Vienna): 15:57 CET

Genius is that which forces
the inertia of humanity to learn.    Henri Bergson

The Bioequivalence and Bioavailability Forum is hosted by
BEBAC Ing. Helmut Schütz
HTML5