将spec_tbl_df转换为自定义S4对象时遇错误,求解决方案
解决S3对象转自定义S4对象的错误问题
错误原因
直接将spec_tbl_df(属于S3类层次)传入自定义S4类的构造函数时,因为你的LongitudinalData类并未实现对该S3类的兼容映射,构造函数无法自动将S3对象的内容分配到S4的slot中,因此报错。
解决方案
方案1:直接按slot传入对应数据
最简单的方式是提取原数据框的每一列,逐个传入S4构造函数:
Make_LD <- setClass("LongitudinalData", slots = c(id = "numeric", visit = "numeric", room = "character", value = "numeric", timepoint = "numeric")) # 提取数据列并构造S4对象 x <- Make_LD(id = data$id, visit = data$visit, room = data$room, value = data$value, timepoint = data$timepoint)
方案2:自定义初始化方法支持直接传入data.frame类对象
如果希望直接传入原数据对象,可定义S4类的初始化方法,自动处理S3数据框的slot赋值:
Make_LD <- setClass("LongitudinalData", slots = c(id = "numeric", visit = "numeric", room = "character", value = "numeric", timepoint = "numeric")) # 为LongitudinalData类添加初始化方法 setMethod("initialize", "LongitudinalData", function(.Object, data) { if (!missing(data) && inherits(data, "data.frame")) { # 将data中的列映射到S4对象的slot .Object@id <- data$id .Object@visit <- data$visit .Object@room <- data$room .Object@value <- data$value .Object@timepoint <- data$timepoint } return(.Object) }) # 现在可直接传入原数据对象构造S4对象 x <- Make_LD(data)
方案3:让S4类继承S3类(保留原S3特性)
如果需要你的S4对象同时兼容S3数据框的操作,可先注册S3类层次,再让S4类继承:
# 注册S3类的完整层次 setOldClass(c("spec_tbl_df", "tbl_df", "tbl", "data.frame")) # 定义继承data.frame的S4类 Make_LD <- setClass("LongitudinalData", slots = c(id = "numeric", visit = "numeric", room = "character", value = "numeric", timepoint = "numeric"), contains = "data.frame") # 同样需要初始化方法来同步slot与数据框内容 setMethod("initialize", "LongitudinalData", function(.Object, data) { if (!missing(data) && inherits(data, "data.frame")) { .Object <- callNextMethod(.Object, data) # 同步自定义slot .Object@id <- data$id .Object@visit <- data$visit .Object@room <- data$room .Object@value <- data$value .Object@timepoint <- data$timepoint } return(.Object) }) x <- Make_LD(data)
注:这种方式下的对象依然是S4对象,可通过isS4(x)验证,并非转为S3对象。
内容的提问来源于stack exchange,提问作者PhDavey
相关产品推荐
相关产品推荐

