如何让`d$y`触发与`with(d,y)`相同的报错终止行为?
问题场景
当访问数据框不存在的列时,$操作符默认返回NULL,但with()函数会直接抛出错误终止执行,示例如下:
> d <- data.frame( x=rnorm(20) ) > d$y NULL > with(d,y) Error in eval(substitute(expr), data, enclos = parent.frame()) : object 'y' not found
需求是无需重写已有代码,让d$y始终触发与with(d,y)一致的报错终止行为。
实现方法
全局修改所有数据框的$行为
通过重载data.frame类的S3方法$.data.frame,添加列存在性检查,不存在则抛出错误:
# 重载data.frame的$操作符 `$.data.frame` <- function(x, name) { if (!name %in% colnames(x)) { stop(sprintf("object '%s' not found", name), call. = FALSE) } # 调用原始的$方法处理存在的列 NextMethod() }
测试效果:
> d <- data.frame(x = rnorm(20)) > d$y Error: object 'y' not found
此方法会全局改变所有data.frame对象的$操作行为,所有访问不存在列的操作都会报错。
仅针对特定数据框生效
如果不想影响全局数据框,可以自定义一个继承自data.frame的类,只为该类重载$操作符:
# 创建自定义安全数据框构造函数 safe_df <- function(df) { stopifnot(is.data.frame(df)) class(df) <- c("safe_df", "data.frame") df } # 为safe_df类重载$操作符 `$.safe_df` <- function(x, name) { if (!name %in% colnames(x)) { stop(sprintf("object '%s' not found", name), call. = FALSE) } # 调用父类的$方法 NextMethod() }
使用示例:
# 将普通数据框转为安全数据框 d <- safe_df(data.frame(x = rnorm(20))) # 访问不存在的列会报错 d$y # 输出:Error: object 'y' not found # 普通数据框不受影响 normal_d <- data.frame(x = rnorm(20)) normal_d$y # 返回NULL
内容的提问来源于stack exchange,提问作者ivo Welch
相关产品推荐
相关产品推荐

