2012-02-25 1 views
9

Dlaczego konstrukcja if-else i funkcja ifelse() zachowują się inaczej?if-else vs ifelse z listami

mylist <- list(list(a=1, b=2), list(x=10, y=20)) 

l1 <- ifelse(sum(sapply(mylist, class) != "list")==0, mylist, list(mylist)) 

l2 <- 
if(sum(sapply(mylist, class) != "list") == 0){ # T: all list elements are lists 
    mylist 
} else { 
    list(mylist) 
} 

all.equal(l1,l2) 
# [1] "Length mismatch: comparison on first 1 components" 

Odpowiedz

11

if ( cond) { yes } else { no } to struktura kontrolna. Został zaprojektowany tak, by efektować widły programistyczne, a nie przetwarzać sekwencję. Myślę, że wiele osób pochodzi z SPSS lub SAS, których autorzy wybrali "JEŻELI" do realizacji warunkowego przypisania w ramach swoich funkcji DATA lub TRANSFORM i dlatego oczekują, że R zachowa się tak samo, podczas gdy R pochodzi z tradycji programowania. Niejawne pętle for R są wbudowane w wiele funkcji wektorowych (w tym ifelse).

ifelse przyjmuje wyrażenie, które tworzy wektor wartości logicznych jako pierwszy argument. Drugi i trzeci argument muszą być wektorami o równej długości i albo pierwszy, albo drugi zostanie wybrany. Jest to podobne do poleceń SPSS/SAS IF, które mają domyślny tryb działania w wierszu.

12

Z ifelse dokumentacji:

‘ifelse’ returns a value with the same shape as ‘test’ which is 
filled with elements selected from either ‘yes’ or ‘no’ depending 
on whether the element of ‘test’ is ‘TRUE’ or ‘FALSE’. 

Więc wejście ma długość jednego więc wyjście jest obcinany do długości 1.

Można również zobaczyć ilustrowany bardziej prosty przykład:

ifelse(TRUE, c(1, 3), 7) 
# [1] 1 
+1

+1. Zastanawiam się, co kryje się za tą decyzją projektową ... – Ryogi

+0

@Dason, na niepowiązanej notatce, jeśli mówię, że mam to 'df.stats $ Mean.Result2 <- ifelse ((df.stats $ t.test.equal <= 0.05 & df.stats $ f.test> 0.05 & df.stats $ Mean.Diff <0), "Slower", 0) ' czy istnieje alternatywny sposób zapisu go przy pomocy if - else construct? czy wydajność ifelse jest lepsza od innej, jeśli konstruujesz –