Як перевірити, чи визначений об'єкт (змінна) в R?


294

Я хотів би перевірити, чи визначена якась змінна в R - без отримання помилки. Як я можу це зробити?

Мої спроби (невдалі):

> is.na(ooxx)
Error: object 'ooxx' not found
> is.finite(ooxx)
Error: object 'ooxx' not found

Дякую!

Відповіді:


448

Ви хочете exists():

R> exists("somethingUnknown")
[1] FALSE
R> somethingUnknown <- 42
R> exists("somethingUnknown")
[1] TRUE
R> 

3
@Gavin & Dirk, ви так приємно одне одному :) Єдине рішення полягає в тому, щоб ви кинули монету (Бернуллі з р = 0,5 :-)), хто отримає згоду! :-)
TMS

29
@tim, якщо ви знаходитесь у функції, відсутність () - це те, що ви хочете.
CousinCocaine

2
Ви можете стати трохи складнішим, якщо перевіряти елементи списку: stackoverflow.com/q/7719741
TMS

5
як щодо того, чого хотів оп - використовуючи ім’я змінної, а не лапки?
час

109

Дивіться ?exists, для деякого визначення поняття "... визначено". Напр

> exists("foo")
[1] FALSE
> foo <- 1:10
> exists("foo")
[1] TRUE

7
Ви виграєте 52 секунди :)
Дірк Еддельбуеттель

9
@DirkEddelbuettel Добре, якщо ви будете використовувати смішно довгі назви об'єктів ;-)
Гавін Сімпсон

2
хе. У мене трапляється весь час, коли я тестую приклади перед публікацією, Гевін чи Джош уже відповіли на це.
Майасаура

60

якщо ви знаходитесь у функції, відсутність () - це те, що ви хочете.

exchequer = function(x) {
    if(missing(x)){
        message("x is missing… :-(")
    }
}

exchequer()
x is missing… :-(

missingпроте працює лише для аргументів функції. Ти не можеш зробити, foo <- function(x) {missing(x); missing(y)}інакше отримаєш foo(1) > Error in missing(y) : 'missing' can only be used for arguments.
Даннід

45

Як вказували інші, ви шукаєте exists. Майте на увазі, що використання existsз іменами, використовуваними базовими пакетами R, поверне справжнє значення незалежно від того, визначили ви змінну:

> exists("data")
[1] TRUE

Щоб обійти це (як вказував Bazz; див. ?exists), Використовуйте inheritsаргумент:

> exists("data", inherits = FALSE)
[1] FALSE

foo <- TRUE
> exists("foo", inherits = FALSE)
[1] TRUE

Звичайно, якби ви хотіли шукати простори імен доданих пакетів, це також буде невдалим:

> exists("data.table")
[1] FALSE
require(data.table)
> exists("data.table", inherits = FALSE)
[1] FALSE
> exists("data.table")
[1] TRUE

Єдине, що я можу придумати, щоб обійти це - пошук у доданих пакетах, але не в базових пакетах, - це наступне:

any(sapply(1:(which(search() == "tools:rstudio") - 1L),
           function(pp) exists(_object_name_, where = pp, inherits = FALSE)))

Порівняйте заміну _object_name_з "data.table"( TRUE) проти "var"( FALSE)

(звичайно, якщо ви не в RStudio, я думаю, що перше автоматично приєднане середовище "package:stats")


2
Граючи, використовуючи аргументи, inherits = FALSEсхоже, ізолюють речі в глобальному середовищі. Це правильно звучить?
CJB

1
@Bazz ви маєте рацію; Я це відредагував у відповідь.
MichaelChirico

2
Цей коментар повинен бути вище, оскільки я використовую назву змінної "data", просто використання існувало мені спочатку мало проблем.
mzm

25

Якщо ви не хочете використовувати лапки, ви можете використовувати deparse(substitute())хитрість, яку я знайшов у прикладі розділу ?substitute:

is.defined <- function(sym) {
  sym <- deparse(substitute(sym))
  env <- parent.frame()
  exists(sym, env)
}

is.defined(a)
# FALSE
a <- 10
is.defined(a)
# TRUE

1
Ви також можете forceоцінити його у такій функції:is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
chinsoon12

1

Можуть бути ситуації, коли ви точно не знаєте назву шуканої змінної, як, наприклад, коли масив результатів був створений системою черги. Вони, можливо, можуть бути вирішені "ls" та його аргументом "pattern", який очікує регулярного вираження.

Функція "існує" може бути реалізована таким чином

exists <-function(variablename) {
   #print(ls(env=globalenv()))
   return(1==length(ls(pattern=paste("^",variablename,"$",sep=""),env=globalenv())))
}

Готуючи цю відповідь, я трохи здивувався необхідності специфікації середовища при виклику ls () зсередини функції. Тож, дякую за це, stackoverflow! Також є атрибут "all.names", який я повинен був встановити на істинне, але пропустив.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.