Как поймать целое число (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'") 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.