Reputation: 325
I'm trying to write a function that returns "Fail" if all 3 valves at a given location (x) are open (1), but returns "Pass" if any valve is closed (0). My code is below, but it doesn't work and I get the error---unexpected 'else' in:"else"--- And I can't figure out where my code is wrong.
systemFail <- function(x) {
if(df$valveOne[df$location == x] == 1) {
if(df$valveTwo[df$location == x] == 1) {
if(df$valveThree[df$location == x] == 1) {
print("Fail")}}}
else {
print ("Pass")}
else {
Print("Pass")}
else {
Print("Pass")}
}
Upvotes: 0
Views: 69
Reputation: 16876
Here's a possibility that may work better (although unsure about structure of your data).
library(dplyr)
# Sample data.
df <- structure(
list(
location = 1:8,
valveOne = c(0, 0, 0, 0, 1, 1, 1, 1),
valveTwo = c(0, 0, 1, 1, 0, 1, 1, 1),
valveThree = c(0, 1, 0, 1, 0, 1, 0, 1)), class = "data.frame", row.names = c(NA,-8L))
systemFail <- function(x, y) {
station <- x %>%
dplyr::filter(location == y) %>%
mutate(sum = sum(across(starts_with("valve")), na.rm = T))
if (station$sum == 3) {
message("FAIL")
} else {
message("PASS")
}
}
An alternative is put your data into a long format with tidyr
.
# Put data into long format.
df2 <- df %>%
tidyr::pivot_longer(!location, names_to = "valve", values_to = "value")
# x is your dataframe, and y is the location of the valve.
systemFail <- function(x, y) {
station <- x %>%
dplyr::filter(location == y)
if (all(station$value == 1) == TRUE) {
message("FAIL")
} else {
message("PASS")
}
}
systemFail(df2, 2)
# PASS
systemFail(df2, 8)
# FAIL
Upvotes: 0
Reputation: 1
You can also do it like this:
df <- data.frame(location=1:8,
valveOne=c(0,0,0,0,1,1,1,1),
valveTwo=c(0,0,1,1,0,0,1,1),
valveThree=c(0,1,0,1,0,1,0,1))
SystemFail <- function(x) {
ifelse((df$valveOne==1 & df$valveTwo==1 & df$valveThree==1)[df$location==x],"Fail","Pass")
}
df$SystemFail <- ifelse((df$valveOne==1 & df$valveTwo==1 & df$valveThree==1),"Fail","Pass")
The last line shows how to calculate all the values at once.
Upvotes: 0
Reputation: 263481
I think you had too many closing curley-braces at the innermost if-else, and not enough of them at the outer levels:
Try:
systemFail <- function(x) {
if(df$valveOne[df$location == x] == 1) {
if(df$valveTwo[df$location == x] == 1) {
if(df$valveThree[df$location == x] == 1) { print("Fail")}
else { print ("Pass") } }
else { print("Pass") } }
else {print("Pass")} }
Wait.... that doesn't make sense. Why would there be a single "location" column for three different valves. Instead it should be:
df <- data.frame( valve2loc= sample(0:1,20, repl=TRUE),
valve2loc= sample(0:1,20, repl=TRUE),
valve3loc= sample(0:1,20, repl=TRUE))
So three valves with three open/close values let you decide whether all are open:
df$pass_fail <- c("Pass","Fail")[ 1+ (rowSums(df)==3)]
That is a vectorized operation that calculated the sum of valve location values, determines where they are all "1" and if so adds one to the logical 0/1 Boolean result, which is then used as an index for the two possible results. (R is 1 based on indexing so need to add 1 to logical values (0/1) to make them useful for indexing another 2-valued vector.)
Upvotes: 1