Как поймать целое число (0)?

136

Допустим, у нас есть заявление, которое производит integer(0), например,

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

Какой самый безопасный способ поймать это?

Роман Луштрик
источник
Мне не нравится идея рассматривать это как ошибку - фактически политика R не сворачивать определенные пустые объекты помогает избежать многих потоков восстановления после ошибок и, следовательно, приводит к гораздо более чистому коду.
МБК
20
Не используйте который.
Хэдли
1
Вы можете протестировать с помощью any. Он вернет FALSE либо для, либо which(1:3==5)для 1:3==5.
IRTFM
@BondedDust Я пытался найти integer(0), который я произвел, используя whichв качестве примера.
Роман Луштрик
6
Я знаю, что это старо, но не могли бы вы, Хэдли, обрисовать в общих чертах, почему бы не использовать which? Это было бы очень полезно для меня, чтобы избежать плохого кода.
Кактус

Ответы:

162

Это способ, которым R печатает вектор нулевой длины (целое число), поэтому вы можете проверить aего на длину 0:

R> length(a)
[1] 0

Возможно, стоит переосмыслить стратегию, которую вы используете, чтобы определить, какие элементы вам нужны, но без дополнительных конкретных деталей трудно предложить альтернативную стратегию.

Гэвин Симпсон
источник
19

Если это целые числа нулевой длины , то вы хотите что-то вроде

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

Проверьте это с помощью:

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

Вы также можете использовать assertiveдля этого.

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'.
Ричи Коттон
источник
3
Вы могли бы просто использовать, !length(x)а неlength(x)==0
Джеймс
3
@Джеймс. Правда, но я не думаю, что в любом случае есть проблемы с производительностью, и length(x) == 0Lчитается мне более четко.
Ричи Коттон,
@RichieCotton. Что случилось с 0L в отличие от 0? Я пробовал погуглить, но не нашел ничего подходящего. Извините за некромантию.
eenblam
2
@Ben: добавление Lсуффикса к числу заставляет R хранить его как целое, а не как значение с плавающей запятой. См., Например, cran.r-project.org/doc/manuals/R-lang.html#Constants
Ричи Коттон
Спасибо! Это сэкономило мне время.
Андрей
12

Может быть, не по теме, но в R есть две приятные, быстрые и пустые функции для сокращения логических векторов - anyи all:

if(any(x=='dolphin')) stop("Told you, no mammals!")
МБк
источник
1
Да, было бы здорово, если бы было что-то вроде is.empty, потому что некоторые функции возвращают integer(0)вместо NAили NULL. Но пока ваш путь самый простой и работает векторно, что является большим преимуществом перед length(a).
Ufos
7

Вдохновленный ответом Андри, вы можете использовать identicalи избегать любых проблем с атрибутами, используя тот факт, что это пустой набор этого класса объекта, и объедините его с элементом этого класса:

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

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

Или в более общем плане:

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
Джеймс
источник
Это не самый простой ответ, но, безусловно, самый простой и безопасный для начинающих.
JASC
7
if ( length(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
#[1] "nothing returned for 'a'"

Во-вторых, я думаю, что любой красивее, чем 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
источник