Vectorized If Statement in R

Vectorized IF statement in R?

x <- seq(0.1,10,0.1)

> x
[1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5
[16] 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0
[31] 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5
[46] 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0
[61] 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5
[76] 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0
[91] 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0

> ifelse(x < 5, 1, 2)
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[38] 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
[75] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

R - vectorized if for multiple conditions

How about this?

It's the same function as above, but without the explicit if and else?

> Teff=seq(30,40,1)
> hsa<- 1*(Teff<Tcr) + (1 - (Teff - Tcr)/(Tlim - Tcr))*(Teff >= Tcr & Teff < Tlim)
> hsa
[1] 1.0000000 1.0000000 1.0000000 1.0000000 0.8571429 0.7142857 0.5714286 0.4285714 0.2857143 0.1428571 0.0000000

** Note that you can add + 0*(Teff>=Tlim) in the end, but it wouldn't change anything, because the assigned value would be 0 anyways.

If you really want to use ifelse, then you have to nest them, so it should be something like this:

> hsa<- ifelse(Teff<Tcr, 1,
ifelse(Teff >= Tcr & Teff < Tlim,
(1 - (Teff - Tcr)/(Tlim - Tcr)), 0))
> hsa
[1] 1.0000000 1.0000000 1.0000000 1.0000000 0.8571429 0.7142857 0.5714286 0.4285714 0.2857143 0.1428571 0.0000000

Vectorized 'if' statement without 'ifelse'

To summarize the info I got in this thread, the answer to my first problem was 'don't try to set values inside of an ifelse(), use ifelse() to return a value and set it that way.

The second problem I was having with the else portion of my statement overwriting previous statements, the answer was maddeningly simple: just return the current value. So the following

df$flag <- ifelse((df$year==2011 | df$year==2012) & df$code==df2$yes_code &
df$year==df2$year, 'Y', 'N')

becomes this

df$flag <- ifelse((df$year==2011 | df$year==2012) & df$code==df2$yes_code &
df$year==df2$year, 'Y', df$flag)

Thanks to all who helped, this was a very difficult question to articulate.

R how to vectorize a function with multiple if else conditions

Here is a vectorized way. It creates logical vectors i1, i2, i3 and i4 corresponding to the 4 conditions. Then it assigns the new values to the positions indexed by them.

Trial_func2 <- function(df1){
i1 <- df1[["Obs_Type"]] == 1
i2 <- df1[["Obs_Type"]] == 2
i3 <- df1[["Obs_Type"]] == 3
i4 <- df1[["Obs_Type"]] == 4

#If Type == 1; then a=-Inf, b = Upper_Bound
df1[i1, "draw_value"] <- rtruncnorm(sum(i1), a =-Inf,
b = df1[i1, "Upper_bound"],
mean = df1[i1, "mean"], sd = 1)
#If Type == 2; then a=-10, b = Upper_Bound
df1[i2, "draw_value"] <- rtruncnorm(sum(i2), a = -10,
b = df1[i2 , "Upper_bound"],
mean = df1[i2, "mean"], sd = 1)
#If Type == 3; then a=Lower_bound, b = Inf
df1[i3,"draw_value"] <- rtruncnorm(sum(i3),
a = df1[i3, "Lower_bound"],
b = Inf, mean = df1[i3, "mean"],
sd = 1)
#If Type == 3; then a=Lower_bound, b = 10
df1[i4, "draw_value"] <- rtruncnorm(sum(i4),
a = df1[i4, "Lower_bound"],
b = 10,
mean = df1[i4,"mean"],
sd = 1)
df1
}

In the speed test I have named @Dave2e's answer Trial_func3.

mbm <- microbenchmark(
loop = Trial_func(df1 = df1),
vect = Trial_func2(df1 = df1),
cwhen = Trial_func3(df1 = df1),
times = 10)

print(mbm, order = "median")
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# vect 4.349444 4.371169 4.40920 4.401384 4.450024 4.487453 10 a
# cwhen 13.458946 13.484247 14.16045 13.528792 13.787951 19.363104 10 a
# loop 2125.665690 2138.792497 2211.20887 2157.185408 2201.391083 2453.658767 10 b

Using if/ifelse statement with vector conditions in R

You can also do a normal if statement, since it returns a value:

my_result = if(all(Vector1 == c(T,T,T))) {"Combo1"} else {"Combo2"}

The ifelse function is made for vectorized conditional statements.

By using the standard if statement, you remove potential ambiguity/misinterpretation because the standard if only evaluates one condition.

Vectorized IF statement combined with logic AND in R

b <- ifelse(a==1 & b<1, 1, b)

Create a vector using if...else if...else statements in R

Here's a couple of ways to do it:

the most analogous to your existing method is:

X <- ifelse(MATRIX$Col1==1,
ifelse(MATRIX$Col2==1,"both","col1"),
ifelse(MATRIX$Col2==1,"col2","none"))

It can be slightly quicker to do:

x <- rep(NA,nrow(MATRIX))
x[MATRIX$Col1[i]==1 && MATRIX$Col2[i]==1] <- "both"
x[MATRIX$Col1[i]==1 && !MATRIX$Col2[i]==1] <- "col1"
x[!MATRIX$Col1[i]==1 && MATRIX$Col2[i]==1] <- "col2"
x[!MATRIX$Col1[i]==1 && !MATRIX$Col2[i]==1] <- "none"

but it's harder to see whether all cases have been covered by the code

Note:

  • It looks like MATRIX really is a data.frame; learning to be
    precise about you data types can really help when debugging code.
  • If MATRIX$Col1 really is Boolean, you can drop the ==1 comparison,
    that's wasting time by converting the matrix to numeric and then
    testing for equality.
  • To me, the most transparant method is to create
    a small data.frame with the possible values of Col1, Col2 and
    expected output, and merge this with the existing data.frame, but
    this may not be as efficient.


Related Topics



Leave a reply



Submit