Jak złapać liczbę całkowitą (0)?

136

Powiedzmy, że mamy stwierdzenie, które produkuje integer(0)np

 a <- which(1:3 == 5)

Jaki jest najbezpieczniejszy sposób złapania tego?

Roman Luštrik
źródło
Nie podoba mi się pomysł traktowania tego jako błędu - w rzeczywistości polityka R polegająca na niezwijaniu pewnych pustych obiektów pomaga uniknąć wielu przepływów przywracających błędy, a tym samym prowadzi do znacznie czystszego kodu.
mbq
20
Nie używaj tego.
Hadley
1
Możesz przetestować any. Zwróci FALSE dla albo dla albo which(1:3==5)dla 1:3==5.
IRTFM
@BondedDust, który próbowałem znaleźć integer(0), który stworzyłem whichna przykładzie.
Roman Luštrik
6
Wiem, że to jest stare, ale czy mógłbyś, Hadley, nakreślić, dlaczego nie używać which? Byłoby to dla mnie bardzo pomocne, aby uniknąć złego kodu.
Cactus,

Odpowiedzi:

162

To jest sposób R na wydrukowanie wektora o zerowej długości (liczby całkowitej), więc możesz przetestować, czy ama długość 0:

R> length(a)
[1] 0

Może warto przemyśleć strategię, której używasz, aby określić, które elementy chcesz, ale bez dalszych szczegółowych szczegółów trudno jest zaproponować alternatywną strategię.

Gavin Simpson
źródło
19

Jeśli są to liczby całkowite o zerowej długości , potrzebujesz czegoś takiego

is.integer0 <- function(x)
{
  is.integer(x) && length(x) == 0L
}

Sprawdź to na:

is.integer0(integer(0)) #TRUE
is.integer0(0L)         #FALSE
is.integer0(numeric(0)) #FALSE

Możesz również użyć assertivedo tego.

library(assertive)
x <- integer(0)
assert_is_integer(x)
assert_is_empty(x)
x <- 0L
assert_is_integer(x)
assert_is_empty(x)
## Error: is_empty : x has length 1, not 0.
x <- numeric(0)
assert_is_integer(x)
assert_is_empty(x)
## Error: is_integer : x is not of class 'integer'; it has class 'numeric'.
Richie Cotton
źródło
3
Możesz po prostu użyć !length(x)zamiastlength(x)==0
James
3
@James. To prawda, ale nie sądzę, żeby w każdym razie było wiele problemów z wydajnością i length(x) == 0Lczyta mi się jaśniej.
Richie Cotton
@RichieCotton. O co chodzi z 0L w przeciwieństwie do 0? Próbowałem google, ale nie znajduję nic odpowiedniego. Przepraszam za nekromancję.
eenblam
2
@Ben: Dodanie Lsufiksu do liczby powoduje, że R przechowuje ją jako liczbę całkowitą, a nie wartość zmiennoprzecinkową. Zobacz np. Cran.r-project.org/doc/manuals/R-lang.html#Constants
Richie Cotton
Dzięki! To zaoszczędziło mi czasu.
Andrii
12

Może nie na temat, ale R ma dwie ładne, szybkie i świadome pustej funkcji do redukcji wektorów logicznych - anyi all:

if(any(x=='dolphin')) stop("Told you, no mammals!")
mbq
źródło
1
Tak, byłoby wspaniale, gdyby było coś takiego is.empty, ponieważ niektóre funkcje zwracają się integer(0)zamiast NAlub NULL. Ale na razie twoja droga jest najprostsza i działa pod względem wektorów, co jest dużą zaletą length(a).
Ufos
7

Zainspirowany odpowiedzią Andrie, możesz użyć identicali uniknąć problemów z atrybutami, wykorzystując fakt, że jest to pusty zbiór tej klasy obiektów i łącząc go z elementem tej klasy:

attr(a,"foo")<-"bar"

> identical(1L,c(a,1L))
[1] TRUE

Lub bardziej ogólnie:

is.empty <- function(x, mode=NULL){
    if (is.null(mode)) mode <- class(x)
    identical(vector(mode,1),c(x,vector(class(x),1)))
}

b <- numeric(0)

> is.empty(a)
[1] TRUE
> is.empty(a,"numeric")
[1] FALSE
> is.empty(b)
[1] TRUE
> is.empty(b,"integer")
[1] FALSE
James
źródło
To nie jest najprostsza odpowiedź, ale zdecydowanie najprostsza i najbezpieczniejsza dla początkujących.
JASC,
7
if ( length(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
#[1] "nothing returned for 'a'"

Z drugiej strony myślę, że każdy jest piękniejszy niż length(.):

 if ( any(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
 if ( any(a <- 1:3 == 5 ) ) print(a)  else print("nothing returned for 'a'") 
IRTFM
źródło