0

I'm expecting the ifelse below to return multiple results, one for each row in the DF.

heuristics = 'rightsize'

vmStorage <- structure(
  list(
    Disk.Used.GB = c(
      46.14,4.38,57.89,57.79,79.34,108.49,
      42.69,5.05,24.07,627.59,24.15
      )
    ,
    Disk.Allocated.GB = c(
      74.53,14.98,78.61,75,250,
      150,74.65,100,79.51,800,50
    )
  ),
  row.names = c(NA,-11L),
  class = c("tbl_df", "tbl", "data.frame"))


ifelse(heuristics == 'exact',
       vmStorage$Disk.Allocated.GB,
       vmStorage$Disk.Used.GB * 1.25)

I'm getting [1] 57.675. I use this with DFs all the time. Feeling dense at the moment.

Paul Shearer
  • 91
  • 1
  • 6
  • FYI, there is more the the difference between `ifelse` and control-flow `if`-and-`else`: see https://stackoverflow.com/q/6668963/3358272. Long-story-short: it is not friendly to classes other than `logical`, `numeric`, `integer`, and `character`. – r2evans Aug 14 '21 at 23:57

2 Answers2

2

ifelse requires all the arguments to be of same length which obviously is not as the logical condition is of length 1. We need if/else

if(heuristics == 'exact')  vmStorage$Disk.Allocated.GB else 
         vmStorage$Disk.Used.GB * 1.25

-output

[1]  57.6750   5.4750  72.3625  72.2375  99.1750 135.6125  53.3625   6.3125  30.0875 784.4875  30.1875

i.e. if we check the output, the length is 1, which should be replicated in ifelse

> heuristics == 'exact'
[1] FALSE
> vmStorage$Disk.Allocated.GB
 [1]  74.53  14.98  78.61  75.00 250.00 150.00  74.65 100.00  79.51 800.00  50.00
> vmStorage$Disk.Used.GB * 1.25
 [1]  57.6750   5.4750  72.3625  72.2375  99.1750 135.6125  53.3625   6.3125  30.0875 784.4875  30.1875

Thus, when it checks for 'test', it returns a value FALSE, and the first element of vmStorage$Disk.Used.GB * 1.25 is selected and stops there as the condition is already evaluated. We can replicate the 'test' to do this for all elements

ifelse(rep(heuristics == 'exact', nrow(vmStorage)),
        vmStorage$Disk.Allocated.GB,
        vmStorage$Disk.Used.GB * 1.25)
[1]  57.6750   5.4750  72.3625  72.2375  99.1750 135.6125  53.3625   6.3125  30.0875 784.4875  30.1875
akrun
  • 874,273
  • 37
  • 540
  • 662
1

When you want to check the condition (i.e., test) on every element of a vector, use ifelse(). If you want to check the condition of one variable (as you do), you want to use if/else control statements (not the function)

This code is still operating on your dataframe using vectorized arithmetic:

if (heuristics == 'exact'){
   vmStorage$Disk.Allocated.GB,
} else {
   vmStorage$Disk.Used.GB * 1.25
}

Or all on one line if you prefer:

if (heuristics == 'exact') vmStorage$Disk.Allocated.GB else vmStorage$Disk.Used.GB * 1.25
akrun
  • 874,273
  • 37
  • 540
  • 662
Brigadeiro
  • 2,649
  • 13
  • 30