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 adata.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
Determine Path of the Executing Script
How to Split Data into Training/Testing Sets Using Sample Function
Selecting Data Frame Rows Based on Partial String Match in a Column
Run R Script from Command Line
Dcast Warning: 'Aggregation Function Missing: Defaulting to Length'
Combine Legends For Color and Shape into a Single Legend
Combine (Rbind) Data Frames and Create Column With Name of Original Data Frames
How to Read Multiple (Excel) Files into R
How to Assign Colors to Categorical Variables in Ggplot2 That Have Stable Mapping
How to Add Texture to Fill Colors in Ggplot2
Replace Specific Characters Within Strings
Why Is It Not Advisable to Use Attach() in R, and What Should I Use Instead
Removing All Empty Columns and Rows in Data.Frame When Rows Don't Go Away
Duplicate Columns in Spark Dataframe
How to Delete Rows Where All the Columns Are Zero
R: Error in Usemethod("Group_By_"):Applied to an Object of Class