我正在尝试创建一个简单的 S4 类,它允许存储所有必要的参数,以生成半确定性数据合成集,以便另一组函数起作用。
最终,我的 R 包中将调用两个函数:
getDataModel(x)
和
setDataModel(...)
setDataModel(...)
(首先)将交互地询问用户参数来定义数据生成模型(也许结构是一个更好的术语?)getDataModel(x)
将读取并解析模型对象,以供其他实际生成的函数使用吐出最终数据。 我认为我的问题是我可能试图过度模块化我的代码。
考虑这个 S4 级
setClass(
"TimefitteR_Param_List",
slots = list(
intercept_offset = "numeric",
intercept_noise = "numeric",
slope_offset = "numeric",
slope_noise = "numeric",
curvature_offset = "numeric",
curvature_noise = "numeric"
),
prototype = list(
intercept_offset = 1,
intercept_noise = 1,
slope_offset = 0,
slope_noise = 1,
curvature_offset = 0,
curvature_noise = 1
)
)
这完全按照预期工作,并在其自身调用时创建一个名为 list 的 6 个值。
但是,当我调用
document()
或 load_all()
时,下面的课程会光荣地失败
#' @include classes_param_model.R
setClass(
"TimefitteR_Data_Model",
slots = list(
vars = "list",
time_params = "list",
base_params = "TimefitteR_Param_List",
conditions_params = "list",
predictors_params = "list"
),
prototype = list(
vars = list(
time = "Time",
conditions = list(class="factor", levels = c("Control", "Intervention")),
predictors = list(
Gender = list(class="factor", levels = c("Female","Male")),
SES = list(class="factor", levels = c("Low","Moderate","High"))
)
),
time_params = list("from"=0,"length"=20,"step"=1),
base_params = "TimefitterR_Param_List",
conditions_params = "TimefitteR_Param_List",
predictors_params = list(
Gender = list("TimefitteR_Param_List"),
SES = list("TimefitteR_Param_List","TimefitteR_Param_List")
)
),
contains = "TimefitteR_Param_List"
)
! Failed to load R/classes_data_model.R
Caused by error in `makePrototypeFromClassDef()`:
! in making the prototype for class “TimefitteR_Data_Model” elements of the prototype failed to match the corresponding slot class: base_params (class "TimefitteR_Param_List" ), conditions_params (class "list" )
我追求的是一个具有这种结构的对象(比如mod)
mod
vars
time <<character>>
conditions <<factor with levels "Control" and "Intervention" by default>>
predictors <<list could be any length including NULL>>
Gender <<factor with levels "Female" & "Male" by default>>
SES <<factor with levels "Low", "Moderate", & "High" by default>>
time_params <<list of 3>>
from <<numeric default 0>>
length <<numeric default 20>>
step <<numeric default 1>>
base_params <<TimefitteR_Param_List>>
conditions_params <<list of length(conditions-1) with each element a TimefitteR_Param_List>>
conditions_params <<list of length(predictors-1) with each element a named list>>
Gender <<list of length(Gender-1) with each element a TimefitteR_Param_List>>
SES <<list of length(SES-1) with each element a TimefitteR_Param_List>>
我(可能)可以弄清楚如何通过调用
setDataModel(...)
来构建此数据结构作为返回对象(S3 对象??),但我希望使用 S4 类及其原型系统来构建这一切从简单的调用到 new("TimefitteR_Data_Model")
我认为(知道)问题在于我在原型语法中有列表列表,在插槽中有简单的非嵌套列表。但是,...
您可以从像这样的更简单的示例中汲取灵感:
setClass("param",
slots = c(a = "numeric", b = "numeric"),
prototype = list(a = 0, b = 1))
setClass("listOfParam",
contains = "list",
validity = function(object) {
class. <- getClassDef("param")
for (elt in object)
if (!is(elt, class.))
return("component is not a \"param\" object")
TRUE
})
setClass("model",
slots = c(simpleSlot = "param", nestedSlot = "listOfParam", anotherSlot = "numeric"),
validity = function(object) {
if (length(object@nestedSlot) != length(object@anotherSlot))
return("slots 'nestedSlot' and 'anotherSlot' do not have equal length")
TRUE
})
定义像listOfParam
这样的“包装”类并不是严格必要的。 上述可以实现为:
setClass("param",
slots = c(a = "numeric", b = "numeric"),
prototype = list(a = 0, b = 1))
setClass("model",
slots = c(simpleSlot = "param", nestedSlot = "list", anotherSlot = "numeric"),
validity = function(object) {
class. <- getClassDef("param")
for (elt in object@nestedSlot)
if (!is(elt, class.))
return("component of slot 'nestedSlot' is not a \"param\" object")
if (length(object@nestedSlot) != length(object@anotherSlot))
return("slots 'nestedSlot' and 'anotherSlot' do not have equal length")
TRUE
})