If-Else VS Ifelse with Lists

if-else vs ifelse with lists

if ( cond) { yes } else { no } is a control structure. It was designed to effect programming forks rather than to process a sequence. I think many people come from SPSS or SAS whose authors chose "IF" to implement conditional assignment within their DATA or TRANSFORM functions and so they expect R to behave the same. SA and SPSS both have implicit FOR-loops in there Data steps. Whereas R came from a programming tradition. R's implicit for-loops are built in to the many vectorized functions (including ifelse). The lapply/sapply fucntions are the more Rsavvy way to implement most sequential processing, although they don't succeed at doing lagged variable access, especially if there are any randomizing features whose "effects" get cumulatively handled.

ifelse takes an expression that builds a vector of logical values as its first argument. The second and third arguments need to be vectors of equal length and either the first of them or the second gets chosen. This is similar to the SPSS/SAS IF commands which have an implicit by-row mode of operation.

Ifelse only returns first element of list

ifelse is for vectors, use if/else for scalar comparisons.

if(length(list1)<length(list2)) list2 else list1

#$x
#[1] 1 2 3

#$y
#[1] 4 5 6

#$z
#[1] 7 8 9

ifelse returns output of same length as the test that we are performing. length(length(list1)<length(list2)) is 1 hence the output from it is also of length 1.

else if(){} VS ifelse()

The if construct only considers the first component when a vector is passed to it, (and gives a warning)

if(sample(100,10)>50) 
print("first component greater 50")
else
print("first component less/equal 50")

The ifelse function performs the check on each component and returns a vector

ifelse(sample(100,10)>50, "greater 50", "less/equal 50")

The ifelse function is useful for transform, for instance. It is often useful to
use & or | in ifelse conditions and && or || in if.

R - if-else applied to a list

You can use lapply and transform/within. There are three possibilities:

  • a) ifelse

    lapply(myfiles, transform, V3 = ifelse(V2 > 50, V3, NA))
  • b) mathematical operators (potentially more efficient)

    lapply(myfiles, transform, V3 = NA ^ (V2 <= 50) * V3)
  • c) is.na<-

    lapply(myfiles, within, is.na(V3) <- V2 < 50)

The result

[[1]]
V1 V2 V3
1 10001 33 NA
2 30001 65 0.0991478
3 50001 54 0.1564400

[[2]]
V1 V2 V3
1 10001 62 0.085526
2 30001 74 0.153664
3 50001 71 0.102096

[[3]]
V1 V2 V3
1 10001 49 NA
2 30001 65 0.169615
3 50001 61 0.070896

Using ifelse on list

Assuming your data is in a data.frame you could use apply to loop over each row and check if any of the columns you are interested have a 1:

FatherDisease1 <- paste("n_20107_0_", 0:2, sep = "")
df$FatherCAD_0_0 <- apply(df, 1, function(x) as.integer(any(x[FatherDisease1] == 1)))

df
# n_20107_0_0 n_20107_0_1 n_20107_0_2 FatherCAD_0_0
#1 NA NA NA NA
#2 7 1 8 1
#3 4 6 1 1

Data:

df <- structure(list(n_20107_0_0 = c(NA, 7L, 4L), n_20107_0_1 = c(NA, 
1L, 6L), n_20107_0_2 = c(NA, 8L, 1L)), .Names = c("n_20107_0_0",
"n_20107_0_1", "n_20107_0_2"), row.names = c(NA, -3L), class = "data.frame")

Ifelse statement to add NA to list


t(sapply(list_i1,`length<-`,max(lengths(list_i1))))
[,1] [,2] [,3]
[1,] 35 61 NA
[2,] 2 11 13
[3,] 10 15 35
[4,] 35 44 78
[5,] 22 86 101

where

list_i1 = list(c(35,61),c(2,11,13),c(10,15,35),c(35,44,78),c(22,86,101))

Is there any difference between using multiple if statements and else if statements?

Yes, potentially. Consider this (C#, Java, whatever):

int x = GetValueFromSomewhere();

if (x == 0)
{
// Something
x = 1;
}
else if (x == 1)
{
// Something else...
}

vs this:

int x = GetValueFromSomewhere();

if (x == 0)
{
// Something
x = 1;
}
if (x == 1)
{
// Something else...
}

In the first case, only one of "Something" or "Something else..." will occur. In the second case, the side-effects of the first block make the condition in the second block true.

Then for another example, the conditions may not be mutually exclusive to start with:

int x = ...;

if (x < 10)
{
...
}
else if (x < 100)
{
...
}
else if (x < 1000)
{
...
}

If you get rid of the "else" here, then as soon as one condition has matched, the rest will too.

ifelse() and if else given different results in dplyr mutate() for a time variable

Apparently, you do not understand ifelse. It is fundamentally different from if and else. The documentation clearly says "ifelse returns a value with the same shape as test" which is a vector of length one in your example. mutate then recycles this.

Here is a simple example:

all(c(TRUE, TRUE))
#[1] TRUE
ifelse(all(c(TRUE, TRUE)), 1:2, 3:4) #test is vector of length 1
#[1] 1
ifelse(c(TRUE, FALSE), 1:2, 3:4) #test is vector of length 2
#[1] 1 4

I'd encourage you to study the source code of the ifelse function, which should make it obvious why it behaves like this.

if else in a list comprehension


>>> xs = [22, 13, 45, 50, 98, 69, 43, 44, 1]
>>> [x+1 if x >= 45 else x+5 for x in xs]
[27, 18, 46, 51, 99, 70, 48, 49, 6]

Do-something if <condition>, else do-something else.



Related Topics



Leave a reply



Submit