Làm thế nào để kiểm tra nếu đối tượng (biến) được định nghĩa trong R?


294

Tôi muốn kiểm tra xem một số biến được xác định trong R - mà không gặp lỗi. Tôi có thể làm cái này như thế nào?

Những nỗ lực của tôi (không thành công):

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

Cảm ơn!

Câu trả lời:


448

Bạn muốn exists():

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

3
@Gavin & Dirk, bạn rất tốt với nhau :) Giải pháp duy nhất là bạn tung đồng xu (Bernoulli với p = 0,5 :-)), người sẽ được chấp nhận! :-)
TMS

29
@tim nếu bạn đang ở trong một hàm, thiếu () là những gì bạn muốn.
CousinCocaine

2
Có thể khó khăn hơn một chút nếu kiểm tra các thành phần danh sách: stackoverflow.com/q/7719741
TMS

5
Điều gì về những gì op muốn - sử dụng tên biến, không phải trong dấu ngoặc kép?
tim

109

Xem ?exists, đối với một số định nghĩa của "... được xác định". Ví dụ

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

7
Bạn giành chiến thắng sau 52 giây :)
Dirk Eddelbuettel

9
@DirkEddelbuettel Chà, nếu bạn sẽ sử dụng tên đối tượng dài một cách lố bịch ;-)
Gavin Simpson

2
heh Xảy ra với tôi mọi lúc khi tôi đang thử nghiệm các ví dụ trước khi đăng, Gavin hoặc Josh đã trả lời nó.
Maiasaura

60

nếu bạn đang ở trong một hàm, thiếu () là những gì bạn muốn.

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

exchequer()
x is missing… :-(

missingTuy nhiên, chỉ hoạt động cho các đối số chức năng. Bạn không thể làm foo <- function(x) {missing(x); missing(y)}hoặc bạn sẽ nhận được foo(1) > Error in missing(y) : 'missing' can only be used for arguments.
Dannid

45

Như những người khác đã chỉ ra, bạn đang tìm kiếm exists. Hãy nhớ rằng việc sử dụng existsvới các tên được sử dụng bởi các gói cơ sở của R sẽ trả về true bất kể bạn có xác định biến hay không:

> exists("data")
[1] TRUE

Để giải quyết vấn đề này (như được chỉ ra bởi Bazz; xem ?exists), hãy sử dụng inheritsđối số:

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

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

Tất nhiên, nếu bạn muốn tìm kiếm không gian tên của các gói đính kèm, điều này cũng sẽ bị thiếu:

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

Điều duy nhất tôi có thể nghĩ ra để giải quyết vấn đề này - để tìm kiếm trong các gói đính kèm nhưng không phải trong các gói cơ sở - là như sau:

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

So sánh thay thế _object_name_bằng "data.table"( TRUE) so với "var"( FALSE)

(tất nhiên, nếu bạn không ở trên RStudio, tôi nghĩ môi trường được đính kèm tự động đầu tiên là "package:stats")


2
Chơi xung quanh, sử dụng lý lẽ inherits = FALSEdường như cô lập mọi thứ trong môi trường toàn cầu. Nghe có đúng không?
CJB

1
@Bazz bạn đúng rồi; Tôi đã chỉnh sửa điều này thành câu trả lời.
MichaelChirico

2
Nhận xét này phải cao hơn, vì tôi sử dụng tên "dữ liệu" biến, chỉ cần sử dụng tồn tại đã gây cho tôi một số rắc rối ban đầu.
mzm

25

Nếu bạn không muốn sử dụng dấu ngoặc kép, bạn có thể sử dụng deparse(substitute())mẹo mà tôi tìm thấy trong phần ví dụ của ?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
bạn cũng có thể forcehoặc đánh giá nó trong chức năng như thế này:is.defined <- function(sym) class(try(sym, TRUE))!='try-error'
chin gió12

1

Có thể có những tình huống mà bạn không biết chính xác tên của biến bạn đang tìm, như khi một mảng kết quả được tạo bởi một hệ thống xếp hàng. Chúng có thể được giải quyết bằng "ls" và "mẫu" đối số của nó mong đợi một biểu thức chính quy.

Hàm "tồn tại" có thể được thực hiện lại theo cách đó như

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

Trong khi chuẩn bị câu trả lời này, tôi hơi ngạc nhiên về sự cần thiết của đặc tả môi trường khi gọi ls () từ bên trong một hàm. Vì vậy, cảm ơn bạn vì điều đó, stackoverflow! Ngoài ra còn có một thuộc tính "all.names" mà tôi nên đặt thành đúng nhưng đã bỏ qua.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.