Dlaczego twierdzenia R nie mogą zwracać wektorów?

Od czasu do czasu uważam, że stwierdzenia R ifelse są dość przydatne. Na przykład:

ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2

Ale jestem nieco zdezorientowany przez następujące zachowanie.

ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3

Czy to jest wybór projektu, który jest powyżej mojego paygrade?

Author: Gregor Thomas, 2009-08-26

9 answers

Dokumentacja dla ifelse stwierdza:

ifelse Zwraca wartość o tej samej kształt jako test wypełniony elementy wybrane z yes lub no w zależności od tego, czy element z test jest TRUE lub FALSE.

Ponieważ zdasz test wartości długości 1, otrzymujesz wyniki długości 1. Jeśli zdasz dłuższe wektory testowe, otrzymasz dłuższe wyniki:

> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4

Więc ifelse jest przeznaczony do konkretnego celu badania vector of booleans and returning a vector of the same length, filled with elements taken from the (vector) yes and no arguments.

Jest powszechnym nieporozumieniem, ze względu na nazwę funkcji, aby używać tego, gdy naprawdę chcesz tylko normalnej if () {} else {} konstrukcji zamiast.

 103
Author: Nathan Kitchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-27 16:35:28

Założę się, że chcesz prostej if zamiast ifelse - w R, if nie jest tylko strukturą przepływu sterowania, może zwrócić wartość:

> if(TRUE) c(1,2) else c(3,4)
[1] 1 2
> if(FALSE) c(1,2) else c(3,4)
[1] 3 4
 70
Author: Ken Williams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-18 17:27:59

Zauważ, że możesz obejść problem, jeśli przypisasz wynik wewnątrz ifelse:

ifelse(TRUE, a <- c(1,2), a <- c(3,4))
a
# [1] 1 2

ifelse(FALSE, a <- c(1,2), a <- c(3,4))
a
# [1] 3 4
 12
Author: Cath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 15:03:55

Tak, Myślę, że ifelse() jest naprawdę zaprojektowany dla, gdy masz duży długi wektor testów i chcesz odwzorować każdy z dwóch opcji. Na przykład, często robię kolory dla plot () w ten sposób:

plot(x,y, col = ifelse(x>2,  'red', 'blue'))

Jeśli miałeś duży długi wektor testów, ale chciałeś pary dla wyjść, możesz użyć sapply() lub plyr ' S llply() lub czegoś takiego, być może.

 9
Author: Brendan OConnor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-28 20:30:22

Użyj `if", np.

> `if`(T,1:3,2:4)
[1] 1 2 3
 5
Author: blueskyddd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-06 16:45:13

Czasami użytkownik potrzebuje tylko switch zamiast ifelse. W takim przypadku:

condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2

(co jest kolejną opcją składni odpowiedzi Kena Williamsa)

 4
Author: agenis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 21:13:33

Oto podejście podobne do zaproponowanego przez Cath, ale może pracować z istniejącymi wstępnie przypisanymi wektorami

Opiera się na użyciu get() w ten sposób:

a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
 4
Author: bmonger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-25 20:50:08

W Twoim przypadku użycie if_else z dplyr byłoby pomocne: if_else jest bardziej rygorystyczne niż ifelse i rzuca błąd w Twoim przypadku:

library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2
 2
Author: Matifou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-20 17:21:28

Znalezione na everydropr:

ifelse(rep(TRUE, length(c(1,2))), c(1,2),c(3,4))
#>[1] 1 2

Może replikować wynik twojego stanu, aby zwrócić żądaną długość

 0
Author: SJGD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-15 02:34:07